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.

611 lines
17 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package jyy
import (
"errors"
"fmt"
"recook/internal/model/order"
"recook/internal/model/order_preview"
user2 "recook/internal/model/user"
"recook/internal/v2/model/jyy"
goods2 "recook/internal/v2/model/recook/goods"
manage "recook/internal/v2/model/recook/order"
"recook/internal/v2/model/recook/user"
"time"
"github.com/golangkit/formatime"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"git.oa00.com/go/mysql"
)
type logic struct {
}
var Logic = logic{}
func (o logic) Banners() (res []jyy.Banner, err error) {
now := time.Now()
mysql.Db.Where("start < ?", now).Where("end > ?", now).Order("order_sort asc").Order("id desc").Find(&res)
return
}
func (o logic) Activities() (res []jyy.Activity, err error) {
mysql.Db.Where("status = 1").Order("order_sort asc").Order("id desc").Find(&res)
return
}
type ArgsEntryReq struct {
UserID uint `json:"user_id"`
}
type ShopCartSku struct {
ID uint `json:"id"`
SkuID uint `json:"sku_id"`
DiscountPrice decimal.Decimal `json:"discount_price"`
SalePrice decimal.Decimal `json:"sale_price"`
Quantity uint `json:"quantity"`
Limit int `json:"limit"`
Min int `json:"min"`
SkuName string `json:"sku_name"`
GoodsName string `json:"goods_name,omitempty"`
SalePublish uint `json:"sale_publish"`
PicUrl string `json:"pic_url"`
GoodsID uint `json:"goods_id"`
}
type ShopCartEntry struct {
GoodsID uint `json:"goods_id"`
GoodsName string `json:"goods_name"`
MainPhoto string `json:"main_photo"`
SkuList []ShopCartSku `json:"sku_list"`
SalePublish uint `json:"sale_publish"`
}
func (o logic) ShopCartEntries(args ArgsEntryReq) (res []ShopCartSku) {
sc := make([]jyy.ShopCartEntry, 0)
mysql.Db.Model(&jyy.ShopCartEntry{}).Where("user_id = ?", args.UserID).Find(&sc)
ids := make([]uint, 0)
idsMap := make(map[uint]uint)
skuMap := make(map[uint]uint)
for _, v := range sc {
ids = append(ids, v.SkuID)
idsMap[v.SkuID] = v.Quantity
skuMap[v.SkuID] = v.ID
}
var u1 user.RecookUserInfoModel
mysql.Db.First(&u1, "id = ?", args.UserID)
skuList := make([]goods2.RecookGoodsSkuModel, 0)
mysql.Db.Preload("GoodsInfo").Where("id in (?)", ids).Find(&skuList)
for _, v := range skuList {
res = append(res, ShopCartSku{
ID: skuMap[v.Id],
SkuID: v.Id,
DiscountPrice: v.DiscountPrice,
SalePrice: v.GetSalePrice(u1.Level),
Quantity: idsMap[v.Id],
Limit: v.Limit,
Min: v.Min,
SkuName: v.Name,
PicUrl: v.PicURL,
SalePublish: v.GoodsInfo.SalePublish,
GoodsName: v.GoodsInfo.GoodsName,
GoodsID: v.GoodsId,
})
}
// goodsMap := make(map[uint][]ShopCartSku)
// for _, v := range skuList {
// goodsMap[v.GoodsId] = append(goodsMap[v.GoodsId], ShopCartSku{
// ID: skuMap[v.Id],
// SkuID: v.Id,
// DiscountPrice: v.DiscountPrice,
// SalePrice: v.GetSalePrice(u1.Level),
// Quantity: idsMap[v.Id],
// Limit: v.Limit,
// Min: v.Min,
// SkuName: v.Name,
// })
// }
// inRes := make(map[uint]bool)
// for _, v := range skuList {
// if inRes[v.GoodsId] {
// continue
// }
// inRes[v.GoodsId] = true
// res = append(res, ShopCartEntry{
// GoodsID: v.GoodsId,
// GoodsName: v.GoodsInfo.GoodsName,
// MainPhoto: v.GoodsInfo.MainPhoto.Url,
// SkuList: goodsMap[v.GoodsId],
// SalePublish: v.GoodsInfo.SalePublish,
// })
// }
return
}
type skuEntry struct {
SkuID uint `json:"sku_id"`
Quantity int `json:"quantity"`
}
type ArgsAddSku struct {
UserID uint `json:"user_id"`
IsUpdate bool
SkuList []skuEntry `json:"sku_list" validate:"required,gte=1"`
}
func (o logic) ShopCartAddSku(args ArgsAddSku) (err error) {
var skuList []goods2.RecookGoodsSkuModel
ids := make([]uint, 0)
idMap := make(map[uint]int)
for _, v := range args.SkuList {
ids = append(ids, v.SkuID)
idMap[v.SkuID] = v.Quantity
}
mysql.Db.Preload("GoodsInfo").Find(&skuList, "id in (?)", ids)
if len(skuList) != len(ids) {
return errors.New("商品选择错误")
}
for _, v := range skuList {
if v.GoodsInfo.SalePublish != 1 {
return fmt.Errorf("%d商品下架", v.GoodsId)
}
if !v.GoodsInfo.IsSale {
return fmt.Errorf("%d商品不可批发", v.GoodsId)
}
if idMap[v.Id] < v.Min {
return fmt.Errorf("%s商品最低%d", v.Name, v.Min)
}
if idMap[v.Id]%v.Limit != 0 {
return fmt.Errorf("%s商品每手至少%d", v.Name, v.Min)
}
}
data := make([]jyy.ShopCartEntry, 0)
mysql.Db.Find(&data, "user_id = ?", args.UserID)
isUsed := make(map[uint]bool)
for _, v := range data {
if idMap[v.SkuID] != 0 {
if args.IsUpdate {
v.Quantity = uint(idMap[v.SkuID])
} else {
v.Quantity += uint(idMap[v.SkuID])
}
mysql.Db.Save(v)
isUsed[v.SkuID] = true
}
}
res := make([]jyy.ShopCartEntry, 0)
for _, v := range skuList {
if isUsed[v.Id] {
continue
}
res = append(res, jyy.ShopCartEntry{
SkuID: v.Id,
GoodsID: v.GoodsId,
UserID: args.UserID,
Quantity: uint(idMap[v.Id]),
})
}
if len(res) == 0 {
return nil
}
if err = mysql.Db.Create(&res).Error; err != nil {
return err
}
return
}
func (o logic) ShopCartDeleteSku(args ArgsAddSku) (err error) {
ids := make([]uint, 0)
for _, v := range args.SkuList {
ids = append(ids, v.SkuID)
}
err = mysql.Db.Delete(&jyy.ShopCartEntry{}, "sku_id in (?)", ids).Error
return
}
type OrderPreview struct {
UserID uint `json:"user_id" validate:"required"`
SkuList []skuEntry `json:"sku_list" validate:"required"`
Channel uint `json:"channel" validate:"oneof=0 1"`
}
type OrderPreviewInfo struct {
PreviewID uint `json:"preview_id"`
Addr user2.Addr `json:"Addr"`
SkuList []ShopCartSku `json:"sku_list"`
Total decimal.Decimal `json:"total"`
}
func (o logic) OrderPreview(args OrderPreview) (err error, res OrderPreviewInfo) {
var u1 user.RecookUserInfoModel
if err = mysql.Db.First(&u1, "id = ?", args.UserID).Error; err != nil {
return
}
if u1.Level < 2 || (u1.Level == 2 && !u1.IsOffline) {
err = errors.New("您目前还不是VIP店铺无法进行批发操作")
return
}
var skuList []goods2.RecookGoodsSkuModel
ids := make([]uint, 0)
idMap := make(map[uint]int)
for _, v := range args.SkuList {
ids = append(ids, v.SkuID)
idMap[v.SkuID] = v.Quantity
}
mysql.Db.Preload("GoodsInfo.MainPhoto").
Preload("GoodsInfo.Brand").
Preload("GoodsInfo.FirstCategory").
Preload("GoodsInfo.SecondCategory").
Find(&skuList, "id in (?)", ids)
if len(skuList) != len(ids) {
err = errors.New("商品选择错误")
return
}
for _, v := range skuList {
if v.GoodsInfo.SalePublish != 1 {
err = fmt.Errorf("%d商品下架", v.GoodsId)
return
}
if !v.GoodsInfo.IsSale {
err = fmt.Errorf("%d商品不可批发", v.GoodsId)
return
}
if idMap[v.Id] < v.Min {
err = fmt.Errorf("%s商品最低%d", v.Name, v.Min)
return
}
if idMap[v.Id]%v.Limit != 0 {
err = fmt.Errorf("%s商品每手至少%d", v.Name, v.Min)
return
}
}
goodsTotalAmount := decimal.Zero
cost := decimal.Zero
preOrderGoodsList := make([]order_preview.GoodsDetail, 0, 0)
sl := make([]ShopCartSku, 0)
for _, v := range skuList {
if v.SalePurchasePrice.IsZero() {
err = errors.New("价格异常")
return
}
qu := decimal.NewFromInt(int64(idMap[v.Id]))
goodsInfo := v.GoodsInfo
one := order_preview.GoodsDetail{
VendorID: goodsInfo.VendorID,
VendorName: "",
BrandID: goodsInfo.BrandID,
BrandName: goodsInfo.Brand.Name,
CategoryName: goodsInfo.FirstCategory.Name + "/" + goodsInfo.SecondCategory.Name,
GoodsID: goodsInfo.Id,
GoodsName: goodsInfo.GoodsName,
IsJoinTeamPerformance: goodsInfo.IsJoinTeamPerformance,
Hash: goodsInfo.Hash,
SkuID: v.Id,
SkuName: v.Name,
SkuCode: v.Code,
MainPhotoURL: goodsInfo.MainPhoto.Url,
Quantity: uint(idMap[v.Id]),
FreightID: goodsInfo.FreightID,
Weight: goodsInfo.Weight,
PromotionSkuId: 0,
PromotionGoodsId: 0,
PromotionName: "",
UnitPrice: v.GetSalePrice(u1.Level),
PurchasePrice: v.SalePurchasePrice,
TotalCommission: decimal.Zero,
GoodsAmount: v.GetSalePrice(u1.Level).Mul(qu),
IsImport: goodsInfo.IsImport,
Storehouse: goodsInfo.Storehouse,
IsFerme: goodsInfo.IsFerme,
ActualAmount: v.GetSalePrice(u1.Level).Mul(qu),
}
sl = append(sl, ShopCartSku{
SkuID: v.Id,
DiscountPrice: v.DiscountPrice,
SalePrice: v.GetSalePrice(u1.Level),
Quantity: uint(idMap[v.Id]),
Limit: v.Limit,
Min: v.Min,
SkuName: v.Name,
GoodsName: v.GoodsInfo.GoodsName,
PicUrl: v.PicURL,
})
preOrderGoodsList = append(preOrderGoodsList, one)
goodsTotalAmount = goodsTotalAmount.Add(v.GetSalePrice(u1.Level).Mul(qu))
cost = cost.Add(v.PurchasePrice.Mul(qu))
}
if goodsTotalAmount.LessThanOrEqual(decimal.Zero) {
err = fmt.Errorf("订单价格异常")
return
}
var defaultAddr user2.Addr
{
err = mysql.Db.First(&defaultAddr, "user_id = ? AND is_default = 1", args.UserID).Error
if err != nil && err != gorm.ErrRecordNotFound {
return
}
}
if err = mysql.Db.Transaction(func(tx *gorm.DB) error {
preOrderInfo := order_preview.Information{
AncestorID: 0,
ParentID: 0,
UserID: args.UserID,
SharerID: 0,
Title: skuList[0].GoodsInfo.GoodsName + "等多件",
BrandCouponTotalAmount: decimal.Zero,
UniverseCouponTotalAmount: decimal.Zero,
CoinTotalAmount: decimal.Zero,
ExpressTotalFee: decimal.Zero,
GoodsTotalAmount: goodsTotalAmount,
GoodsTotalCommission: decimal.Zero,
ActualTotalAmount: goodsTotalAmount,
Channel: args.Channel,
Cost: cost,
CreatedAt: formatime.NewSecondNow(),
OrderType: 2,
}
if e := tx.Create(&preOrderInfo).Error; e != nil {
return e
}
for i := range preOrderGoodsList {
preOrderGoodsList[i].OrderID = preOrderInfo.ID
}
if e := tx.Create(&preOrderGoodsList).Error; e != nil {
return e
}
preOrderAddr := order_preview.Addr{
OrderID: preOrderInfo.ID,
AddressID: defaultAddr.ID,
Province: defaultAddr.Province,
City: defaultAddr.City,
District: defaultAddr.District,
Address: defaultAddr.Address,
ReceiverName: defaultAddr.Name,
Mobile: defaultAddr.Mobile,
IsDeliveryArea: 1,
}
if e := tx.Create(&preOrderAddr).Error; e != nil {
return e
}
res.PreviewID = preOrderInfo.ID
res.Addr = defaultAddr
res.SkuList = sl
res.Total = goodsTotalAmount
return nil
}); err != nil {
return
}
return
}
type OrderAddrUpdate struct {
PreviewID uint `json:"preview_id"`
AddressID uint `json:"address_id"`
BuyerMessage string `json:"buyer_message"`
}
func (o logic) OrderUpdate(args OrderAddrUpdate) (err error) {
var addr user2.Addr
err = mysql.Db.First(&addr, "id = ?", args.AddressID).Error
if err != nil {
return
}
var previewOrderAddr order_preview.Addr
err = mysql.Db.First(&previewOrderAddr, "order_id = ?", args.PreviewID).Error
if err != nil {
return
}
if err = mysql.Db.Transaction(func(tx *gorm.DB) error {
if addr.ID > 0 {
if e := tx.Model(&previewOrderAddr).Updates(map[string]interface{}{
"address_id": addr.ID,
"province": addr.Province,
"city": addr.City,
"district": addr.District,
"address": addr.Address,
"receiver_name": addr.Name,
"mobile": addr.Mobile,
"is_delivery_area": 1,
}).Error; e != nil {
return e
}
}
if e := tx.Table((&order_preview.Information{}).TableName()).
Where("id = ?", args.PreviewID).
Updates(map[string]interface{}{"buyer_message": args.BuyerMessage}).Error; e != nil {
return e
}
return nil
}); err != nil {
return
}
return
}
func (o logic) Contact() (res jyy.Contact) {
mysql.Db.First(&res)
return
}
type ArgsProfitListReq struct {
UserID uint `json:"user_id"`
Date string `json:"date"`
ShopID uint `json:"shop_id"`
Kind uint `json:"kind"`
}
type ProfitSaleEntry struct {
Name string `json:"name"`
Amount decimal.Decimal `json:"amount"`
Income decimal.Decimal `json:"income"`
NotIncome decimal.Decimal `json:"not_income"`
Count int `json:"count"`
ShopID uint `json:"shop_id"`
}
type ProfitDetail struct {
All decimal.Decimal `json:"all"`
WeiDaoZ decimal.Decimal `json:"wei_dao_z"`
YiDaoZ decimal.Decimal `json:"yi_dao_z"`
Entry []ProfitSaleEntry `json:"entry"`
}
func (o logic) ProfitSaleList(args ArgsProfitListReq) (res ProfitDetail, err error) {
var p []order.Profit
mysql.Db.Where("type = 7").Find(&p, "user_id = ?", args.UserID)
ids := make([]uint, 0)
incomeMap := make(map[uint]decimal.Decimal)
for _, v := range p {
ids = append(ids, v.OrderID)
incomeMap[v.OrderID] = incomeMap[v.OrderID].Add(v.Income)
res.All = res.All.Add(v.Income)
}
var ods []manage.RecookOrderInfoModel
mysql.Db.Preload("User").Find(&ods, "id in (?)", ids)
userMap := make(map[uint][]manage.RecookOrderInfoModel)
for _, v := range ods {
userMap[v.UserId] = append(userMap[v.UserId], v)
}
for id, v := range userMap {
amount := decimal.Zero
income := decimal.Zero
for _, j := range v {
amount = amount.Add(j.ActualTotalAmount)
income = income.Add(incomeMap[j.Id])
}
res.Entry = append(res.Entry, ProfitSaleEntry{
ShopID: id,
Name: v[0].User.Nickname,
Amount: amount,
Income: income,
Count: len(v),
})
}
return
}
func (o logic) ProfitSalePerson(args ArgsProfitListReq) (res ProfitDetail, err error) {
var p []order.Profit
now, e := time.ParseInLocation("2006", args.Date, time.Local)
if e != nil {
err = errors.New("时间格式异常" + e.Error())
}
mysql.Db.Where("type = 7").Find(&p, "user_id = ? and created_at between ? and ?", args.UserID, now, now.AddDate(1, 0, 0))
ids := make([]uint, 0)
incomeMap := make(map[uint]decimal.Decimal)
for _, v := range p {
ids = append(ids, v.OrderID)
incomeMap[v.OrderID] = incomeMap[v.OrderID].Add(v.Income)
res.All = res.All.Add(v.Income)
}
var ods []manage.RecookOrderInfoModel
mysql.Db.Preload("User").Find(&ods, "id in (?) and user_id = ?", ids, args.ShopID)
dateMap := make(map[string][]manage.RecookOrderInfoModel)
for _, v := range ods {
key := v.CreatedAt.Time.Format("2006-01")
dateMap[key] = append(dateMap[key], v)
}
for id, v := range dateMap {
amount := decimal.Zero
income := decimal.Zero
for _, j := range v {
amount = amount.Add(j.ActualTotalAmount)
income = income.Add(incomeMap[j.Id])
}
res.Entry = append(res.Entry, ProfitSaleEntry{
ShopID: 0,
Name: id,
Amount: amount,
Income: income,
Count: len(v),
})
}
return
}
func (o logic) ProfitShopList(args ArgsProfitListReq) (res ProfitDetail, err error) {
var p []order.Profit
query := mysql.Db.Where("type = ?", args.Kind).Where("user_id = ?", args.UserID)
{
if args.Date != "" {
now, e := time.ParseInLocation("200601", args.Date, time.Local)
if e != nil {
err = errors.New("时间格式异常" + e.Error())
return
}
query = query.Where("created_at between ? and ?", now, now.AddDate(1, 0, 0))
}
}
query.Find(&p)
ids := make([]uint, 0)
incomeMap := make(map[uint]decimal.Decimal)
NotIncomeMap := make(map[uint]decimal.Decimal)
for _, v := range p {
ids = append(ids, v.OrderID)
res.All = res.All.Add(v.Income)
if v.Status == 0 {
NotIncomeMap[v.OrderID] = incomeMap[v.OrderID].Add(v.Income)
res.WeiDaoZ = res.WeiDaoZ.Add(v.Income)
}
if v.Status == 2 {
incomeMap[v.OrderID] = incomeMap[v.OrderID].Add(v.Income)
res.YiDaoZ = res.YiDaoZ.Add(v.Income)
}
}
var ods []manage.RecookOrderInfoModel
mysql.Db.Preload("User").Find(&ods, "id in (?)", ids)
dateMap := make(map[string][]manage.RecookOrderInfoModel)
if args.Date == "" {
for _, v := range ods {
key := v.CreatedAt.Time.Format("2006")
dateMap[key] = append(dateMap[key], v)
}
} else {
for _, v := range ods {
key := v.CreatedAt.Time.Format("2006-01-02")
dateMap[key] = append(dateMap[key], v)
}
}
for id, v := range dateMap {
income := decimal.Zero
notIncome := decimal.Zero
for _, j := range v {
income = income.Add(incomeMap[j.Id])
notIncome = notIncome.Add(NotIncomeMap[j.Id])
}
res.Entry = append(res.Entry, ProfitSaleEntry{
ShopID: 0,
Name: id,
Amount: decimal.Zero,
Income: income,
NotIncome: notIncome,
Count: len(v),
})
}
return
}