package controller import ( "errors" "github.com/codinl/go-logger" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" "mh-server/lib/auth" "mh-server/lib/status" "mh-server/lib/utils" "mh-server/lib/wxpay" "mh-server/model" "time" ) func MallGoodsList(c *gin.Context) { req := model.GoodsListReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } list, total, err := req.GoodsList() if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } var ids []uint32 for _, goods := range list { ids = append(ids, goods.GoodsId) } if len(ids) > 0 { cm := model.GetGoodsFirstSkuCombo(ids) if cm != nil { for j, combo := range cm { for i, goods := range list { if combo.GoodsId == goods.GoodsId { list[i].Combo = &cm[j] } } } } } ret := map[string]interface{}{ "list": list, "cur_page": req.PageIdx, "total_page": total, } RespOK(c, ret) return } func MallGoodsDetail(c *gin.Context) { req := model.GoodsDetailReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } detail, err := req.GoodsDetail() if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } cm := model.GetGoodsFirstSkuCombo([]uint32{detail.GoodsId}) if len(cm) > 0 { detail.Combo = &cm[0] } RespOK(c, detail) return } func MallOrderCreate(c *gin.Context) { req := struct { GoodsId uint32 `json:"goods_id" binding:"required"` // 商品id GoodsAttributeId uint32 `json:"goods_attribute_id" binding:"required"` // 规格id GoodsAttributeComboId uint32 `json:"goods_attribute_combo_id" binding:"required"` // 套餐id Quantity uint32 `json:"quantity" binding:"required"` // 购买数量 //PayType uint32 `json:"pay_type" binding:"required"` // 支付方式 AddressId uint32 `json:"address_id" binding:"required"` // 收货地址 DeliveryExtraInfo string `json:"delivery_extra_info"` // 收货备注 }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } user := model.GetUserByUid(uc.Uid) err := user.SetVm() if err != nil { log.Error().Msgf("set vm err:%#v", err) RespJson(c, status.InternalServerError, nil) return } // 商品是否存在 var goods model.Goods err = model.NewGoodsQuerySet(model.DB).GoodsIdEq(req.GoodsId).One(&goods) if err != nil { logger.Error("err:", err) RespJson(c, status.BadRequest, nil) return } // 商品在售状态 if goods.SaleStatus != model.SaleStatusYes { logger.Error("err:", err) RespJson(c, status.GoodsNotSale, nil) return } var attribute model.GoodsAttribute err = model.NewGoodsAttributeQuerySet(model.DB).IDEq(req.GoodsAttributeId).One(&attribute) if err != nil { log.Error().Msgf("attribute err:%#v", err) RespJson(c, status.InternalServerError, nil) return } // 库存不足 //if goods.Stock < req.Quantity { if attribute.Stock < req.Quantity { logger.Error("err:", err) RespJson(c, status.OrderStockOut, nil) return } // 检测收货地址是否正确 count, _ := model.NewUserAddressQuerySet(model.DB).UidEq(uc.Uid).IDEq(req.AddressId).Count() if count != 1 { logger.Error("err:", err) RespJson(c, status.BadRequest, "收货地址错误") return } //// 计算总金额 //amount := uint32(0) //if req.PayType == model.PayTypeRm { // amount = req.Quantity * goods.PriceRm //} else if req.PayType == model.PayTypeVm { // amount = req.Quantity * goods.PriceVm //} discount, err := goods.GetUserDiscount(user) if err != nil { log.Error().Msgf("combo err:%#v", err) RespJson(c, status.InternalServerError, nil) return } var combo model.GoodsAttributeCombo err = model.NewGoodsAttributeComboQuerySet(model.DB).IDEq(req.GoodsAttributeComboId).One(&combo) if err != nil { log.Error().Msgf("combo err:%#v", err) RespJson(c, status.InternalServerError, nil) return } totalVm := combo.PriceVm * req.Quantity totalRm := (combo.PriceRm*req.Quantity*discount + 5) / model.Rmb if combo.PriceVm > 0 && user.UserVm.Vm < totalVm { log.Error().Msgf("vm not enough") RespJson(c, status.UserVmNotEnough, nil) return } // 开启事务 tx := model.TransactionBegin() // 订单创建逻辑 order := model.GoodsOrder{ OrderId: model.CreateGoodsOrderId(), SerialNo: model.CreateGoodsOrderSerialNo(), Uid: uc.Uid, GoodsId: req.GoodsId, Rm: totalRm, Vm: totalVm, Quantity: req.Quantity, //PayType: req.PayType, PayStatus: model.PayStatusInit, AddressId: req.AddressId, DeliveryExtraInfo: req.DeliveryExtraInfo, DeliveryFee: goods.DeliveryFee, DeliveryStatus: model.DeliveryStatusUnDeliver, GoodsAttributeId: req.GoodsAttributeId, GoodsAttributeComboId: req.GoodsAttributeComboId, Discount: discount, State: model.GoodsOrderStateUnPay, } // 减少库存 // 确认下是在支付后减少,还是下单后 //if req.PayType == model.PayTypeVm { //var userVm model.UserVm //err = model.NewUserVmQuerySet(model.DB).UidEq(uc.Uid).One(&userVm) //if err != nil { // tx.Rollback() // logger.Error("err:", err) // RespJson(c, status.InternalServerError, nil) // return //} //if userVm.Vm < amount { // tx.Rollback() // logger.Error("err:", err) // RespJson(c, status.UserVmNotEnough, nil) // return //} //err := model.OrderDeductionUserVm(uc.Uid, int(userVm.Vm), int(amount)*-1, tx) //if err != nil { // tx.Rollback() // logger.Error("err:", err) // RespJson(c, status.InternalServerError, nil) // return //} //} //if goods.DeliveryFee == 0 { if combo.PriceRm == 0 { order.PayTime = time.Now() order.PayStatus = model.PayStatusOK order.State = model.GoodsOrderStateOnDeliver err = order.Create(tx) if err != nil { logger.Error("err:", err) tx.Rollback() RespJson(c, status.InternalServerError, nil) return } err = model.OrderUpdateGoodsStock(req.GoodsAttributeId, order.Quantity, tx) if err != nil { tx.Rollback() logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } err = model.UserVmUpdate(order.Uid, int(order.Vm)*-1, model.VmEventBuyGoods, "购买商品积分抵扣") if err != nil { tx.Rollback() logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } err = tx.Commit().Error if err != nil { tx.Rollback() logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } sub := model.DeliverTaskSub{ Uid: order.Uid, UserAddressId: order.AddressId, OrderType: 2, OrderId: order.OrderId, StoreId: 13, } err = sub.Add() if err != nil { logger.Error("deliver task sub add err:", err) } ret := map[string]interface{}{ "order_id": order.ID, "order": order, } RespOK(c, ret) return } err = order.Create(tx) if err != nil { logger.Error("err:", err) tx.Rollback() RespJson(c, status.InternalServerError, nil) return } err = tx.Commit().Error if err != nil { tx.Rollback() logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } //var user model.User //err = model.NewUserQuerySet(model.DB).UidEq(uint32(order.Uid)).One(&user) //if err != nil { // logger.Error("Order err:", err) // RespJson(c, status.InternalServerError, nil) // return //} configInfo, err := model.PayConfigInfo() if err != nil { logger.Error(err) RespJson(c, status.InternalServerError, nil) return } //webPay, err := wxpay.WebPay(order.SerialNo, order.Rm, user.WxOpenID, "N", // wxpay.WxPayBuyGoods, configInfo.NotifyUrl) //if err != nil { // logger.Error(errors.New("WebPay err")) // RespJson(c, status.InternalServerError, nil) // return //} err = model.UserOpenMemberRecord{Uid: uc.Uid, OpenNo: order.SerialNo, OrderId: order.OrderId, OrderType: 6, Attach: wxpay.WxPayBuyGoods}.Insert() if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) return } webPay, err := wxpay.HmJsPayUnifiedOrder(order.SerialNo, order.Rm, user.WxOpenID, configInfo.NotifyUrl) if err != nil { logger.Error(errors.New("WebPay err")) RespJson(c, status.InternalServerError, nil) return } ret := map[string]interface{}{ "web_pay": webPay, "order_id": order.ID, "order": order, } RespOK(c, ret) //RespOK(c, order) return } // 订单支付 // 暂时只支持积分支付, 以后再考虑人民币支付 func MallOrderPay(c *gin.Context) { req := struct { OrderId uint32 `json:"order_id" binding:"required"` }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } // 订单是否存在 var order model.GoodsOrder err := model.NewGoodsOrderQuerySet(model.DB). OrderIdEq(req.OrderId). UidEq(uc.Uid). One(&order) if err != nil { logger.Error("err:", err) RespJson(c, status.BadRequest, nil) return } // 订单状态不可以支付 if order.PayStatus != model.PayStatusInit { logger.Error("err:", err) RespJson(c, status.BadRequest, nil) return } tx := model.TransactionBegin() // 减少库存 // 确认下是在支付后减少,还是下单后? // 减少用户积分 // 更新支付状态 err = model.NewGoodsOrderQuerySet(tx). OrderIdEq(req.OrderId). VersionIdEq(order.VersionId). GetUpdater(). SetPayStatus(model.PayStatusOK). SetVersionId(order.VersionId + 1). Update() if err != nil { logger.Error("err:", err) tx.Rollback() RespJson(c, status.BadRequest, nil) return } tx.Commit() RespOK(c, nil) return } func MallOrderList(c *gin.Context) { req := model.GoodsOrderListReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } list, total, err := req.OrderList(uc.Uid) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } ret := map[string]interface{}{ "list": list, "cur_page": req.PageIdx, "total_page": total, } RespOK(c, ret) return } func MallOrderDetail(c *gin.Context) { req := model.GoodsOrderDetailReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } detail, err := req.OrderDetail(uc.Uid) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } RespOK(c, detail) return } func MallOrderRefund(c *gin.Context) { req := struct { GoodsOrderId uint32 `json:"goods_order_id"` RefundReason string `json:"refund_reason"` }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } //model.GoodsOrder{} var goodsOrder model.GoodsOrder err := model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).One(&goodsOrder) if err != nil { log.Error().Msgf("goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } if goodsOrder.CreatedAt.AddDate(0, 0, 15).Before(utils.Now()) || (!goodsOrder.ReceivedTime.IsZero() && goodsOrder.ReceivedTime.AddDate(0, 0, 7).Before(utils.Now())) { log.Error().Msg("goods order refund exceed the time limit") RespJson(c, status.InternalServerError, nil) return } if goodsOrder.State != model.GoodsOrderStateDelivered && goodsOrder.State != model.GoodsOrderStateReceived && goodsOrder.State != model.GoodsOrderStateRefundedCancel { log.Error().Msg("goods order state err") RespJson(c, status.OrderDelivered, nil) return } store, err := model.GetStore(goodsOrder.DeliverStoreId) if err != nil { log.Error().Msgf("get store err:%#v", err) RespJson(c, status.InternalServerError, nil) return } goodsOrder.DeliverStore = store err = model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).GetUpdater(). SetRefundReason(req.RefundReason).SetState(model.GoodsOrderStateOnRefund).Update() if err != nil { log.Error().Msgf("update goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } RespOK(c, goodsOrder) return } func MallOrderRefundCancel(c *gin.Context) { req := struct { GoodsOrderId uint32 `json:"goods_order_id"` }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } var goodsOrder model.GoodsOrder err := model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).One(&goodsOrder) if err != nil { log.Error().Msgf("goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } if goodsOrder.State != model.GoodsOrderStateOnRefund { log.Error().Msgf("state err") RespJson(c, status.StateNotCancel, nil) return } err = model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).GetUpdater(). SetState(model.GoodsOrderStateRefundedCancel).Update() if err != nil { log.Error().Msgf("update goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } RespOK(c, nil) return } func MallOrderRefundSend(c *gin.Context) { req := struct { GoodsOrderId uint32 `json:"goods_order_id"` RefundExpressCompany string `json:"refund_express_company"` // 退货物流公司 RefundExpressCompanyNo string `json:"refund_express_company_no"` // 退货物流公司编号 RefundExpressNo string `json:"refund_express_no"` // 退货物流单号 }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } var goodsOrder model.GoodsOrder err := model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).One(&goodsOrder) if err != nil { log.Error().Msgf("goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } if goodsOrder.State != model.GoodsOrderStateOnRefund { log.Error().Msgf("state err") RespJson(c, status.StateNotCancel, nil) return } err = model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).GetUpdater(). SetRefundExpressNo(req.RefundExpressNo). SetRefundExpressCompany(req.RefundExpressCompany). SetRefundExpressCompanyNo(req.RefundExpressCompanyNo).Update() if err != nil { log.Error().Msgf("update goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } RespOK(c, nil) return } func MallOrderCancel(c *gin.Context) { req := struct { GoodsOrderId uint32 `json:"goods_order_id"` }{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } var goodsOrder model.GoodsOrder err := model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).One(&goodsOrder) if err != nil { log.Error().Msgf("goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } if goodsOrder.State != model.GoodsOrderStateOnDeliver { log.Error().Msg("goods order state err") RespJson(c, status.OrderDelivered, nil) return } if goodsOrder.PayStatus != 2 { log.Error().Msg("not pay") RespJson(c, status.InternalServerError, nil) return } if goodsOrder.Rm != 0 { outTradeNo, err := model.GetWxPayExpressFeeRefundRecord(goodsOrder.OrderId) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } //m.OpenNo = model.GetOrderSn() memberRecord := &model.UserOpenMemberRecord{OpenNo: model.GetOrderSn(), OrderType: 7, GoodsOrder: &goodsOrder} err = memberRecord.MallGoodsOrderRefund(outTradeNo) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } } //tx := model.DB.Begin() err = model.NewGoodsOrderQuerySet(model.DB).OrderIdEq(req.GoodsOrderId).GetUpdater(). SetState(model.GoodsOrderStateCancel).Update() if err != nil { //tx.Rollback() log.Error().Msgf("update goods order err:%#v", err) RespJson(c, status.InternalServerError, nil) return } //err = tx.Commit().Error //if err != nil { // tx.Rollback() // log.Error().Msgf("commit err:%#v", err) // RespJson(c, status.InternalServerError, nil) // return //} if goodsOrder.Vm != 0 { err = model.UserVmUpdate(goodsOrder.Uid, int(goodsOrder.Vm), model.VmEventBuyGoods, "购买商品积分抵扣取消") if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } } model.UpdateDeliverTaskSubStateCancel(goodsOrder.OrderId) RespOK(c, "") return } func MallUserVmRecord(c *gin.Context) { req := model.MallUserVmRecordReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } list, total, err := req.UserVmRecordList(uc.Uid) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } ret := map[string]interface{}{ "list": list, "cur_page": req.PageIdx, "total_page": total, } RespOK(c, ret) return } func MallGoodsOrderConfirmReceipt(c *gin.Context) { req := model.MallGoodsOrderConfirmReceiptReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } uc := auth.GetCurrentUser(c) if uc == nil { RespJson(c, status.Unauthorized, nil) return } err := req.MallGoodsOrderConfirmReceipt(uc.Uid) if err != nil { logger.Error("err:", err) RespJson(c, status.InternalServerError, nil) return } RespOK(c, nil) return } func MallGoodsSpec(c *gin.Context) { req := model.MallGoodsSpecReq{} if err := c.ShouldBindJSON(&req); err != nil { logger.Error(err) RespJson(c, status.BadRequest, nil) return } err := req.Spec() if err != nil { logger.Error("err:", err) if err.Error() == "not_found" { RespJson(c, status.OrderStockOut, nil) return } RespJson(c, status.InternalServerError, nil) return } RespOK(c, req.GoodsAttribute) return } func MallGoodsCatList(c *gin.Context) { var goodsCats []model.GoodsCat err := model.DB.Table("goods_cat").Where("level=?", 1).Where("state=2"). Order("sort DESC").Find(&goodsCats).Error if err != nil { logger.Error("goods cat list err:", err) RespJson(c, status.InternalServerError, nil) return } pids := make([]uint32, 0) for i, _ := range goodsCats { pids = append(pids, goodsCats[i].ID) } var subCat []model.GoodsCat err = model.DB.Table("goods_cat").Where("pid in (?)", pids).Where("state=2"). Order("sort DESC").Find(&subCat).Error if err != nil { logger.Errorf("pCat err:%#v", err) RespJson(c, status.InternalServerError, nil) return } pCatMap := make(map[uint32][]model.GoodsCat, 0) for i, _ := range subCat { pCatMap[subCat[i].Pid] = append(pCatMap[subCat[i].Pid], subCat[i]) } for i, _ := range goodsCats { v, ok := pCatMap[goodsCats[i].ID] if ok { goodsCats[i].SubCats = v } } RespOK(c, goodsCats) return }