package third import ( "errors" "fmt" "git.oa00.com/go/mysql" "github.com/golangkit/formatime" "github.com/shopspring/decimal" "gorm.io/gorm" "log" "path" "recook/internal/dbc" "recook/internal/libs/bean" order4 "recook/internal/model/order" "recook/internal/v2/lib/supply" after2 "recook/internal/v2/logic/manage/after" order2 "recook/internal/v2/logic/manage/order" "recook/internal/v2/model/recook/after" "recook/internal/v2/model/recook/goods" manage3 "recook/internal/v2/model/recook/manage" manage2 "recook/internal/v2/model/recook/order" manage "recook/internal/v2/model/third" "recook/tools" "sort" "strconv" "strings" ) var SupplyLogic = &supplyLogic{} type supplyLogic struct { } type skuItem struct { Id uint `json:"id"` Name string `json:"name"` ImgUrl string `json:"imgUrl"` SupplyStatus uint `json:"supplyStatus"` SupplySkuId uint `json:"supplySkuId"` FirstCategoryName string `json:"firstCategoryName"` SecondCategoryName string `json:"secondCategoryName"` ThirdCategoryName string `json:"thirdCategoryName"` BrandName string `json:"brandName"` Price decimal.Decimal `json:"price"` GuidePrice decimal.Decimal `json:"guidePrice"` } type SupplySearch struct { Status uint Name string SupplySkuId uint IsExport bool } // Lists @Title 商品列表 func (s *supplyLogic) Lists(search SupplySearch, page bean.Page) (lists []skuItem, total int64) { var thirdPartySupplies []manage.RecookThirdPartySupply where := mysql.Db // 入库状态 switch search.Status { case manage.RecookThirdPartySupplyStatusNone: // 未入库 where = where.Where("status = ?", manage.RecookThirdPartySupplyStatusNone) case manage.RecookThirdPartySupplyStatusAdopt: // 已入库 where = where.Where("status = ?", manage.RecookThirdPartySupplyStatusAdopt) } // 商品名称 if search.Name != "" { where = where.Where("name like ?", fmt.Sprintf("%%%s%%", search.Name)) } // 供应商skuId if search.SupplySkuId > 0 { where = where.Where("supply_sku_id = ?", search.SupplySkuId) } if search.IsExport { mysql.Db.Where(where).Order("id desc").Find(&thirdPartySupplies) } else { mysql.Db.Model(thirdPartySupplies).Where(where).Count(&total) if page.HasPage(total) { mysql.Db.Where(where).Offset(page.GetStart()).Limit(page.GetLimit()).Order("id desc").Find(&thirdPartySupplies) } } for _, thirdPartySupply := range thirdPartySupplies { lists = append(lists, skuItem{ Id: thirdPartySupply.Id, Name: thirdPartySupply.Name, ImgUrl: thirdPartySupply.ImgUrl, SupplyStatus: thirdPartySupply.SupplyStatus, SupplySkuId: thirdPartySupply.SupplySkuId, FirstCategoryName: thirdPartySupply.FirstCategoryName, SecondCategoryName: thirdPartySupply.SecondCategoryName, ThirdCategoryName: thirdPartySupply.ThirdCategoryName, BrandName: thirdPartySupply.BrandName, Price: thirdPartySupply.Price, GuidePrice: thirdPartySupply.GuidePrice, }) } return } type supplySkuDetail struct { Id uint `json:"id"` Name string `json:"name"` ImgUrl string `json:"imgUrl"` Status uint `json:"status"` SupplyStatus uint `json:"supplyStatus"` SupplySkuId uint `json:"supplySkuId"` FirstCategoryName string `json:"firstCategoryName"` SecondCategoryName string `json:"secondCategoryName"` ThirdCategoryName string `json:"thirdCategoryName"` BrandName string `json:"brandName"` Price decimal.Decimal `json:"price"` GuidePrice decimal.Decimal `json:"guidePrice"` CategoryId uint `json:"categoryId"` CategoryName string `json:"categoryName"` CategoryParentName string `json:"categoryParentName"` Color string `json:"color"` Size string `json:"size"` UpcCode string `json:"upcCode"` Imgs []string `json:"imgs"` Content string `json:"content"` Unit string `json:"unit"` TaxCode string `json:"taxCode"` TaxName string `json:"taxName"` Tax string `json:"tax"` } // Detail @Title 商品详情 func (s *supplyLogic) Detail(supplySkuId uint) (result supplySkuDetail, err error) { thirdPartySupply := manage.RecookThirdPartySupply{} if mysql.Db.Preload("ThirdPartySupplyCategory.Category.Parent"). Preload("Imgs"). Where("supply_sku_id = ?", supplySkuId).First(&thirdPartySupply).Error != nil { return result, errors.New("商品错误") } result = supplySkuDetail{ Id: thirdPartySupply.Id, Name: thirdPartySupply.Name, ImgUrl: thirdPartySupply.ImgUrl, Status: thirdPartySupply.Status, SupplyStatus: thirdPartySupply.SupplyStatus, SupplySkuId: thirdPartySupply.SupplySkuId, FirstCategoryName: thirdPartySupply.FirstCategoryName, SecondCategoryName: thirdPartySupply.SecondCategoryName, ThirdCategoryName: thirdPartySupply.ThirdCategoryName, CategoryId: thirdPartySupply.ThirdPartySupplyCategory.CategoryId, BrandName: thirdPartySupply.BrandName, Price: thirdPartySupply.Price, GuidePrice: thirdPartySupply.GuidePrice, Color: thirdPartySupply.Color, Size: thirdPartySupply.Size, UpcCode: thirdPartySupply.UpcCode, Content: thirdPartySupply.Content, Unit: thirdPartySupply.Unit, TaxCode: thirdPartySupply.TaxCode, TaxName: thirdPartySupply.TaxName, Tax: thirdPartySupply.Tax, } if thirdPartySupply.ThirdPartySupplyCategory.CategoryId > 0 { result.CategoryName = thirdPartySupply.ThirdPartySupplyCategory.Category.Name result.CategoryParentName = thirdPartySupply.ThirdPartySupplyCategory.Category.Parent.Name } for _, thirdPartySupplyImg := range thirdPartySupply.Imgs { result.Imgs = append(result.Imgs, thirdPartySupplyImg.Path) } return } type AdoptSkuInfo struct { SupplySkuId uint DiscountPrice decimal.Decimal // 售价 Coupon decimal.Decimal // 商品券 } // Adopt @Title 商品入库 func (s *supplyLogic) Adopt(data AdoptSkuInfo) error { thirdPartySupply := manage.RecookThirdPartySupply{} if mysql.Db.Preload("ThirdPartySupplyCategory.Category"). Preload("Imgs"). Where("supply_sku_id = ?", data.SupplySkuId).First(&thirdPartySupply).Error != nil { return errors.New("商品错误") } if thirdPartySupply.GoodsId > 0 { return errors.New("商品已入库") } groups, err := supply.Api.Sku.Groups([]uint{data.SupplySkuId}) if err != nil { return err } var recookGoodsSkuModels []goods.RecookGoodsSkuModel mysql.Db.Where("third_party_type = ? and third_party_sku_id in ?", goods.RecookGoodsInfoThirdPartyTypeSupply, groups[0].GroupSkuIds).Find(&recookGoodsSkuModels) if len(recookGoodsSkuModels) > 0 { // 已添加过商品 return mysql.Db.Transaction(func(tx *gorm.DB) error { // 原数据处理 if tx.Model(&manage.RecookThirdPartySupply{}).Where("id = ?", thirdPartySupply.Id).Updates(map[string]interface{}{ "status": manage.RecookThirdPartySupplyStatusAdopt, "goods_id": recookGoodsSkuModels[0].GoodsId, }).RowsAffected != 1 { return errors.New("入库失败") } // 详情 if thirdPartySupply.Content != "" { if tx.Model(&goods.RecookGoodsContentModel{}).Where("goods_id = ?", recookGoodsSkuModels[0].GoodsId).Update("content", thirdPartySupply.Content).Error != nil { return errors.New("入库失败") } } // 商品图片 var mainPhotoModels []goods.RecookGoodsMainPhotoModel for key, skuImg := range thirdPartySupply.Imgs { isMaster := 0 if key == 0 { isMaster = 1 } mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, Url: skuImg.Path, Name: path.Base(skuImg.Path), IsMaster: isMaster, OrderNo: key, Width: 800, Height: 800, }) } if len(mainPhotoModels) > 0 { if len(mainPhotoModels) == 1 { mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: mainPhotoModels[0].GoodsId, Url: mainPhotoModels[0].Url, Name: mainPhotoModels[0].Name, IsMaster: 0, OrderNo: mainPhotoModels[0].OrderNo, Width: mainPhotoModels[0].Width, Height: mainPhotoModels[0].Height, }) } if tx.Where("goods_id = ?", recookGoodsSkuModels[0].GoodsId).Delete(&goods.RecookGoodsMainPhotoModel{}).Error != nil { return errors.New("更新失败") } if tx.Create(&mainPhotoModels).Error != nil { return errors.New("更新失败") } } // 多规格处理 var goodsAttributeModels, recookGoodsAttributeModel []goods.RecookGoodsAttributeModel mysql.Db.Where("goods_id = ?", recookGoodsSkuModels[0].GoodsId).Find(&recookGoodsAttributeModel) if thirdPartySupply.Color != "" { attItem := goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, Name: "规格", Value: thirdPartySupply.Color, } for _, item := range recookGoodsAttributeModel { if item.Name == "规格" && item.Value == thirdPartySupply.Color { attItem = item break } } if attItem.Id == 0 { if tx.Create(&attItem).Error != nil { return errors.New("入库失败") } } goodsAttributeModels = append(goodsAttributeModels, attItem) } if thirdPartySupply.Size != "" { attItem := goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, Name: "尺寸", Value: thirdPartySupply.Size, } for _, item := range recookGoodsAttributeModel { if item.Name == "规格" && item.Value == thirdPartySupply.Size { attItem = item break } } if attItem.Id == 0 { if tx.Create(&attItem).Error != nil { return errors.New("入库失败") } } goodsAttributeModels = append(goodsAttributeModels, attItem) } if len(goodsAttributeModels) == 0 { attItem := goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, Name: "规格", Value: "标准", } if attItem.Id == 0 { if tx.Create(&attItem).Error != nil { return errors.New("入库失败") } } goodsAttributeModels = append(goodsAttributeModels, attItem) } sort.Slice(goodsAttributeModels, func(i, j int) bool { return goodsAttributeModels[i].Id < goodsAttributeModels[j].Id }) var combineId []string var skuName []string for _, goodsAttributeModel := range goodsAttributeModels { combineId = append(combineId, strconv.Itoa(int(goodsAttributeModel.Id))) skuName = append(skuName, goodsAttributeModel.Value) } inventory := 0 if thirdPartySupply.SupplyStatus == manage.RecookThirdPartySupplySupplyStatusUp { inventory = 500 } // sku信息处理 sku := goods.RecookGoodsSkuModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, Name: strings.Join(skuName, "+"), CombineId: strings.Join(combineId, ","), PicURL: thirdPartySupply.ImgUrl, Code: thirdPartySupply.UpcCode, PurchasePrice: thirdPartySupply.Price, OriginalPrice: data.DiscountPrice.Add(data.Coupon), DiscountPrice: data.DiscountPrice, Coupon: data.Coupon, ControlPrice: thirdPartySupply.GuidePrice, Inventory: uint(inventory), ThirdPartySkuId: fmt.Sprintf("%d", thirdPartySupply.SupplySkuId), ThirdPartyType: goods.RecookGoodsInfoThirdPartyTypeSupply, } // 税率 tax, err := decimal.NewFromString(thirdPartySupply.Tax) if err == nil { // 发票税率 sku.Invoice = goods.RecookSkuInvoiceModel{ GoodsId: recookGoodsSkuModels[0].GoodsId, GoodsName: thirdPartySupply.Name, TaxSn: thirdPartySupply.TaxCode, TaxName: thirdPartySupply.TaxName, Unit: thirdPartySupply.Unit, TaxRate: tax, PlatformRate: tax, DeductionRate: tax, } } if tx.Create(&sku).Error != nil { return errors.New("入库失败") } return nil }) } else { // 未添加过商品 if thirdPartySupply.ThirdPartySupplyCategory.CategoryId == 0 { return errors.New("分类未匹配") } return mysql.Db.Transaction(func(tx *gorm.DB) error { goodsBrandModel := goods.RecookGoodsBrandModel{ Name: thirdPartySupply.BrandName, } if tx.Where(&goodsBrandModel).FirstOrCreate(&goodsBrandModel).Error != nil { return errors.New("入库失败") } recookGoodsInfoModel := goods.RecookGoodsInfoModel{ BrandID: goodsBrandModel.Id, VendorID: manage.RecookThirdPartySupplyVendorId, GoodsName: thirdPartySupply.Name, FirstCategoryID: thirdPartySupply.ThirdPartySupplyCategory.Category.ParentId, SecondCategoryID: thirdPartySupply.ThirdPartySupplyCategory.CategoryId, Hash: tools.GenerateGoodsHashSign(), CreatedAt: formatime.NewSecondNow(), UpdatedAt: formatime.NewSecondNow(), ThirdPartyType: goods.RecookGoodsInfoThirdPartyTypeSupply, } if tx.Create(&recookGoodsInfoModel).Error != nil { return errors.New("入库失败") } // 原数据处理 if tx.Model(&manage.RecookThirdPartySupply{}).Where("id = ?", thirdPartySupply.Id).Updates(map[string]interface{}{ "status": manage.RecookThirdPartySupplyStatusAdopt, "goods_id": recookGoodsInfoModel.Id, }).RowsAffected != 1 { return errors.New("入库失败") } // 商品详情 recookGoodsContentModel := goods.RecookGoodsContentModel{ GoodsId: recookGoodsInfoModel.Id, Content: thirdPartySupply.Content, } if tx.Create(&recookGoodsContentModel).Error != nil { return errors.New("入库失败") } // 商品图片 var mainPhotoModels []goods.RecookGoodsMainPhotoModel for key, skuImg := range thirdPartySupply.Imgs { isMaster := 0 if key == 0 { isMaster = 1 } mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: recookGoodsInfoModel.Id, Url: skuImg.Path, Name: path.Base(skuImg.Path), IsMaster: isMaster, OrderNo: key, Width: 800, Height: 800, }) } if len(mainPhotoModels) > 0 { if len(mainPhotoModels) == 1 { mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: mainPhotoModels[0].GoodsId, Url: mainPhotoModels[0].Url, Name: mainPhotoModels[0].Name, IsMaster: 0, OrderNo: mainPhotoModels[0].OrderNo, Width: mainPhotoModels[0].Width, Height: mainPhotoModels[0].Height, }) } if tx.Create(&mainPhotoModels).Error != nil { return errors.New("更新失败") } } else { return errors.New("商品图片错误") } // 多规格处理 var goodsAttributeModels []goods.RecookGoodsAttributeModel if thirdPartySupply.Color != "" { goodsAttributeModels = append(goodsAttributeModels, goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsInfoModel.Id, Name: "规格", Value: thirdPartySupply.Color, }) } if thirdPartySupply.Size != "" { goodsAttributeModels = append(goodsAttributeModels, goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsInfoModel.Id, Name: "尺寸", Value: thirdPartySupply.Size, }) } if len(goodsAttributeModels) == 0 { goodsAttributeModels = append(goodsAttributeModels, goods.RecookGoodsAttributeModel{ GoodsId: recookGoodsInfoModel.Id, Name: "规格", Value: "标准", }) } if tx.Create(&goodsAttributeModels).Error != nil { return errors.New("入库失败") } var combineId []string var skuName []string for _, goodsAttributeModel := range goodsAttributeModels { combineId = append(combineId, strconv.Itoa(int(goodsAttributeModel.Id))) skuName = append(skuName, goodsAttributeModel.Value) } inventory := 0 if thirdPartySupply.SupplyStatus == manage.RecookThirdPartySupplySupplyStatusUp { inventory = 500 } // sku信息处理 sku := goods.RecookGoodsSkuModel{ GoodsId: recookGoodsInfoModel.Id, Name: strings.Join(skuName, "+"), CombineId: strings.Join(combineId, ","), PicURL: thirdPartySupply.ImgUrl, Code: thirdPartySupply.UpcCode, PurchasePrice: thirdPartySupply.Price, ControlPrice: thirdPartySupply.GuidePrice, OriginalPrice: data.DiscountPrice.Add(data.Coupon), DiscountPrice: data.DiscountPrice, Coupon: data.Coupon, Inventory: uint(inventory), ThirdPartySkuId: fmt.Sprintf("%d", thirdPartySupply.SupplySkuId), ThirdPartyType: goods.RecookGoodsInfoThirdPartyTypeSupply, } // 税率 tax, err := decimal.NewFromString(thirdPartySupply.Tax) if err == nil { // 发票税率 sku.Invoice = goods.RecookSkuInvoiceModel{ GoodsId: recookGoodsInfoModel.Id, GoodsName: thirdPartySupply.Name, TaxSn: thirdPartySupply.TaxCode, TaxName: thirdPartySupply.TaxName, Unit: thirdPartySupply.Unit, TaxRate: tax, PlatformRate: tax, DeductionRate: tax, } } if tx.Create(&sku).Error != nil { return errors.New("入库失败") } return nil }) } } // SyncPrice @Title 同步价格 func (s *supplyLogic) SyncPrice(skuIds []uint) error { prices, err := supply.Api.Sku.Prices(skuIds) if err != nil { return err } mSkuPrice := map[uint]supply.SkuPrice{} for _, price := range prices { mSkuPrice[price.Id] = price } var thirdPartySupplies []manage.RecookThirdPartySupply mysql.Db.Where("supply_sku_id in ?", skuIds).Find(&thirdPartySupplies) for _, partySupply := range thirdPartySupplies { mysql.Db.Transaction(func(tx *gorm.DB) error { if tx.Model(&partySupply).Updates(map[string]interface{}{ "price": mSkuPrice[partySupply.SupplySkuId].Price, "guide_price": mSkuPrice[partySupply.SupplySkuId].GuidePrice, "supply_status": mSkuPrice[partySupply.SupplySkuId].Status, }).Error != nil { return errors.New("更新失败") } // 入库商品同步价格 if partySupply.Status == manage.RecookThirdPartySupplyStatusAdopt { // 上游上下架修改库存 inventory := 0 if mSkuPrice[partySupply.SupplySkuId].Status == manage.RecookThirdPartySupplySupplyStatusUp { inventory = 500 } if tx.Model(&goods.RecookGoodsSkuModel{}).Where("third_party_type = ? and third_party_sku_id = ?", goods.RecookGoodsInfoThirdPartyTypeSupply, partySupply.SupplySkuId).Updates(map[string]interface{}{ "purchase_price": partySupply.Price, "inventory": inventory, }).Error != nil { return errors.New("更新失败") } } return nil }) } return nil } // SyncData @Title 同步商品信息 func (s *supplyLogic) SyncData(skuIds []uint) error { details, err := supply.Api.Sku.Details(skuIds) if err != nil { return err } var thirdPartySupplies []manage.RecookThirdPartySupply mysql.Db.Where("supply_sku_id in ?", skuIds).Find(&thirdPartySupplies) mThirdPartySupply := map[uint]manage.RecookThirdPartySupply{} for _, partySupply := range thirdPartySupplies { mThirdPartySupply[partySupply.SupplySkuId] = partySupply } for _, skuInfo := range details { if partySupply, ok := mThirdPartySupply[skuInfo.Id]; ok { // 更新商品 mysql.Db.Transaction(func(tx *gorm.DB) error { if tx.Model(&partySupply).Updates(map[string]interface{}{ "name": skuInfo.Name, "brand_id": skuInfo.BrandId, "brand_name": skuInfo.BrandName, "first_category_id": skuInfo.FirstCategoryId, "first_category_name": skuInfo.FirstCategoryName, "second_category_id": skuInfo.SecondCategoryId, "second_category_name": skuInfo.SecondCategoryName, "third_category_id": skuInfo.ThirdCategoryId, "third_category_name": skuInfo.ThirdCategoryName, "price": skuInfo.Price, "guide_price": skuInfo.GuidePrice, "img_url": skuInfo.ImgUrl, "profit": skuInfo.Profit, "size": skuInfo.Size, "color": skuInfo.Color, "tax": skuInfo.Tax, "tax_code": skuInfo.TaxCode, "tax_name": skuInfo.TaxName, "unit": skuInfo.Unit, "upc_code": skuInfo.UpcCode, "content": skuInfo.Content, "supply_status": skuInfo.Status, }).Error != nil { return errors.New("更新失败") } var thirdPartySupplyImgs []manage.RecookThirdPartySupplyImg for _, skuImg := range skuInfo.Imgs { thirdPartySupplyImgs = append(thirdPartySupplyImgs, manage.RecookThirdPartySupplyImg{ SupplySkuId: skuInfo.Id, Path: skuImg.Path, }) } if len(thirdPartySupplyImgs) > 0 { if tx.Where("supply_sku_id = ?", partySupply.SupplySkuId).Delete(&manage.RecookThirdPartySupplyImg{}).Error != nil { return errors.New("更新失败") } if tx.Create(&thirdPartySupplyImgs).Error != nil { return errors.New("更新失败") } } var thirdPartySupplySpecifications []manage.RecookThirdPartySupplySpecification for _, specification := range skuInfo.Specifications { for _, attribute := range specification.Attributes { thirdPartySupplySpecifications = append(thirdPartySupplySpecifications, manage.RecookThirdPartySupplySpecification{ SupplySkuId: skuInfo.Id, Name: attribute.Name, Value: strings.Join(attribute.Value, ";"), GroupName: specification.Name, }) } } if len(thirdPartySupplySpecifications) > 0 { if tx.Where("supply_sku_id = ?", partySupply.SupplySkuId).Delete(&manage.RecookThirdPartySupplySpecification{}).Error != nil { return errors.New("更新失败") } if tx.Create(&thirdPartySupplySpecifications).Error != nil { return errors.New("更新失败") } } // 入库商品同步信息 if partySupply.Status == manage.RecookThirdPartySupplyStatusAdopt { // 商品信息同步 // 详情 if skuInfo.Content != "" { if tx.Model(&goods.RecookGoodsContentModel{}).Where("goods_id = ?", partySupply.GoodsId).Update("content", skuInfo.Content).Error != nil { return errors.New("更新失败") } } // 商品图片 var mainPhotoModels []goods.RecookGoodsMainPhotoModel for key, skuImg := range skuInfo.Imgs { isMaster := 0 if key == 0 { isMaster = 1 } mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: partySupply.GoodsId, Url: skuImg.Path, Name: path.Base(skuImg.Path), IsMaster: isMaster, OrderNo: key, Width: 800, Height: 800, }) } if len(mainPhotoModels) > 0 { if len(mainPhotoModels) == 1 { mainPhotoModels = append(mainPhotoModels, goods.RecookGoodsMainPhotoModel{ GoodsId: mainPhotoModels[0].GoodsId, Url: mainPhotoModels[0].Url, Name: mainPhotoModels[0].Name, IsMaster: 0, OrderNo: mainPhotoModels[0].OrderNo, Width: mainPhotoModels[0].Width, Height: mainPhotoModels[0].Height, }) } if tx.Where("goods_id = ?", partySupply.GoodsId).Delete(&goods.RecookGoodsMainPhotoModel{}).Error != nil { return errors.New("更新失败") } if tx.Create(&mainPhotoModels).Error != nil { return errors.New("更新失败") } } // 税率 tax, err := decimal.NewFromString(skuInfo.Tax) if err == nil { // 获取sku信息 recookGoodsSkuModel := goods.RecookGoodsSkuModel{} mysql.Db.Where("third_party_type = ? and third_party_sku_id = ?", goods.RecookGoodsInfoThirdPartyTypeSupply, partySupply.SupplySkuId).First(&recookGoodsSkuModel) if recookGoodsSkuModel.Id > 0 { // 发票税率 skuInvoiceModel := goods.RecookSkuInvoiceModel{} mysql.Db.Where("sku_id = ?", recookGoodsSkuModel.Id).First(&skuInvoiceModel) if skuInvoiceModel.Id > 0 { if tx.Model(&skuInvoiceModel).Updates(map[string]interface{}{ "goods_name": skuInfo.Name, "tax_sn": skuInfo.TaxCode, "tax_name": skuInfo.TaxName, "unit": skuInfo.Unit, "tax_rate": tax, "platform_rate": tax, "deduction_rate": tax, }).Error != nil { return errors.New("更新失败") } } else { skuInvoiceModel = goods.RecookSkuInvoiceModel{ SkuId: recookGoodsSkuModel.Id, GoodsId: recookGoodsSkuModel.GoodsId, GoodsName: skuInfo.Name, TaxSn: skuInfo.TaxCode, TaxName: skuInfo.TaxName, Unit: skuInfo.Unit, TaxRate: tax, PlatformRate: tax, DeductionRate: tax, } if tx.Create(&skuInvoiceModel).Error != nil { return errors.New("更新失败") } } } } // 上游上下架修改库存 inventory := 0 if skuInfo.Status == manage.RecookThirdPartySupplySupplyStatusUp { inventory = 500 } if tx.Model(&goods.RecookGoodsSkuModel{}).Where("third_party_type = ? and third_party_sku_id = ?", goods.RecookGoodsInfoThirdPartyTypeSupply, partySupply.SupplySkuId).Updates(map[string]interface{}{ "purchase_price": partySupply.Price, "inventory": inventory, "pic_url": skuInfo.ImgUrl, "code": skuInfo.UpcCode, }).Error != nil { return errors.New("更新失败") } } return nil }) } else { // 分类处理 category := manage.RecookThirdPartySupplyCategory{ FirstCategoryName: skuInfo.FirstCategoryName, SecondCategoryName: skuInfo.SecondCategoryName, ThirdCategoryName: skuInfo.ThirdCategoryName, } mysql.Db.Where(&category).FirstOrCreate(&category) // 添加商品 thirdPartySupply := manage.RecookThirdPartySupply{ SupplySkuId: skuInfo.Id, Name: skuInfo.Name, BrandId: skuInfo.BrandId, BrandName: skuInfo.BrandName, ThirdPartySupplyCategoryId: category.Id, FirstCategoryId: skuInfo.FirstCategoryId, FirstCategoryName: skuInfo.FirstCategoryName, SecondCategoryId: skuInfo.SecondCategoryId, SecondCategoryName: skuInfo.SecondCategoryName, ThirdCategoryId: skuInfo.ThirdCategoryId, ThirdCategoryName: skuInfo.ThirdCategoryName, Price: decimal.NewFromFloat(skuInfo.Price), GuidePrice: decimal.NewFromFloat(skuInfo.GuidePrice), ImgUrl: skuInfo.ImgUrl, Profit: decimal.NewFromFloat(skuInfo.Profit), Size: skuInfo.Size, Color: skuInfo.Color, Tax: skuInfo.Tax, Unit: skuInfo.Unit, UpcCode: skuInfo.UpcCode, TaxName: skuInfo.TaxName, TaxCode: skuInfo.TaxCode, Content: skuInfo.Content, Status: manage.RecookThirdPartySupplyStatusNone, SupplyStatus: skuInfo.Status, } for _, skuImg := range skuInfo.Imgs { thirdPartySupply.Imgs = append(thirdPartySupply.Imgs, manage.RecookThirdPartySupplyImg{ SupplySkuId: skuInfo.Id, Path: skuImg.Path, }) } for _, specification := range skuInfo.Specifications { for _, attribute := range specification.Attributes { thirdPartySupply.Specifications = append(thirdPartySupply.Specifications, manage.RecookThirdPartySupplySpecification{ SupplySkuId: skuInfo.Id, Name: attribute.Name, Value: strings.Join(attribute.Value, ";"), GroupName: specification.Name, }) } } mysql.Db.Create(&thirdPartySupply) } } return nil } // OrderSplit @Title 拆单 func (s *supplyLogic) OrderSplit(orderSplit supply.OrderSplit) error { var orderInfo manage2.RecookOrderInfoModel mysql.Db.Preload("OrderSku").First(&orderInfo, "third_party_order_sn = ? and third_party_type = ?", orderSplit.OrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply) if orderInfo.Id > 0 { log.Println("重复拆单请求") return nil } var parentOrderInfo manage2.RecookOrderInfoModel if err := mysql.Db.Preload("OrderSku").First(&parentOrderInfo, "third_party_order_sn = ? and third_party_type = ?", orderSplit.ParentOrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply).Error; err != nil { return err } var rod manage2.RecookOrderInfoModel if err := mysql.Db.Preload("OrderSku").First(&rod, "third_party_order_sn = ? and third_party_type = ?", orderSplit.RootOrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply).Error; err != nil { return err } return mysql.Db.Transaction(func(tx *gorm.DB) error { parentOrderInfo.IsSplit = true parentOrderInfo.Status = 3 tx.Model(manage2.RecookOrderInfoModel{}).Where("id = ?", parentOrderInfo.Id).Updates(map[string]interface{}{ "is_split": true, "status": 3, }) if err := tx.Table((&order4.Profit{}).TableName()).Where("order_id = ?", rod.Id).Update("status", 1).Error; err != nil { return err } if err := tx.Table((&order4.Profit{}).TableName()).Where("order_id = ?", parentOrderInfo.Id).Update("status", 1).Error; err != nil { return err } var skuIds []uint for _, sku := range orderSplit.Skus { skuIds = append(skuIds, sku.SkuId) } var orderSku []manage2.RecookOrderGoodsDetailModel var sku []goods.RecookGoodsSkuModel sub := tx.Select("id").Find(&sku, "third_party_sku_id in (?)", skuIds) if err := tx.Find(&orderSku, "sku_id in (?) AND order_id = ?", sub, rod.Id).Error; err != nil { log.Println(err.Error()) return err } // 拆分拆单运费 unit := orderSplit.FreightFee.Div(decimal.NewFromInt(int64(len(orderSku)))).Round(2) fee := orderSplit.FreightFee unitMap := make(map[uint]decimal.Decimal) var orderSkuNew []manage2.RecookOrderGoodsDetailModel for i := 0; i < len(orderSku); i++ { if i == len(orderSku)-1 { unitMap[orderSku[i].SkuId] = fee break } fee = fee.Sub(unit) unitMap[orderSku[i].SkuId] = unit } coinTotal := decimal.Zero goodsTotalAmount := decimal.Zero goodsTotalCommission := decimal.Zero actualAmount := decimal.Zero for _, v := range orderSku { actualAmount = actualAmount.Add(v.GoodsAmount).Add(unitMap[v.SkuId]).Sub(v.CoinAmount) coinTotal = coinTotal.Add(v.CoinAmount) goodsTotalAmount = goodsTotalAmount.Add(v.GoodsAmount) } orderNew := manage2.RecookOrderInfoModel{ AncestorId: rod.AncestorId, ParentId: rod.ParentId, SharerId: rod.SharerId, LiveId: rod.LiveId, UserId: rod.UserId, UserRole: rod.UserRole, Title: "", CoinTotalAmount: coinTotal, ExpressTotalFee: orderSplit.FreightFee, GoodsTotalAmount: goodsTotalAmount, GoodsTotalCommission: goodsTotalCommission, ActualTotalAmount: actualAmount, Channel: rod.Channel, ShippingMethod: rod.ShippingMethod, StoreId: rod.StoreId, BuyerMessage: rod.BuyerMessage, Status: 1, ExpressStatus: rod.ExpressStatus, InvoiceStatus: rod.InvoiceStatus, CreatedAt: rod.CreatedAt, ExpireTime: rod.ExpireTime, PayIP: rod.PayIP, TradeNo: rod.TradeNo, PayTime: rod.PayTime, PayMethod: rod.PayMethod, RbacId: rod.RbacId, IsFirst: rod.IsFirst, VirtualID: rod.VirtualID, PayType: rod.PayType, Kind: rod.Kind, ThirdPartyType: rod.ThirdPartyType, ThirdPartyOrderSn: orderSplit.OrderSn, OrderType: rod.OrderType, } var orderAddr manage2.RecookOrderAddrModel tx.First(&orderAddr, "order_id = ?", rod.Id) if err := tx.Create(&orderNew).Error; err != nil { log.Println(err.Error()) return err } orderAddr.Id = 0 orderAddr.OrderId = orderNew.Id if err := tx.Create(&orderAddr).Error; err != nil { log.Println(err.Error()) return err } cost := decimal.Zero total := decimal.Zero for _, v := range orderSku { cost = cost.Add(v.PurchasePrice).Mul(decimal.NewFromInt(int64(v.Quantity))) total = total.Add(v.GoodsAmount) v.Id = 0 v.OrderId = orderNew.Id v.ExpressFee = unitMap[v.SkuId] //v.CoinAmount = decimal.Zero v.ActualAmount = v.GoodsAmount.Add(v.ExpressFee).Sub(v.CoinAmount) //coinTotal = decimal.Zero orderSkuNew = append(orderSkuNew, v) } //orderNew.CoinTotalAmount = coinTotal if err := tx.Save(orderNew).Error; err != nil { log.Println(err.Error()) return err } if err := tx.Create(orderSkuNew).Error; err != nil { log.Println(err.Error()) return err } var rp []order4.Profit if err := tx.Table((&order4.Profit{}).TableName()).Find(&rp, "order_id = ?", rod.Id).Error; err != nil { return err } profitNew := make([]*order4.Profit, 0) b2 := decimal.Zero for _, k := range orderSkuNew { b2 = b2.Add(k.GetBase().Mul(decimal.NewFromInt(int64(k.Quantity)))) } for _, v := range rp { temp := order4.CreateProfit(v.UserID, v.Type, b2, orderNew.Id) profitNew = append(profitNew, temp) } if len(profitNew) != 0 { if err := tx.Create(profitNew).Error; err != nil { log.Println(err.Error()) return err } } return nil }) } // OrderCancel @Title 订单取消 func (s *supplyLogic) OrderCancel(orderCancel supply.OrderCancel) error { var orderInfo manage2.RecookOrderInfoModel if err := mysql.Db.First(&orderInfo, "third_party_order_sn = ? and third_party_type = ?", orderCancel.OrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply).Error; err != nil { if err != gorm.ErrRecordNotFound { log.Println(err.Error()) return err } else { return nil } } switch orderCancel.Status { case supply.OrderCancelSuccess: // 取消成功 if orderInfo.Status == 0 { // 未支付订单直接取消 return nil } else { tx := dbc.DB.Begin() { var asGoods []after.RecookAfterSalesGoodsModel tx.Find(&asGoods, "order_id = ?", orderInfo.Id) for _, v := range asGoods { if v.RefundStatus == 1 { continue } t := &after2.UpdateOrderCheckStatusReq{ AsID: v.Id, } if err := after2.Refund(tx, v, orderInfo, t, manage3.RecookManageUserInfoModel{}); err != nil { tx.Rollback() return err } } } if err := tx.Model(orderInfo).Update("deal_status", 11).Error; err != nil { return err } tx.Commit() } case supply.OrderCancelFail: // 取消失败 tx := dbc.DB.Begin() { orderInfo.DealStatus = 12 if err := tx.Save(&orderInfo).Error; err != nil { return err } var asGoods []after.RecookAfterSalesGoodsModel if err := tx.Find(&asGoods, "order_id = ?", orderInfo.Id).Error; err != nil { return err } for _, v := range asGoods { if err := tx.Model(v).Updates(after.RecookAfterSalesGoodsModel{ ReturnStatus: 2, RejectReason: "系统自动拒绝", FinishTime: formatime.NewSecondNow(), }).Error; err != nil { tx.Rollback() return err } if err := tx.Model(&manage2.RecookOrderGoodsDetailModel{Id: v.OrderGoodsId}).Updates(map[string]interface{}{ "ass_type": 0, }).Error; err != nil { tx.Rollback() return err } //这里插入日志 Log1 := after.RecookAfterSalesLogsModel{ AsID: v.Id, Title: "平台拒绝退款", Content: "拒绝买家退款申请,如有疑问,请联系客服", CTime: formatime.NewSecondNow(), User: "系统", UserId: 0, } tx.Create(&Log1) Log2 := after.RecookAfterSalesLogsModel{ AsID: v.Id, Title: "退款关闭", Content: "系统自动关闭", CTime: formatime.NewSecondNow(), User: "系统", UserId: 0, } tx.Create(&Log2) } } tx.Commit() case supply.OrderCancelReject: // 拒收/商家主动取消case supply. } return nil } // OrderStockOut @Title 订单出库 func (s *supplyLogic) OrderStockOut(orderStockOut supply.OrderStockOut) error { var orderInfo manage2.RecookOrderInfoModel if err := mysql.Db.First(&orderInfo, "third_party_order_sn = ? and third_party_type = ?", orderStockOut.OrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply).Error; err != nil { if err != gorm.ErrRecordNotFound { log.Println(err.Error()) return err } else { return nil } } var orderSku []manage2.RecookOrderGoodsDetailModel if err := mysql.Db.Find(&orderSku, "order_id =? ", orderInfo.Id).Error; err != nil { log.Println(err.Error()) return err } ep := make([]order2.ExpressInfo, 0) for _, v := range orderStockOut.Packages { ep = append(ep, order2.ExpressInfo{ ExpressCompName: v.LogisticsName, ExpressNo: v.WaybillCode, }) } for index, j := range orderSku { if j.ExpressStatus == manage2.RecookOrderGoodsDetailExpressStatusTrue { continue } if err := order2.Expresslogic.Express(j.VendorId, "third_api", orderSku[index], ep); err != nil { return err } } return nil } // OrderFinish @Title 订单完成 func (s *supplyLogic) OrderFinish(orderFinish supply.OrderFinish) error { var orderInfo manage2.RecookOrderInfoModel if err := mysql.Db.First(&orderInfo, "third_party_order_sn = ? and third_party_type = ?", orderFinish.OrderSn, goods.RecookGoodsInfoThirdPartyTypeSupply).Error; err != nil { if err != gorm.ErrRecordNotFound { log.Println(err.Error()) return err } else { return nil } } if mysql.Db.Model(&orderInfo).Updates(map[string]interface{}{ "third_party_status": 1, }).Error != nil { return errors.New("保存失败") } return nil }