You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
646 lines
15 KiB
646 lines
15 KiB
package goods
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"recook/internal/api/manage/excel"
|
|
"recook/internal/back"
|
|
"recook/internal/dbc"
|
|
"recook/internal/model/freight"
|
|
"recook/internal/model/goods"
|
|
"recook/internal/static_path"
|
|
"recook/tools"
|
|
"strconv"
|
|
"unicode/utf8"
|
|
|
|
"github.com/360EntSecGroup-Skylar/excelize/v2"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
type updatePromotionPhotoParam struct {
|
|
GoodsID uint `json:"goodsID" validate:"required"`
|
|
Width uint `json:"width" validate:"required"`
|
|
Height uint `json:"height" validate:"required"`
|
|
URL string `json:"url" validate:"required"`
|
|
}
|
|
|
|
type updateGoodsPhotosParam struct {
|
|
UserID uint `json:"userId" validate:"required"`
|
|
GoodsID uint `json:"goodsId" validate:"required"`
|
|
PhotoPaths []string `json:"photoPaths" validate:"required"`
|
|
}
|
|
|
|
type updateGoodsVideoParam struct {
|
|
UserID uint `json:"user_id" validate:"required"`
|
|
GoodsID uint `json:"goods_id" validate:"required"`
|
|
VideoPath string `json:"video_path" validate:"required"`
|
|
}
|
|
type deleteGoodsVideoParam struct {
|
|
GoodsID uint `json:"goods_id" validate:"required"`
|
|
}
|
|
|
|
type updateGoodsAbstractParam struct {
|
|
UserId uint `json:"user_id" validate:"required"`
|
|
GoodsId uint `json:"goods_id" validate:"required"`
|
|
UpdateField uint `json:"update_field" validate:"required"`
|
|
Value interface{} `json:"value" validate:"required"`
|
|
}
|
|
|
|
type changeGoodsPhotoParam struct {
|
|
UserId uint `json:"user_id" validate:"required"`
|
|
GoodsId uint `json:"goods_id" validate:"required"`
|
|
OriginPath string `json:"origin_path" validate:"required"`
|
|
ChangePath string `json:"change_path" validate:"required"`
|
|
Width uint `json:"width" validate:"required"`
|
|
Height uint `json:"height" validate:"required"`
|
|
}
|
|
|
|
func UpdateGoodsAbstractInfo(c *gin.Context) {
|
|
var p updateGoodsAbstractParam
|
|
if err := tools.Params(&p, c); err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var info goods.Information
|
|
if err := dbc.DB.First(&info, "id = ?", p.GoodsId).Error; err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
if p.UpdateField == 1 {
|
|
v := p.Value.(string)
|
|
if utf8.RuneCountInString(v) > 35 {
|
|
back.Fail(c, "商品名称不超过35个字符")
|
|
return
|
|
}
|
|
if utf8.RuneCountInString(v) < 5 {
|
|
back.Fail(c, "商品名称符不少于5个字")
|
|
return
|
|
}
|
|
if err := dbc.DB.Model(&info).Updates(goods.Information{GoodsName: v}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
back.Suc(c, "", nil)
|
|
} else if p.UpdateField == 2 {
|
|
v := p.Value.(string)
|
|
if utf8.RuneCountInString(v) > 30 {
|
|
back.Fail(c, "商品描述不超过30个字符")
|
|
return
|
|
}
|
|
if err := dbc.DB.Model(&info).Updates(map[string]interface{}{"description": v}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
back.Suc(c, "", nil)
|
|
} else if p.UpdateField == 3 {
|
|
|
|
} else if p.UpdateField == 4 {
|
|
|
|
} else if p.UpdateField == 5 {
|
|
v := p.Value.(float64)
|
|
if v < 0 {
|
|
back.Fail(c, "参数错误")
|
|
return
|
|
}
|
|
if v > 1000 {
|
|
back.Fail(c, "最大支持1000")
|
|
return
|
|
}
|
|
if err := dbc.DB.Model(&info).Updates(map[string]interface{}{"weight": v}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
back.Suc(c, "", nil)
|
|
} else {
|
|
back.Fail(c, "参数错误")
|
|
}
|
|
}
|
|
|
|
func UpdateGoodsPromotionPhoto(c *gin.Context) {
|
|
var p updatePromotionPhotoParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var photo goods.PromotionPhoto
|
|
err = dbc.DB.First(&photo, "goods_id = ?", p.GoodsID).Error
|
|
if err != nil && gorm.IsRecordNotFoundError(err) == false {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
if gorm.IsRecordNotFoundError(err) {
|
|
photo = goods.PromotionPhoto{
|
|
GoodsID: p.GoodsID,
|
|
URL: p.URL,
|
|
Width: p.Width,
|
|
Height: p.Height,
|
|
}
|
|
err = dbc.DB.Create(&photo).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
} else {
|
|
err = dbc.DB.Model(&photo).Updates(goods.PromotionPhoto{
|
|
URL: p.URL,
|
|
Width: p.Width,
|
|
Height: p.Height,
|
|
}).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
|
|
back.Suc(c, "操作成功", nil)
|
|
}
|
|
|
|
/*
|
|
更新商品详情图片顺序
|
|
*/
|
|
func UpdateDetailPhotoOrder(c *gin.Context) {
|
|
var p updateGoodsPhotosParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var arr []goods.DetailPhoto
|
|
err = dbc.DB.Find(&arr, "goods_id = ?", p.GoodsID).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
// 先验证。不要走数据库
|
|
for _, v1 := range arr {
|
|
// 遍历找到该图的顺序
|
|
var odr = -1
|
|
for j, v2 := range p.PhotoPaths {
|
|
if v1.URL == v2 {
|
|
odr = j
|
|
break
|
|
}
|
|
}
|
|
|
|
if odr == -1 {
|
|
back.Fail(c, "参数不正确,不能完全匹配")
|
|
return
|
|
}
|
|
}
|
|
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
for i, v1 := range arr {
|
|
// 遍历找到该图的顺序
|
|
for j, v2 := range p.PhotoPaths {
|
|
if v1.URL == v2 {
|
|
err = tx.Model(&(arr[i])).Updates(map[string]interface{}{
|
|
"order_no": j,
|
|
}).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tx.Commit()
|
|
back.Suc(c, "操作成功", nil)
|
|
}
|
|
|
|
/*
|
|
更新商品主图顺序
|
|
*/
|
|
func UpdateMainPhotoOrder(c *gin.Context) {
|
|
var p updateGoodsPhotosParam
|
|
if err := tools.Params(&p, c); err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var photos []goods.MainPhoto
|
|
if err := dbc.DB.Find(&photos, "goods_id = ?", p.GoodsID).Error; err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
// 先验证。不要走数据库
|
|
for _, v1 := range photos {
|
|
// 遍历找到该图的顺序
|
|
var odr = -1
|
|
for j, v2 := range p.PhotoPaths {
|
|
if v1.URL == v2 {
|
|
odr = j
|
|
break
|
|
}
|
|
}
|
|
|
|
if odr == -1 {
|
|
back.Fail(c, "参数不正确,不能完全匹配")
|
|
return
|
|
}
|
|
}
|
|
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
for i1, v1 := range p.PhotoPaths {
|
|
isMaster := 0
|
|
if i1 == 0 {
|
|
isMaster = 1
|
|
}
|
|
for _, v2 := range photos {
|
|
if v1 == v2.URL {
|
|
if err := tx.Model(&v2).Updates(map[string]interface{}{
|
|
"order_no": i1,
|
|
"is_master": isMaster,
|
|
}).Error; err != nil {
|
|
back.Fail(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tx.Commit()
|
|
back.Suc(c, "操作成功", nil)
|
|
}
|
|
|
|
func ChangeGoodsMainPhoto(c *gin.Context) {
|
|
var p changeGoodsPhotoParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var mp goods.MainPhoto
|
|
err = dbc.DB.First(&mp, "url = ?", p.OriginPath).Error
|
|
if err != nil {
|
|
back.Fail(c, "不存在该图")
|
|
return
|
|
}
|
|
|
|
if mp.GoodsID != p.GoodsId {
|
|
back.Fail(c, "商品参数异常")
|
|
return
|
|
}
|
|
|
|
err = dbc.DB.Model(&mp).Updates(goods.MainPhoto{URL: p.ChangePath, Width: p.Width, Height: p.Height}).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
func ChangeGoodsDetailPhoto(c *gin.Context) {
|
|
var p changeGoodsPhotoParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var dp goods.DetailPhoto
|
|
err = dbc.DB.First(&dp, "url = ?", p.OriginPath).Error
|
|
if err != nil {
|
|
back.Fail(c, "不存在该图")
|
|
return
|
|
}
|
|
|
|
if dp.GoodsID != p.GoodsId {
|
|
back.Fail(c, "商品参数异常")
|
|
return
|
|
}
|
|
|
|
err = dbc.DB.Model(&dp).Updates(goods.MainPhoto{URL: p.ChangePath, Width: p.Width, Height: p.Height}).Error
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
func DeletedGoodsVideo(c *gin.Context) {
|
|
var p deleteGoodsVideoParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
var video goods.Video
|
|
err = dbc.DB.First(&video, "goods_id = ?", p.GoodsID).Error
|
|
if err != nil && !gorm.IsRecordNotFoundError(err) {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
if video.ID > 0 { // 更换
|
|
if video.GoodsID != p.GoodsID {
|
|
back.Err(c, "商品与视频无法匹配")
|
|
return
|
|
}
|
|
|
|
dbc.DB.Where("goods_id = ?", p.GoodsID).Delete(&video)
|
|
}
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
func UpdateGoodsVideo(c *gin.Context) {
|
|
var p updateGoodsVideoParam
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var video goods.Video
|
|
err = dbc.DB.First(&video, "goods_id = ?", p.GoodsID).Error
|
|
if err != nil && !gorm.IsRecordNotFoundError(err) {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
videoPath := filepath.Join(static_path.Dir.Root, p.VideoPath)
|
|
fileInfo, err := os.Stat(videoPath)
|
|
if err != nil && os.IsNotExist(err) {
|
|
back.Fail(c, "不存在该视频文件")
|
|
return
|
|
}
|
|
|
|
fileSize := fileInfo.Size()
|
|
duration, err := tools.ParseVideoDuration(videoPath)
|
|
if err != nil {
|
|
back.Err(c, err.Error()+"视频解析失败")
|
|
return
|
|
}
|
|
|
|
if video.ID > 0 { // 更换
|
|
if video.GoodsID != p.GoodsID {
|
|
back.Err(c, "商品与视频无法匹配")
|
|
return
|
|
}
|
|
|
|
dbc.DB.Model(&video).Updates(goods.Video{
|
|
URL: p.VideoPath,
|
|
Thumbnail: tools.GenerateVideoThumbnail(p.VideoPath),
|
|
Duration: uint(duration),
|
|
Size: float64(fileSize)/(1<<20) + 0.005,
|
|
})
|
|
} else {
|
|
video = goods.Video{
|
|
GoodsID: p.GoodsID,
|
|
URL: p.VideoPath,
|
|
Thumbnail: tools.GenerateVideoThumbnail(p.VideoPath),
|
|
Duration: uint(duration),
|
|
Size: float64(fileSize)/(1<<20) + 0.005,
|
|
}
|
|
err = dbc.DB.Create(&video).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
type updateStatus struct {
|
|
UserID uint `json:"userId" validate:"required"`
|
|
GoodsID uint `json:"goodsId" validate:"required"`
|
|
Status uint `json:"status" validate:"oneof=0 1"`
|
|
}
|
|
|
|
func UpdateGoodsPublishStatus(c *gin.Context) {
|
|
var p updateStatus
|
|
err := tools.Params(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var goodsInfo goods.Information
|
|
dbc.DB.First(&goodsInfo, p.GoodsID)
|
|
|
|
if goodsInfo.PublishStatus != p.Status {
|
|
if err = dbc.DB.Model(&goodsInfo).Updates(map[string]interface{}{
|
|
"publish_status": p.Status,
|
|
"hash": tools.GenerateGoodsHashSign(),
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
type freightParam struct {
|
|
GoodsID uint `json:"goodsId"`
|
|
FreightID uint `json:"freightId"`
|
|
}
|
|
|
|
// 更换运费模版
|
|
func UpdateGoodsFreight(c *gin.Context) {
|
|
var p freightParam
|
|
if err := tools.Params(&p, c); err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var goodsInfo goods.Information
|
|
dbc.DB.First(&goodsInfo, p.GoodsID)
|
|
|
|
if err := dbc.DB.Model(&goodsInfo).Updates(goods.Information{
|
|
FreightID: p.FreightID,
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
back.Suc(c, "", &goodsInfo)
|
|
}
|
|
|
|
// 更改商品信息
|
|
type updateGoodsInfoParam struct {
|
|
GoodsID uint `json:"goodsId" validate:"required"`
|
|
VendorID uint `json:"vendorId"`
|
|
GoodsName string `json:"goodsName" validate:"required"`
|
|
Description string `json:"description" `
|
|
Material string `json:"material" `
|
|
FirstCategoryID uint `json:"firstCategoryId" validate:"required"`
|
|
SecondCategoryID uint `json:"secondCategoryId" validate:"required"`
|
|
PublishStatus uint `json:"publishStatus"`
|
|
Weight decimal.Decimal `json:"weight"`
|
|
FreightID uint `json:"freightId" validate:"required"`
|
|
IsJoinTeamPerformance uint `json:"isJoinTeamPerformance"` // 是否参与团队业绩计算
|
|
}
|
|
|
|
func UpdateGoodsInfo(c *gin.Context) {
|
|
var p updateGoodsInfoParam
|
|
if err := tools.Params(&p, c); err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
var secCate goods.Category
|
|
dbc.DB.First(&secCate, "id = ? AND parent_id = ?", p.SecondCategoryID, p.FirstCategoryID)
|
|
if secCate.ID == 0 {
|
|
back.Fail(c, "类目参数错误")
|
|
return
|
|
}
|
|
|
|
var goodsInfo goods.Information
|
|
dbc.DB.First(&goodsInfo, p.GoodsID)
|
|
|
|
if err := dbc.DB.Model(&goodsInfo).Updates(map[string]interface{}{
|
|
"vendor_id": p.VendorID,
|
|
"goods_name": p.GoodsName,
|
|
"description": p.Description,
|
|
"material": p.Material,
|
|
"first_category_id": p.FirstCategoryID,
|
|
"second_category_id": p.SecondCategoryID,
|
|
//"publish_status": p.PublishStatus,
|
|
"freight_id": p.FreightID,
|
|
"weight": p.Weight.Round(2),
|
|
"is_join_team_performance": p.IsJoinTeamPerformance,
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
back.Suc(c, "", &goodsInfo)
|
|
}
|
|
|
|
func UpdateCoupon(c *gin.Context) {
|
|
file, err := c.FormFile("excel")
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
|
|
name := filepath.Join(static_path.Dir.Excel, file.Filename)
|
|
dst := filepath.Join(static_path.Dir.Root, name)
|
|
err = c.SaveUploadedFile(file, dst)
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
exl, err := excelize.OpenFile(dst)
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
|
|
allRows, _ := exl.GetRows(excel.SheetName) // 获取所有的行
|
|
if len(allRows) < 2 {
|
|
back.Suc(c, "", nil)
|
|
return
|
|
}
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
|
|
for _, r := range allRows[1:] {
|
|
if r[0] == "" || r[1] == "" {
|
|
continue
|
|
}
|
|
skuDetail := goods.Sku{}
|
|
err := tx.Where("code = ?", r[0]).First(&skuDetail).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error()+"skuCode:"+r[0])
|
|
tx.Rollback()
|
|
return
|
|
} else {
|
|
purchasePrice, err := decimal.NewFromString(r[1])
|
|
discountPrice, err := decimal.NewFromString(r[2])
|
|
coupon, err := decimal.NewFromString(r[3])
|
|
originalPrice := discountPrice.Add(coupon)
|
|
commissionRate, err := decimal.NewFromString(r[5])
|
|
commission := discountPrice.Mul(commissionRate)
|
|
inventory, err := strconv.Atoi(r[7])
|
|
goodsNum := string(r[8])
|
|
if err != nil {
|
|
back.Err(c, err.Error()+"skuCode:"+r[0])
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
skuDetail.PurchasePrice = purchasePrice
|
|
skuDetail.CommissionRate = commissionRate
|
|
skuDetail.DiscountPrice = discountPrice
|
|
skuDetail.Commission = commission
|
|
skuDetail.Inventory = uint(inventory)
|
|
skuDetail.Coupon = coupon
|
|
skuDetail.OriginalPrice = originalPrice
|
|
skuDetail.GoodsNum = goodsNum
|
|
if err = tx.Save(&skuDetail).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tx.Commit()
|
|
|
|
back.Suc(c, "", nil)
|
|
}
|
|
|
|
type FreightByCategoryPem struct {
|
|
CategoryId int `json:"category_id"`
|
|
FreightId uint `json:"freight_id"`
|
|
}
|
|
|
|
//根据产品类目修改运费模板
|
|
func FreightByCategory(c *gin.Context) {
|
|
var p FreightByCategoryPem
|
|
if err := tools.Params(&p, c); err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
//判断品牌是否存在
|
|
var categoryData goods.Category
|
|
dbc.DB.First(&categoryData, "id=?", p.CategoryId)
|
|
if categoryData.ID <= 0 {
|
|
back.Fail(c, "品牌不存在")
|
|
return
|
|
}
|
|
//判断运费模板是否存在
|
|
var freightData freight.Information
|
|
dbc.DB.First(&freightData, "id=?", p.FreightId)
|
|
if freightData.ID <= 0 {
|
|
back.Fail(c, "运费模板不存在")
|
|
return
|
|
}
|
|
//正式修改运费模板,这边根据分类还没确定
|
|
var goodsData goods.Information
|
|
dbc.DB.Model(&goodsData).Where("").Updates(goods.Information{
|
|
FreightID: p.FreightId,
|
|
})
|
|
back.Suc(c, "", nil)
|
|
return
|
|
}
|
|
|
|
type FreightByBrandPem struct {
|
|
BrandId int `json:"brand_id"`
|
|
FreightId uint `json:"freight_id"`
|
|
}
|
|
|
|
//根据产品品牌修改运费模板
|
|
func FreightByBrand(c *gin.Context) {
|
|
|
|
}
|