mh_server/model/mall.go

1298 lines
39 KiB
Go
Raw Normal View History

2022-01-16 08:56:33 +00:00
package model
import (
2022-05-28 06:18:27 +00:00
"encoding/json"
"errors"
2022-03-07 06:14:05 +00:00
"fmt"
2022-01-16 08:56:33 +00:00
"github.com/codinl/go-logger"
2022-11-26 08:52:05 +00:00
"github.com/gin-gonic/gin"
2022-03-07 06:14:05 +00:00
"github.com/jinzhu/gorm"
2022-05-28 06:18:27 +00:00
"github.com/rs/zerolog/log"
2022-01-16 08:56:33 +00:00
"mh-server/lib/utils"
2022-11-26 08:52:05 +00:00
"net/url"
2022-05-28 06:18:27 +00:00
"sort"
"strconv"
"strings"
2022-01-16 08:56:33 +00:00
"time"
)
const (
SaleStatusUnknown = iota
SaleStatusYes
SaleStatusNo
)
const (
PayTypeUnknown = iota
PayTypeRm // 人民币
PayTypeVm // 积分
)
const (
PayStatusUnknown = iota
PayStatusInit
PayStatusOK
PayStatusFail
)
2022-03-07 06:14:05 +00:00
const (
DeliveryStatusUnknown = iota
DeliveryStatusUnDeliver // 1-待发货
DeliveryStatusDelivered // 2-已发货
DeliveryStatusHarvestGoods // 3-已收货
)
2022-05-28 06:18:27 +00:00
const (
Rmb = 100
)
2022-01-16 08:56:33 +00:00
const (
AccountForDw = 2 // 迪为账户
)
2022-01-16 08:56:33 +00:00
// 商品
// gen:qs
2023-08-01 02:23:00 +00:00
//
//go:generate goqueryset -in mall.go
2022-01-16 08:56:33 +00:00
type Goods struct {
Model
GoodsId uint32 `json:"goods_id" gorm:"unique_index"`
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // ERP商品id
SerialNo string `json:"serial_no" gorm:"unique_index"` // 序列号
CatId uint32 `json:"cat_id" gorm:"index"` // 分类
Name string `json:"name"` // 名称
Title string `json:"title"` // 标题
MainImage string `json:"main_image"` // 主图
Images string `json:"images"` // 图片列表,用,隔开
Detail string `json:"detail" gorm:"type:text;"` // 详情, 富文本
SoldCount uint32 `json:"sold_count"` // 已销售数量
SaleStatus uint32 `json:"sale_status"` // 在售状态 1-在售 2-下架
CatSort uint32 `json:"cat_sort"` // 分类排序
Sort uint32 `json:"sort"` // 商品排序
SpecList string `json:"spec_list" gorm:"type:text;"` // 属性json数据
DiscountList string `json:"discount_list" gorm:"type:text;"` // 折扣
SpecIndex string `json:"spec_index" gorm:"index"` // 1_3
PriceVm uint32 `json:"price_vm"` // 积分价格
PriceRm uint32 `json:"price_rm"` // 人民币价格
PriceOriginal uint32 `json:"price_original"` // 市场价
DeliveryFee uint32 `json:"delivery_fee"` // 邮费
DealType uint32 `json:"deal_type"` // 1-积分兑换 2-购买 3-抵扣
VersionId uint64 `json:"version_id"` // 乐观锁
ShowDiscount int8 `json:"show_discount"` //
GoodsAccountNum uint32 `json:"goods_account_num"` // 收款账户编号
ErpStock uint32 `json:"erp_stock" gorm:"-"` // erp库存
CurrentStoreErpStock uint32 `json:"current_store_erp_stock" gorm:"-"` // 当前门店的erp库存
2022-05-28 06:18:27 +00:00
2023-09-20 10:05:53 +00:00
GoodsCat *GoodsCat `json:"goods_cat" gorm:"-"`
GoodsDiscount *GoodsDiscount `json:"goods_discount" gorm:"-"`
Attributes []GoodsAttribute `json:"attributes" gorm:"-"`
Combo *GoodsAttributeCombo `json:"combo" gorm:"-"`
2022-05-28 06:18:27 +00:00
}
// gen:qs
type GoodsCat struct {
Model
Name string `json:"name"` // 名称
Priority string `json:"priority"` // 分类
State uint32 `json:"state"` // 1-未使用 2-使用
Level uint32 `json:"level"` // 分类层级
Pid uint32 `json:"pid" gorm:"index"`
Sort uint32 `json:"sort"`
SubCats []GoodsCat `json:"sub_cats" gorm:"-"` // 子列表
}
type GoodsDiscount struct {
Gold uint32 `json:"gold"` // 黄金折扣
Platinum uint32 `json:"platinum"` // 白金折扣
BlackGold uint32 `json:"black_gold"` // 黑金折扣
}
// gen:qs
type GoodsAttribute struct {
Model
GoodsId uint32 `json:"goods_id" gorm:"index"`
SerialNo string `json:"serial_no" gorm:"index"` // 序列号
CatId uint32 `json:"cat_id" gorm:"index"` // 分类
Name string `json:"name"` // 名称
Title string `json:"title"` // 标题
MainImage string `json:"main_image"` // 主图
Stock uint32 `json:"stock"` // 库存
SoldCount uint32 `json:"sold_count"` // 已销售数量
PriceRm uint32 `json:"price_rm"` // 人民币价格
PriceOriginal uint32 `json:"price_original"` // 市场价
SpecValueList string `json:"spec_value_list" gorm:"type:text;"` // 属性json数据
SpecValueIndex string `json:"spec_value_index" gorm:"index"` // 1_3_5
DealType uint32 `json:"deal_type"` // 1-积分兑换 2-购买 3-抵扣
SpecValues []*SpecValue `json:"spec_values" gorm:"-"`
Goods *Goods `json:"goods" gorm:"-"`
Combos []GoodsAttributeCombo `json:"combos" gorm:"-"`
Combo *GoodsAttributeCombo `json:"combo" gorm:"-"`
// goods_attribute
}
// gen:qs
type GoodsAttributeCombo struct {
Model
GoodsAttributeId uint32 `json:"goods_attribute_id" gorm:"index"`
GoodsId uint32 `json:"goods_id" gorm:"index"`
SerialNo string `json:"serial_no" gorm:"index"` // 序列号
CatId uint32 `json:"cat_id" gorm:"index"` // 分类
Name string `json:"name"` // 名称
Title string `json:"title"` // 标题
MainImage string `json:"main_image"` // 主图
ComboName string `json:"combo_name"` // 名称
PriceVm uint32 `json:"price_vm"` // 积分价格
PriceRm uint32 `json:"price_rm"` // 人民币价格
2022-01-16 08:56:33 +00:00
}
2022-05-28 06:18:27 +00:00
//type GoodsSpec struct {
2022-01-22 05:07:06 +00:00
// Model
//}
2022-05-28 06:18:27 +00:00
// gen:qs
type Spec struct {
Model
DisplayName string `json:"display_name" gorm:"unique_index"`
Name string `json:"name"`
State uint32 `json:"state"` // 1-未使用 2-使用
Sort uint32 `json:"sort"`
Values []SpecValue `json:"values" gorm:"-"`
}
// gen:qs
type SpecValue struct {
Model
SpecId uint32 `json:"spec_id" gorm:"index"`
SpecDisplayName string `json:"spec_display_name"`
SpecName string `json:"spec_name"`
DisplayValue string `json:"display_value" gorm:"unique_index"`
State uint32 `json:"state"` // 1-未使用 2-使用
Value string `json:"value"`
SpecSort uint32 `json:"spec_sort"`
Sort uint32 `json:"sort"`
}
2022-01-16 08:56:33 +00:00
func CreateGoodsSerialNo() string {
for {
serialNo := utils.GenSerialNo()
if count, err := NewGoodsQuerySet(DB).SerialNoEq(serialNo).Count(); err == nil && count > 0 {
continue
}
return serialNo
}
}
func CreateGoodsId() uint32 {
for {
orderId := utils.GenUid()
if count, err := NewGoodsQuerySet(DB).GoodsIdEq(orderId).Count(); err == nil && count > 0 {
continue
}
return orderId
}
}
type GoodsListReq struct {
CatId uint32 `json:"cat_id"`
NearestStoreId uint32 `json:"nearest_store_id"` // 用户选择的门店ID
PageIdx int `json:"page_idx"`
PageSize int `json:"page_size"`
2022-01-16 08:56:33 +00:00
}
type GoodsListResp struct {
List []Goods `json:"list"`
CurPage int `json:"cur_page"`
TotalPage int `json:"total_page"`
}
2022-01-16 08:56:33 +00:00
func (m *GoodsListReq) GoodsList() ([]Goods, int, error) {
page := m.PageIdx - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
2022-05-28 06:18:27 +00:00
fmt.Println("CatId:", m.CatId)
2022-01-16 08:56:33 +00:00
var goodsList []Goods
2022-03-07 06:14:05 +00:00
qs := NewGoodsQuerySet(DB).SaleStatusEq(1)
2022-05-28 06:18:27 +00:00
if m.CatId != 0 {
//cat, err := GetGoodsCat(m.CatId)
//if err != nil {
// log.Error().Msgf("cat err:%#v", err)
// return nil, 0, err
//}
var goodsCats []GoodsCat
err := NewGoodsCatQuerySet(DB).PidEq(m.CatId).All(&goodsCats)
if err != nil {
log.Error().Msgf("goods cat err:%#v", err)
return nil, 0, err
}
ids := []uint32{m.CatId}
if len(goodsCats) > 0 {
for i, _ := range goodsCats {
ids = append(ids, goodsCats[i].ID)
}
}
qs = qs.CatIdIn(ids...)
}
2022-01-16 08:56:33 +00:00
count, err := qs.Count()
if err != nil {
logger.Error("err:", err)
return nil, 0, err
}
totalPage := count/m.PageSize + 1
2022-05-28 06:18:27 +00:00
err = qs.OrderDescByCatSort().OrderDescBySort().Offset(page * m.PageSize).Limit(m.PageSize).All(&goodsList)
2022-01-16 08:56:33 +00:00
if err != nil {
logger.Error("err:", err)
return nil, 0, err
}
// 处理ERP库存批量查询
erpIDs := make([]uint32, 0)
for _, g := range goodsList {
if g.ErpCommodityId != 0 {
erpIDs = append(erpIDs, g.ErpCommodityId)
}
}
type ErpStockData struct {
ErpCommodityId uint32
Stock uint32
}
if len(erpIDs) > 0 {
var stocks []ErpStockData
db := DB.Table("erp_stock_commodity").
Select("erp_commodity_id, SUM(count) AS stock").
Where("state = ?", 1).
Group("erp_commodity_id")
// 根据数量区分使用 = 或 IN
if len(erpIDs) == 1 {
db = db.Where("erp_commodity_id = ?", erpIDs[0])
} else {
db = db.Where("erp_commodity_id IN ?", erpIDs)
}
if err := db.Find(&stocks).Error; err != nil {
logger.Error("err:", err)
return nil, 0, err
}
// 构建映射
stockMap := make(map[uint32]uint32, len(stocks))
for _, s := range stocks {
stockMap[s.ErpCommodityId] = s.Stock
}
// 给商品赋值库存
for i := range goodsList {
if goodsList[i].ErpCommodityId != 0 {
goodsList[i].ErpStock = stockMap[goodsList[i].ErpCommodityId]
}
}
}
// 当前门店库存
if m.NearestStoreId != 0 {
var storeStocks []ErpStockData
dbStore := DB.Table("erp_stock_commodity").
Select("erp_commodity_id, SUM(count) AS stock").
Where("state = ? AND store_id = ?", 1, m.NearestStoreId).
Group("erp_commodity_id")
if len(erpIDs) == 1 {
dbStore = dbStore.Where("erp_commodity_id = ?", erpIDs[0])
} else {
dbStore = dbStore.Where("erp_commodity_id IN ?", erpIDs)
}
if err := dbStore.Find(&storeStocks).Error; err != nil {
logger.Error("err:", err)
return nil, 0, err
}
storeStockMap := make(map[uint32]uint32, len(storeStocks))
for _, s := range storeStocks {
storeStockMap[s.ErpCommodityId] = s.Stock
}
for i := range goodsList {
if goodsList[i].ErpCommodityId != 0 {
goodsList[i].CurrentStoreErpStock = storeStockMap[goodsList[i].ErpCommodityId]
}
}
}
2022-01-16 08:56:33 +00:00
return goodsList, totalPage, nil
}
type GoodsDetailReq struct {
GoodsId uint32 `json:"goods_id"`
}
func (m *GoodsDetailReq) GoodsDetail() (*Goods, error) {
var goods Goods
err := NewGoodsQuerySet(DB).GoodsIdEq(m.GoodsId).One(&goods)
if err != nil {
logger.Error("err:", err)
return nil, err
}
2022-05-28 06:18:27 +00:00
var goodsAttributes []GoodsAttribute
2023-09-21 07:08:16 +00:00
err = DB.Table("goods_attribute").
Where("goods_id=?", m.GoodsId).
Order("sort DESC").
2022-05-28 06:18:27 +00:00
Find(&goodsAttributes).Error
if err != nil {
log.Error().Msgf("goods attribute err:%#v", err)
return &goods, err
}
if goods.DiscountList != "" {
discount := new(GoodsDiscount)
err = json.Unmarshal([]byte(goods.DiscountList), discount)
if err != nil {
log.Error().Msgf("goods discount err:%#v", err)
return &goods, err
}
goods.GoodsDiscount = discount
}
cat, err := GetGoodsCat(goods.CatId)
if err != nil {
log.Error().Msgf("goods cat err:%#v", err)
}
goods.GoodsCat = cat
GoodsAttributeListSetSpecValues(goodsAttributes)
GoodsAttributeListSetCombos(goodsAttributes)
goods.Attributes = goodsAttributes
2022-01-16 08:56:33 +00:00
return &goods, nil
}
// 商品分类
// gen:qs
type GoodsCategory struct {
Model
CatId uint32 `json:"cat_id"`
ParentCatId uint32 `json:"parent_cat_id"`
Name string `json:"name"`
Sort uint32 `json:"sort"` // 排序
Level uint32 `json:"level"`
State uint32 `json:"state"`
}
2022-05-28 06:18:27 +00:00
const (
GoodsOrderStateUnPay = "un_pay" // 待付款
GoodsOrderStateOnDeliver = "on_deliver" // 待发货
GoodsOrderStateDelivered = "delivered" // 已发货
GoodsOrderStateReceived = "received" // 已收货
GoodsOrderStateCancel = "cancel" // 已取消
GoodsOrderStateOnRefund = "on_refund" // 退货中
GoodsOrderStateRefunded = "refunded" // 已退货
GoodsOrderStateRefundedCancel = "refunded_cancel" // 退货取消
)
2022-01-16 08:56:33 +00:00
// 商品订单
// gen:qs
type GoodsOrder struct {
Model
OrderId uint32 `json:"order_id" gorm:"unique_index"` // 订单 id
NearestStoreId uint32 `json:"nearest_store_id"` // 定位最近的门店id
NearestStoreName string `json:"nearest_store_name"` // 定位最近的门店名称
SerialNo string `json:"serial_no" gorm:"unique_index"` // 序列号
Uid uint32 `json:"uid" gorm:"index"` // 用户id
Amount uint32 `json:"amount"` // 订单金额
Quantity uint32 `json:"quantity"` // 购买商品的数量
TotalDiscount float64 `json:"total_discount"` // 订单总优惠
PayType uint32 `json:"pay_type"` // 支付方式 1-rm 2-vm
PayTime time.Time `json:"pay_time"` // 支付时间
PayStatus uint32 `json:"pay_status"` // 支付状态 1-待支付 2-已支付 3-失败
State string `json:"state"` //
AddressId uint32 `json:"address_id"` // 收货地址
DeliveryExtraInfo string `json:"delivery_extra_info"` // 物流备注
DeliveryFee uint32 `json:"delivery_fee"` // 物流费用
DeliveryTrackingNo string `json:"delivery_tracking_no"` // 物流单号
DeliveryCompany string `json:"delivery_company"` // 物流公司
DeliveryCompanyNo string `json:"delivery_company_no"` // 物流公司编号
DeliveryStatus uint32 `json:"delivery_status"` // 物流状态 1-待发货 2-已发货 3-已收货
Rm uint32 `json:"rm"` // 人民币
Vm uint32 `json:"vm"` // 积分
DeliverStoreId uint32 `json:"deliver_store_id"` // 发货门店
DeliverTime time.Time `json:"deliver_time"` // 发货时间
RefundExpressCompany string `json:"refund_express_company"` // 退货物流公司
RefundExpressCompanyNo string `json:"refund_express_company_no"` // 退货物流公司编号
RefundExpressNo string `json:"refund_express_no"` // 退货物流单号
RefundReason string `json:"refund_reason" gorm:"type:text;"` // 退货原因
ReceivedTime time.Time `json:"received_time"` // 签收时间
VersionId uint64 `json:"version_id"` // 乐观锁
GoodsOrderCommodities []GoodsOrderCommodity `json:"goods_order_commodities" gorm:"-"` // 商城订单商品信息
DeliverStore *Store `json:"deliver_store" gorm:"-"`
UserAddress *UserAddress `json:"user_address" gorm:"-"`
// 以下字段是冗余,暂时用不上
GoodsId uint32 `json:"goods_id" gorm:"index"` // 商品id
Discount uint32 `json:"discount"` // 折扣
GoodsAttributeId uint32 `json:"goods_attribute_id"` //
GoodsAttributeComboId uint32 `json:"goods_attribute_combo_id"` //
CouponCode string `json:"coupon_code"` //
CouponName string `json:"coupon_name"` // 优惠券名称
CouponDiscount uint32 `json:"coupon_discount"` // 优惠券抵扣
}
// 商城订单商品表
// gen:qs
type GoodsOrderCommodity struct {
Model
GoodsOrderId uint32 `json:"goods_order_id" gorm:"index"` // 商品订单id
GoodsId uint32 `json:"goods_id"` // 商品id
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // ERP商品id
Quantity uint32 `json:"quantity"` // 销售数量
PriceRm uint32 `json:"price_rm"` // 价格:人民币
PriceVm uint32 `json:"price_vm"` // 价格:积分
Discount uint32 `json:"discount"` // 折扣
GoodsAttributeId uint32 `json:"goods_attribute_id"` //
GoodsAttributeComboId uint32 `json:"goods_attribute_combo_id"` //
CouponID uint32 `json:"coupon_id"` // 优惠券ID
CouponCode string `json:"coupon_code"` // 优惠券券码
CouponName string `json:"coupon_name"` // 优惠券名称
CouponDiscount uint32 `json:"coupon_discount"` // 优惠券抵扣
2022-03-07 06:14:05 +00:00
2022-05-28 06:18:27 +00:00
Goods *Goods `json:"goods" gorm:"-"`
GoodsAttribute *GoodsAttribute `json:"goods_attribute" gorm:"-"`
2022-01-16 08:56:33 +00:00
}
func CreateGoodsOrderSerialNo() string {
for {
serialNo := utils.GenSerialNo()
if count, err := NewGoodsOrderQuerySet(DB).SerialNoEq(serialNo).Count(); err == nil && count > 0 {
continue
}
return serialNo
}
}
func CreateGoodsOrderId() uint32 {
for {
orderId := utils.GenUid()
if count, err := NewGoodsOrderQuerySet(DB).OrderIdEq(orderId).Count(); err == nil && count > 0 {
continue
}
return orderId
}
}
type GoodsOrderListReq struct {
2022-05-28 06:18:27 +00:00
PageIdx int `json:"page_idx"`
PageSize int `json:"page_size"`
State string `json:"state"`
//DeliveryStatus uint32 `json:"delivery_status"` // 物流状态 1-待发货 2-已发货 3-已收货
2022-01-16 08:56:33 +00:00
}
func (m *GoodsOrderListReq) OrderList(uid uint32) ([]GoodsOrder, int, error) {
page := m.PageIdx - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
var list []GoodsOrder
2022-05-28 06:18:27 +00:00
qs := NewGoodsOrderQuerySet(DB).PayStatusEq(PayStatusOK).UidEq(uid)
2022-01-16 08:56:33 +00:00
2022-05-28 06:18:27 +00:00
//if uid != 0 {
// qs = qs.UidEq(uid)
//}
//if m.DeliveryStatus != 0 {
// qs = qs.DeliveryStatusEq(m.DeliveryStatus)
//}
if m.State != "" {
qs = qs.StateEq(m.State)
2022-03-07 06:14:05 +00:00
}
2022-01-16 08:56:33 +00:00
count, err := qs.Count()
if err != nil {
logger.Error("err:", err)
return nil, 0, err
}
totalPage := count/m.PageSize + 1
// 查询订单
2022-03-07 06:14:05 +00:00
err = qs.OrderDescByID().Offset(page * m.PageSize).Limit(m.PageSize).All(&list)
2022-01-16 08:56:33 +00:00
if err != nil {
logger.Error("err:", err)
return nil, 0, err
}
// 关联查询订单商品
if err = SetGoodsOrderCommoditiesWithAddress(list); err != nil {
logger.Error("set commodities err:", err)
return nil, 0, err
}
2022-03-07 06:14:05 +00:00
2022-01-16 08:56:33 +00:00
return list, totalPage, nil
}
func SetGoodsOrderCommoditiesWithAddress(orders []GoodsOrder) error {
if len(orders) == 0 {
return nil
}
// 收集订单ID、收货地址ID
orderIds := make([]uint32, 0, len(orders))
addressIds := make([]uint32, 0)
for _, o := range orders {
orderIds = append(orderIds, o.OrderId)
if o.AddressId > 0 {
addressIds = append(addressIds, o.AddressId)
}
}
// 查出所有订单商品
var commodities []GoodsOrderCommodity
if err := DB.Model(&GoodsOrderCommodity{}).
Where("goods_order_id IN (?)", orderIds).
Find(&commodities).Error; err != nil {
return err
}
// 批量查商品、属性
goodsIds := make([]uint32, 0)
attributeIds := make([]uint32, 0)
for _, c := range commodities {
if c.GoodsId > 0 {
goodsIds = append(goodsIds, c.GoodsId)
}
if c.GoodsAttributeId > 0 {
attributeIds = append(attributeIds, c.GoodsAttributeId)
}
}
goodsMap := GetGoodsMapByIds(goodsIds)
attributeMap, err := GetGoodsAttributeMap(attributeIds)
if err != nil {
log.Error().Msgf("attribute map err:%#v", err)
return err
}
// 填充商品和属性
for i := range commodities {
if g, ok := goodsMap[commodities[i].GoodsId]; ok {
commodities[i].Goods = &g
}
if a, ok := attributeMap[commodities[i].GoodsAttributeId]; ok {
commodities[i].GoodsAttribute = &a
}
}
// 按订单分组
orderMap := make(map[uint32][]GoodsOrderCommodity)
for _, c := range commodities {
orderMap[c.GoodsOrderId] = append(orderMap[c.GoodsOrderId], c)
}
// 批量查收货地址
addressMap := make(map[uint32]UserAddress)
if len(addressIds) > 0 {
var addresses []UserAddress
if err := DB.Unscoped().
Model(&UserAddress{}).
Where("id IN (?)", addressIds).
Find(&addresses).Error; err != nil {
return err
}
for _, addr := range addresses {
addressMap[addr.ID] = addr
}
}
// 塞回订单
for i := range orders {
if list, ok := orderMap[orders[i].OrderId]; ok {
orders[i].GoodsOrderCommodities = list
}
if addr, ok := addressMap[orders[i].AddressId]; ok {
orders[i].UserAddress = &addr
}
}
return nil
}
2022-01-16 08:56:33 +00:00
type GoodsOrderDetailReq struct {
OrderId uint32 `json:"order_id"`
}
func (m *GoodsOrderDetailReq) OrderDetail(uid uint32) (*GoodsOrder, error) {
var order GoodsOrder
2022-05-28 06:18:27 +00:00
qs := NewGoodsOrderQuerySet(DB).OrderIdEq(m.OrderId).UidEq(uid)
2022-01-16 08:56:33 +00:00
// 查订单主表
2022-01-16 08:56:33 +00:00
err := qs.One(&order)
2022-03-07 06:14:05 +00:00
if err != nil && err != RecordNotFound {
2022-01-16 08:56:33 +00:00
logger.Error("err:", err)
return nil, err
}
2022-05-28 06:18:27 +00:00
// 用统一的函数,填充商品和收货地址
if err := SetGoodsOrderCommoditiesWithAddress([]GoodsOrder{order}); err != nil {
logger.Error("set commodities/address err:", err)
2022-05-28 06:18:27 +00:00
return nil, err
}
// 每个商品做附加处理
for i := range order.GoodsOrderCommodities {
commodity := &order.GoodsOrderCommodities[i]
if commodity.Goods != nil && commodity.Goods.DiscountList != "" {
discount := new(GoodsDiscount)
err = json.Unmarshal([]byte(commodity.Goods.DiscountList), discount)
if err != nil {
log.Error().Msgf("goods discount err:%#v", err)
return nil, err
}
commodity.Goods.GoodsDiscount = discount
2022-05-28 06:18:27 +00:00
}
2022-06-14 06:07:15 +00:00
// 属性规格 & 组合
if commodity.GoodsAttribute != nil {
attributes := []GoodsAttribute{*commodity.GoodsAttribute}
GoodsAttributeListSetSpecValues(attributes)
2022-05-28 06:18:27 +00:00
combo, err := GetCombo(commodity.GoodsAttributeComboId)
if err != nil {
log.Error().Msgf("goods attribute combo err:%#v", err)
return nil, err
}
if len(attributes) > 0 {
attributes[0].Combo = combo
}
commodity.Goods.Attributes = attributes
}
2022-03-07 06:14:05 +00:00
}
2022-06-03 03:30:03 +00:00
// 发货门店
2022-06-03 03:30:03 +00:00
store, err := GetStore(order.DeliverStoreId)
if err != nil {
logger.Error("store err:", err)
}
order.DeliverStore = store
2022-01-16 08:56:33 +00:00
return &order, nil
}
2022-03-07 06:14:05 +00:00
func OrderDeductionUserVm(uid uint32, userVmAmount, vm int, gdb *gorm.DB) error {
sql := fmt.Sprintf("UPDATE user_vm SET vm = vm+? WHERE uid=? ")
err := gdb.Exec(sql, vm, uid).Error
if err != nil {
logger.Error("err:", err)
return err
}
vmRecord := &UserVmRecord{
Uid: uid,
BeforeVm: uint32(userVmAmount),
AfterVm: uint32(int(userVmAmount) + vm),
Alter: vm,
Event: "exchange_goods",
Describe: "兑换礼品",
}
err = gdb.Create(vmRecord).Error
if err != nil {
logger.Error("err:", err)
return err
}
return nil
}
2022-05-28 06:18:27 +00:00
func OrderUpdateGoodsStock(attributeId, count uint32, gdb *gorm.DB) error {
sql := fmt.Sprintf("UPDATE goods_attribute SET stock=stock-%d,sold_count=sold_count+%d WHERE id=%d ",
count, count, attributeId)
2022-03-07 06:14:05 +00:00
err := gdb.Exec(sql).Error
if err != nil {
logger.Error("err:", err)
return err
}
return nil
}
func GetGoodsMapByIds(ids []uint32) map[uint32]Goods {
goodsMap := make(map[uint32]Goods, 0)
if len(ids) == 0 {
return goodsMap
}
var goodsList []Goods
err := NewGoodsQuerySet(DB).GoodsIdIn(ids...).All(&goodsList)
if err != nil {
logger.Error("err:", err)
return goodsMap
}
for i, _ := range goodsList {
goodsMap[goodsList[i].GoodsId] = goodsList[i]
}
return goodsMap
}
2022-05-28 06:18:27 +00:00
func GetGoodsAttributeMap(ids []uint32) (map[uint32]GoodsAttribute, error) {
attributeMap := make(map[uint32]GoodsAttribute, 0)
if len(ids) == 0 {
return attributeMap, nil
}
var attributes []GoodsAttribute
err := NewGoodsAttributeQuerySet(DB).IDIn(ids...).All(&attributes)
if err != nil {
log.Error().Msgf("goods attribute err:%#v", err)
return attributeMap, err
}
for i, _ := range attributes {
attributeMap[attributes[i].ID] = attributes[i]
}
return attributeMap, nil
2022-03-07 06:14:05 +00:00
}
type MallUserVmRecordReq struct {
PageIdx int `json:"page_idx"`
PageSize int `json:"page_size"`
VmType uint32 `json:"vm_type"` // 默认0-正常查询1-查询7天内即将过期积分
2022-03-07 06:14:05 +00:00
//Uid uint32 `json:"uid"`
}
type MallUserVmRecordResp struct {
List []UserVmRecord `json:"list"`
CurPage int `json:"cur_page"`
TotalPage int `json:"total_page"`
}
2022-03-07 06:14:05 +00:00
func (m *MallUserVmRecordReq) UserVmRecordList(uid uint32) ([]UserVmRecord, int, error) {
page := m.PageIdx - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
var list []UserVmRecord
qs := NewUserVmRecordQuerySet(DB)
if uid != 0 {
qs = qs.UidEq(uid)
}
if m.VmType != 0 {
now := time.Now()
year, month, day := now.Date()
startTime := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
endTime := time.Date(year, month, day, 23, 59, 59, 0, time.UTC).AddDate(0, 0, 7)
qs = qs.ExpiryDateAtGte(startTime)
qs = qs.ExpiryDateLte(endTime)
qs = qs.AlterGt(0)
qs = qs.AlterNeUsedVm()
}
2022-03-07 06:14:05 +00:00
count, err := qs.Count()
if err != nil {
logger.Error("err:", err)
return nil, 0, err
}
totalPage := count/m.PageSize + 1
err = qs.OrderDescByID().Offset(page * m.PageSize).Limit(m.PageSize).All(&list)
if err != nil && err != RecordNotFound {
logger.Error("err:", err)
return nil, 0, err
}
for i, _ := range list {
list[i].ExpiryVm = list[i].Alter - list[i].UsedVm
}
2022-03-07 06:14:05 +00:00
return list, totalPage, nil
}
type MallGoodsOrderConfirmReceiptReq struct {
OrderId uint32 `json:"order_id"`
}
func (m *MallGoodsOrderConfirmReceiptReq) MallGoodsOrderConfirmReceipt(uid uint32) error {
_, err := NewGoodsOrderQuerySet(DB).OrderIdEq(m.OrderId).UidEq(uid).GetUpdater().
2022-05-28 06:18:27 +00:00
SetState(GoodsOrderStateReceived).UpdateNum()
2022-03-07 06:14:05 +00:00
if err != nil {
logger.Error("err:", err)
return err
}
return nil
}
2022-05-28 06:18:27 +00:00
type MallGoodsSpecReq struct {
GoodsId uint32 `json:"goods_id"` // 商品id
SpecValueIndex string `json:"spec_value_index"` // 1,3,5
GoodsAttribute *GoodsAttribute
}
func (r *MallGoodsSpecReq) Spec() error {
//GoodsAttribute{}
indexSort, err := IndexSortString(r.SpecValueIndex)
if err != nil {
log.Error().Msgf("index sort:%#v", err)
return err
}
r.SpecValueIndex = indexSort
err = NewGoodsAttributeQuerySet(DB).GoodsIdEq(r.GoodsId).SpecValueIndexEq(r.SpecValueIndex).One(r.GoodsAttribute)
if err != nil && err != RecordNotFound {
log.Error().Msgf("goods attribute err:%#v", err)
return err
}
if err == RecordNotFound {
log.Error().Msg("goods attribute not found")
return errors.New("not_found")
}
var combos []GoodsAttributeCombo
err = NewGoodsAttributeComboQuerySet(DB).GoodsAttributeIdEq(r.GoodsAttribute.ID).All(&combos)
if err != nil {
log.Error().Msgf("goods attribute combo err:%#v", err)
return err
}
return nil
}
func IndexSortString(n string) (string, error) {
numStrings := strings.Split(n, ",")
nums := make([]int, 0, len(numStrings))
for i, _ := range numStrings {
num, err := strconv.Atoi(numStrings[i])
if err != nil {
logger.Error("num err:", err)
return "", err
}
nums = append(nums, num)
}
ns := ""
sort.Ints(nums)
for i, _ := range nums {
ns += fmt.Sprintf("%d,", nums[i])
}
return ns[:len(ns)-1], nil
}
func GetGoods(id uint32) (Goods, error) {
var goods Goods
err := NewGoodsQuerySet(DB).GoodsIdEq(id).One(&goods)
if err != nil {
log.Error().Msgf("get goods err:%#v", err)
return goods, err
}
return goods, err
}
func GetGoodsCat(id uint32) (*GoodsCat, error) {
var cat GoodsCat
err := DB.Table("goods_cat").Where("id=?", id).Find(&cat).Error
if err != nil {
log.Error().Msgf("goods cat err:%#v", err)
return &cat, err
}
if cat.Pid != 0 {
var pCat GoodsCat
err := DB.Table("goods_cat").Where("id=?", cat.Pid).Find(&pCat).Error
if err != nil {
log.Error().Msgf("goods cat err:%#v", err)
return &cat, err
}
pCat.SubCats = []GoodsCat{cat}
return &pCat, nil
}
return &cat, nil
}
func (g *Goods) SetDiscount() error {
discount := new(GoodsDiscount)
err := json.Unmarshal([]byte(g.DiscountList), discount)
if err != nil {
log.Error().Msgf("set goods discount:%#v", err)
return err
}
2022-06-03 03:30:03 +00:00
g.GoodsDiscount = discount
2022-05-28 06:18:27 +00:00
return nil
}
func (g *Goods) GetUserDiscount(u *User) (uint32, error) {
if g.GoodsDiscount == nil {
err := g.SetDiscount()
if err != nil {
log.Error().Msgf("set discount err:%#v", err)
return 100, err
}
}
switch u.MemberLevel {
case MemberLevelGold:
return g.GoodsDiscount.Gold, nil
case MemberLevelPlatinum:
2022-06-03 03:30:03 +00:00
return g.GoodsDiscount.Platinum, nil
2022-05-28 06:18:27 +00:00
case MemberLevelBlackGold:
2022-06-03 03:30:03 +00:00
return g.GoodsDiscount.BlackGold, nil
2022-05-28 06:18:27 +00:00
}
//return 100, errors.New("member level err")
return 100, nil
}
func GoodsAttributeListSetSpecValues(attributes []GoodsAttribute) {
for i, _ := range attributes {
err := json.Unmarshal([]byte(attributes[i].SpecValueList), &attributes[i].SpecValues)
if err != nil {
log.Error().Msgf("spec value err:%#v", err)
continue
}
}
}
func GoodsAttributeListSetCombos(attributes []GoodsAttribute) {
ids := make([]uint32, 0)
for i, _ := range attributes {
ids = append(ids, attributes[i].ID)
}
comboMap := GetGoodsAttributeComboMap(ids)
for i, _ := range attributes {
v, ok := comboMap[attributes[i].ID]
if ok {
attributes[i].Combos = v
}
}
}
func GetGoodsAttributeComboMap(attributeIds []uint32) map[uint32][]GoodsAttributeCombo {
attributeMap := make(map[uint32][]GoodsAttributeCombo, 0)
if len(attributeIds) == 0 {
return attributeMap
}
var combos []GoodsAttributeCombo
err := DB.Table("goods_attribute_combo").Where("goods_attribute_id in (?)", attributeIds).
Find(&combos).Error
if err != nil {
log.Error().Msgf("goods attribute combo err:%#v", err)
return attributeMap
}
for i, _ := range combos {
attributeMap[combos[i].GoodsAttributeId] =
append(attributeMap[combos[i].GoodsAttributeId], combos[i])
}
return attributeMap
}
func GetCombo(id uint32) (*GoodsAttributeCombo, error) {
var combo GoodsAttributeCombo
err := NewGoodsAttributeComboQuerySet(DB).IDEq(id).One(&combo)
if err != nil {
log.Error().Msgf("goods attribute combo err:%#v", err)
return &combo, err
}
return &combo, nil
}
func GetStore(id uint32) (*Store, error) {
var store Store
err := NewStoreQuerySet(DB).IDEq(id).One(&store)
if err != nil {
log.Error().Msgf("store err:%#v", err)
return nil, err
}
return &store, nil
}
2022-06-03 03:30:03 +00:00
// 发货
const (
DeliverTaskStateOnDeliver = "on_deliver" // 待发货
DeliverTaskStateDelivered = "delivered" // 已发货
DeliverTaskStateCancel = "cancel" // 已取消
DeliverTaskStateComplete = "complete" // 已完成
)
// gen:qs
type DeliverTask struct {
Model
Uid uint32 `json:"uid" gorm:"index"`
UserAddressId uint32 `json:"user_address_id" gorm:"index"` // 用户地址
State string `json:"state"` // 状态
2022-06-14 06:07:15 +00:00
OrderType uint32 `json:"order_type"` // 1-借卡 2-商城购买 3-收回卡
2022-06-03 03:30:03 +00:00
StoreId uint32 `json:"store_id"` //
DeliverTime time.Time `json:"deliver_time"` // 发货时间
DeliverStoreId uint32 `json:"deliver_store_id" gorm:"index"` // 发货门店
// deliver_task
}
// gen:qs
type DeliverTaskSub struct {
Model
Uid uint32 `json:"uid"`
DeliverTaskId uint32 `json:"deliver_task_id" gorm:"index"`
UserAddressId uint32 `json:"user_address_id" gorm:"index"` // 用户地址
State string `json:"state"` // 状态
OrderType uint32 `json:"order_type"` // 1-借卡 2-商城购买 3-收回卡
OrderId uint32 `json:"order_id" gorm:"index"` // 订单id
StoreId uint32 `json:"store_id"` //
GoodsOrder *GoodsOrder `json:"goods_order" gorm:"-"`
Order *Order `json:"order" gorm:"-"`
ShareCardRetrieve *ShareCardRetrieve `json:"share_card_retrieve" gorm:"-"`
// deliver_task_sub
}
func (m *DeliverTaskSub) Add() error {
//exist, err := QueryRecordExist(
// fmt.Sprintf("SELECT * FROM deliver_task WHERE user_address_id = %d AND state='%s'",
// m.UserAddressId, DeliverTaskStateOnDeliver))
//if err != nil {
// log.Error().Msgf("deliver_task exist err:%#v", err)
// return err
//}
//var deliver DeliverTask
//if exist {
// err = NewDeliverTaskQuerySet(DB).UserAddressIdEq(m.UserAddressId).
// StateEq(DeliverTaskStateOnDeliver).One(&deliver)
// if err != nil {
// log.Error().Msgf("deliver err:%#v", err)
// return err
// }
// m.DeliverTaskId = deliver.ID
// m.State = DeliverTaskStateOnDeliver
//
// err = DB.Create(m).Error
// if err != nil {
// log.Error().Msgf("create deliver task sub err:%#v", err)
// return err
// }
// return nil
//}
2022-06-14 06:07:15 +00:00
//var deliver DeliverTask
//err := NewDeliverTaskQuerySet(DB).UserAddressIdEq(m.UserAddressId).
// StateEq(DeliverTaskStateOnDeliver).OrderTypeEq(1).One(&deliver)
//if err != nil && err != RecordNotFound {
// log.Error().Msgf("deliver err:%#v", err)
// return err
//}
//
//if err == RecordNotFound || (deliver.StoreId != 0 && deliver.StoreId != m.StoreId) {
//
// begin := DB.Begin()
// deliver = DeliverTask{
// Uid: m.Uid,
// UserAddressId: m.UserAddressId,
// State: DeliverTaskStateOnDeliver,
// StoreId: m.StoreId,
// }
// err = begin.Create(&deliver).Error
// if err != nil {
// begin.Rollback()
// log.Error().Msgf("create deliver task err:%#v", err)
// return err
// }
//
// m.DeliverTaskId = deliver.ID
// m.State = DeliverTaskStateOnDeliver
// err = begin.Create(m).Error
// if err != nil {
// begin.Rollback()
// log.Error().Msgf("create deliver task sub err:%#v", err)
// return err
// }
// err = begin.Commit().Error
// if err != nil {
// begin.Rollback()
// log.Error().Msgf("commit deliver task sub err:%#v", err)
// return err
// }
// return nil
//}
//
//m.DeliverTaskId = deliver.ID
//m.State = DeliverTaskStateOnDeliver
//
//err = DB.Create(m).Error
//if err != nil {
// log.Error().Msgf("create deliver task sub err:%#v", err)
// return err
//}
//if deliver.StoreId == 0 {
// err = NewDeliverTaskQuerySet(DB).IDEq(deliver.ID).GetUpdater().SetStoreId(m.StoreId).Update()
// if err != nil {
// logger.Error("deliver task err:", err)
// }
//}
2022-06-03 03:30:03 +00:00
var deliver DeliverTask
err := NewDeliverTaskQuerySet(DB).UserAddressIdEq(m.UserAddressId).
2022-06-14 06:07:15 +00:00
StateEq(DeliverTaskStateOnDeliver).OrderTypeEq(m.OrderType).StoreIdEq(m.StoreId).One(&deliver)
2022-06-03 03:30:03 +00:00
if err != nil && err != RecordNotFound {
log.Error().Msgf("deliver err:%#v", err)
return err
}
2022-06-14 06:07:15 +00:00
if err == RecordNotFound {
2022-06-03 03:30:03 +00:00
begin := DB.Begin()
deliver = DeliverTask{
Uid: m.Uid,
UserAddressId: m.UserAddressId,
State: DeliverTaskStateOnDeliver,
StoreId: m.StoreId,
2022-06-14 06:07:15 +00:00
OrderType: m.OrderType,
2022-06-03 03:30:03 +00:00
}
err = begin.Create(&deliver).Error
if err != nil {
begin.Rollback()
log.Error().Msgf("create deliver task err:%#v", err)
return err
}
m.DeliverTaskId = deliver.ID
m.State = DeliverTaskStateOnDeliver
2022-06-14 06:07:15 +00:00
//m.OrderType = deliver.OrderType
2022-06-03 03:30:03 +00:00
err = begin.Create(m).Error
if err != nil {
begin.Rollback()
log.Error().Msgf("create deliver task sub err:%#v", err)
return err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
log.Error().Msgf("commit deliver task sub err:%#v", err)
return err
}
return nil
}
m.DeliverTaskId = deliver.ID
m.State = DeliverTaskStateOnDeliver
err = DB.Create(m).Error
if err != nil {
log.Error().Msgf("create deliver task sub err:%#v", err)
return err
}
2022-06-14 06:07:15 +00:00
//if deliver.StoreId == 0 {
// err = NewDeliverTaskQuerySet(DB).IDEq(deliver.ID).GetUpdater().SetStoreId(m.StoreId).Update()
// if err != nil {
// logger.Error("deliver task err:", err)
// }
//}
2022-06-03 03:30:03 +00:00
return nil
}
func UpdateDeliverTaskSubStateCancel(orderId uint32) {
var sub DeliverTaskSub
err := DB.Table("deliver_task_sub").Where("order_id=?", orderId).Find(&sub).Error
if err != nil {
log.Error().Msgf("deliver task sub err:%#v", err)
return
}
//begin := DB.Begin()
err = DB.Table("deliver_task_sub").Where("order_id=?", orderId).
Update("state", DeliverTaskStateCancel).Error
if err != nil {
//begin.Rollback()
log.Error().Msgf("deliver task sub err:%#v", err)
return
}
exist, err := QueryRecordExist(
fmt.Sprintf("SELECT * FROM deliver_task_sub WHERE deliver_task_id=%d AND state='%s'",
sub.DeliverTaskId, DeliverTaskStateOnDeliver))
if err != nil {
//begin.Rollback()
logger.Error("deliver task sub exist err:", err)
return
}
if !exist {
err := DB.Table("deliver_task").Where("id=?", sub.DeliverTaskId).
Update("state", DeliverTaskStateCancel).Error
if err != nil {
//begin.Rollback()
log.Error().Msgf("deliver task sub err:%#v", err)
return
}
}
//err = begin.Commit().Error
//if err != nil {
// logger.Error("commit err:", err)
//}
}
2022-11-26 08:52:05 +00:00
func ParaToSubstance(c *gin.Context, sign string) (string, error) {
urlString := c.Request.URL.String()
urlPara, err := url.QueryUnescape(urlString)
if err != nil {
return "", errors.New("url query unescape err")
}
if !strings.Contains(urlPara, "/api/v1/wxpay/notice?") {
return "", errors.New("url err")
}
para := strings.Replace(urlPara, "/api/v1/wxpay/notice?", "", -1)
//fmt.Println("para--", para)
conspire := strings.Split(para, "&")
signConspire := make([]string, 0, len(conspire))
for i, _ := range conspire {
if !strings.Contains(conspire[i], "sign=") {
//fmt.Println("conspire---------", conspire[i])
signConspire = append(signConspire, conspire[i])
}
}
sort.Strings(signConspire)
//signDataJson2, _ := json.MarshalIndent(&signData, "", " ")
//fmt.Println("signDataJson2", string(signDataJson2))
signStr := strings.Join(signConspire, "&")
//signStr = signStr + "&key=" + payKey
logger.Info("签字符串1 :", signStr)
return signStr, nil
}
2023-09-20 10:05:53 +00:00
func GetGoodsFirstSkuCombo(goodsId []uint32) []GoodsAttributeCombo {
var list []GoodsAttributeCombo
//查询每个商品按sort字端排序的最大的一个sku的价格
err := DB.
Raw(`
SELECT b.*
FROM (SELECT id
FROM goods_attribute d
INNER JOIN (SELECT goods_id, MAX(sort) AS max_sort FROM goods_attribute GROUP BY goods_id) c
ON c.goods_id = d.goods_id AND c.max_sort = d.sort) AS a
INNER JOIN goods_attribute_combo b ON a.id = b.goods_attribute_id
WHERE b.goods_id IN (?)
GROUP BY b.goods_id
`, goodsId).
Scan(&list).
Error
if err != nil {
logger.Error("get goods first sku failed", err)
return nil
}
return list
}