package phpjx import ( "errors" "fmt" "git.rosy.net.cn/jx-callback/business/model/dao" "strings" "time" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/partner" ) type Data4AfsOrderSku struct { VendorSkuID string `orm:"column(vendor_sku_id);size(48)" json:"vendorSkuID"` // 平台skuid PromotionType int `json:"promotionType"` // 商品级别促销类型 (1、无优惠;2、秒杀(已经下线);3、单品直降;4、限时抢购;1202、加价购;1203、满赠(标识商品);6、买赠(买A送B,标识B);9999、表示一个普通商品参与捆绑促销,设置的捆绑类型;9998、表示一个商品参与了捆绑促销,并且还参与了其他促销类型;9997、表示一个商品参与了捆绑促销,但是金额拆分不尽,9996:组合购,8001:轻松购会员价,8:第二件N折,9:拼团促销) Name string `orm:"size(255)" json:"name"` // 商品名 SalePrice int64 `json:"salePrice"` // 售卖价 Count int `json:"count"` // 订单下单数量 } type Data4AfsOrder struct { VendorOrderID string `orm:"column(vendor_order_id);size(48)" json:"vendorOrderID"` // 关联原始订单ID AfsOrderID string `orm:"column(afs_order_id);size(48)" json:"afsOrderID"` // 售后订单ID AfsCreatedAt time.Time `orm:"type(datetime);null;index" json:"afsCreatedAt"` // 售后单生成时间 VendorStoreID string `orm:"column(vendor_store_id);size(48)" json:"vendorStoreID"` // 外部系统里记录的storeid VendorStatus string `orm:"size(255)" json:"vendorStatus"` VendorReasonType string `orm:"size(255)" json:"vendorReasonType"` // 原始售后原因 ReasonDesc string `orm:"size(1024)" json:"reasonDesc"` // 售后原因描述 ReasonImgList string `orm:"size(1024)" json:"reasonImgList"` // 售后描述图片 VendorAppealType string `orm:"size(255)" json:"vendorAppealType"` // 原始售后方式 Skus []*Data4AfsOrderSku } func OnAfsOrderMsg(msg *CallbackMsg) (err error) { //jxutils.CallMsgHandlerAsync(func() { err = onAfsOrderMsg(msg) //}, jxutils.ComposeUniversalOrderID(msg.ThingID, model.VendorIDJX)) return err } func CheckOrderSkuCanRefund(db *dao.DaoDB, afsOrder *Data4AfsOrder) error { // 获取此订单商品吃否存在售后单 refundFinancial, err := dao.GetOrderRefundSkuList(db, []string{afsOrder.VendorOrderID}) if err != nil && !strings.Contains(err.Error(), "no row found") { return nil } if len(refundFinancial) == model.NO { return nil } for _, r := range refundFinancial { for _, s := range afsOrder.Skus { if r.SkuID == utils.Str2Int(s.VendorSkuID) { return fmt.Errorf("商品:[%s],已经存在售后单无法重复申请", s.Name) } } } // 获取用户下单商品列表 skuList, err := dao.GetSimpleOrderSkus(dao.GetDB(), afsOrder.VendorOrderID, nil) if err != nil { return err } var really = make(map[int]bool, 0) for _, s := range skuList { really[s.SkuID] = true } for _, v := range afsOrder.Skus { if _, ok := really[utils.Str2Int(v.VendorSkuID)]; !ok { return fmt.Errorf("商品:[%s],不是购买商品", v.Name) } } return nil } func buildAfsOrder(msg *CallbackMsg) (outAfsOrder *model.AfsOrder, err error) { var afsOrder *Data4AfsOrder var db = dao.GetDB() if err = utils.UnmarshalUseNumber([]byte(msg.Data), &afsOrder); err == nil { if err := CheckOrderSkuCanRefund(db, afsOrder); err != nil { return nil, err } outAfsOrder = &model.AfsOrder{ VendorID: model.VendorIDJX, AfsOrderID: afsOrder.AfsOrderID, VendorOrderID: afsOrder.VendorOrderID, VendorStoreID: afsOrder.VendorStoreID, StoreID: int(utils.Str2Int64WithDefault(afsOrder.VendorStoreID, 0)), AfsCreatedAt: afsOrder.AfsCreatedAt, VendorStatus: afsOrder.VendorStatus, VendorReasonType: afsOrder.VendorReasonType, ReasonType: int8(utils.Str2Int64WithDefault(afsOrder.VendorReasonType, 0)), ReasonDesc: utils.LimitUTF8StringLen(afsOrder.ReasonDesc, 1024), ReasonImgList: afsOrder.ReasonImgList, VendorAppealType: afsOrder.VendorAppealType, AppealType: int8(utils.Str2Int64WithDefault(afsOrder.VendorAppealType, 0)), Flag: model.OrderFlagMaskTempJX, } outAfsOrder.Status = int(utils.Str2Int64WithDefault(afsOrder.VendorStatus, 0)) skuNumber := 0 // 申请退款商品种类个数 skuCount := 0 // 申请商品退款总条数 refundMoney := 0 // 当前申请退款的商品 for _, x := range afsOrder.Skus { orderSku := &model.OrderSkuFinancial{ Count: x.Count, VendorSkuID: x.VendorSkuID, SkuID: int(utils.Str2Int64WithDefault(x.VendorSkuID, 0)), Name: x.Name, UserMoney: x.SalePrice * int64(x.Count), } if x.PromotionType != 0 && x.PromotionType != jdapi.PromotionTypeNormal { orderSku.StoreSubName = utils.Int2Str(x.PromotionType) } outAfsOrder.Skus = append(outAfsOrder.Skus, orderSku) skuCount += orderSku.Count skuNumber++ refundMoney += x.Count * int(x.SalePrice) } // 已经退款商品 refundFinancial, err := dao.GetStoreAfsOrderSkuList2(db, []string{afsOrder.VendorOrderID}) if err != nil && !dao.IsNoRowsError(err) { return nil, err } for _, f := range refundFinancial { skuCount += f.Count skuNumber++ refundMoney += f.Count * int(f.SalePrice) } // 获取订单商品列表(所有的订单商品) skuList, err := dao.GetSimpleOrderSkus(dao.GetDB(), afsOrder.VendorOrderID, nil) if err != nil { return nil, err } makeOrderSkuCount := 0 afsOrderOrderSkuCount := 0 refundFinacialSkuCount := 0 for _, v := range skuList { makeOrderSkuCount += v.Count } for _, v := range afsOrder.Skus { afsOrderOrderSkuCount += v.Count } for _, v := range refundFinancial { refundFinacialSkuCount += v.Count } // 这么写主要是不想让满足条件一的进入条件三 if makeOrderSkuCount == afsOrderOrderSkuCount && refundFinacialSkuCount == model.NO { // 整单退 } else if makeOrderSkuCount-refundFinacialSkuCount == model.YES && makeOrderSkuCount == model.YES { // 整单退且只有一个商品 } else if makeOrderSkuCount-refundFinacialSkuCount-afsOrderOrderSkuCount == model.NO && afsOrderOrderSkuCount > 0 { // 分单退最后一个,不给退 return nil, errors.New("如需整单退款,请使用整单退,无法分批次整单退款") } orderSkuNumber := 0 orderSkuCount := 0 for _, v := range skuList { orderSkuNumber++ orderSkuCount += v.Count } if skuNumber == orderSkuNumber && skuCount == orderSkuCount { outAfsOrder.RefundType = model.AfsTypeFullRefund } else { // 部分退款,只退还商品部分 outAfsOrder.RefundType = model.AfsTypePartRefund } } return outAfsOrder, err } func callbackAfsMsg2Status(msg *CallbackMsg) *model.OrderStatus { orderStatus := &model.OrderStatus{ VendorOrderID: msg.ThingID2, // 是售后单ID,不是订单ID,订单ID在RefVendorOrderID中 VendorID: model.VendorIDJX, OrderType: model.OrderTypeAfsOrder, RefVendorOrderID: msg.ThingID, RefVendorID: model.VendorIDJX, VendorStatus: msg.SubMsgType, Status: int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)), StatusTime: time.Now(), Remark: "", } return orderStatus } func onAfsOrderMsg(msg *CallbackMsg) (err error) { subMsgType := int(utils.Str2Int64WithDefault(msg.SubMsgType, 0)) status := callbackAfsMsg2Status(msg) if subMsgType == model.AfsOrderStatusWait4Approve || subMsgType == model.AfsOrderStatusNew { afsOrder, err2 := buildAfsOrder(msg) if err = err2; err == nil { err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, status) } } else { err = partner.CurOrderManager.OnOrderStatusChanged("", status) } return err } func postFakeAfsMsg(orderNo, afsOrderID string, status int) { msg := &CallbackMsg{ AppKey: appKey, MsgType: MsgTypeAfsOrder, SubMsgType: utils.Int2Str(status), ThingID: orderNo, ThingID2: afsOrderID, Timestamp: time.Now().Unix(), } utils.CallFuncAsync(func() { OnCallbackMsg(msg) }) } func NotifyAfsOrderStatusChanged(order *model.AfsOrder, status int) (err error) { orderMsg := *order orderMsg.Status = status if err = jxAPI.NotifyAfsOrderStatusChanged(&orderMsg); err == nil { postFakeAfsMsg(orderMsg.VendorOrderID, orderMsg.AfsOrderID, orderMsg.Status) } return err }