From 8f1d5a72d4908d1fb27167f5402aeb39065f1dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E5=B0=B9=E5=B2=9A?= <770236076@qq.com> Date: Thu, 25 Feb 2021 17:18:09 +0800 Subject: [PATCH] aa --- .../jxcallback/scheduler/defsch/defsch.go | 3 + .../jxcallback/scheduler/defsch/defsch_ext.go | 92 ++++++++++++++++--- business/jxstore/cms/store_acct.go | 26 ++++-- business/model/dao/store.go | 6 +- business/model/error_code.go | 3 + business/partner/partner_store_acct.go | 12 ++- controllers/jx_order.go | 4 +- 7 files changed, 120 insertions(+), 26 deletions(-) diff --git a/business/jxcallback/scheduler/defsch/defsch.go b/business/jxcallback/scheduler/defsch/defsch.go index aac6f7401..24eac70a1 100644 --- a/business/jxcallback/scheduler/defsch/defsch.go +++ b/business/jxcallback/scheduler/defsch/defsch.go @@ -853,6 +853,9 @@ func (s *DefScheduler) createWaybillOn3rdProviders(savedOrderInfo *WatchOrderInf } } } + + //1表示为门店发单,需要验证门店账户余额情况 + _, err = s.CheckStoreBalance(jxcontext.AdminCtx, order, waybillVendorIDs) //TODO 2021-02-19 增加品牌配送开关 if storeDetail.BrandIsOpen == model.YES { err = fmt.Errorf("此品牌已关闭配送! [%v]", storeDetail.BrandName) diff --git a/business/jxcallback/scheduler/defsch/defsch_ext.go b/business/jxcallback/scheduler/defsch/defsch_ext.go index 802f4567d..9f43aa67f 100644 --- a/business/jxcallback/scheduler/defsch/defsch_ext.go +++ b/business/jxcallback/scheduler/defsch/defsch_ext.go @@ -5,6 +5,8 @@ import ( "math" "time" + "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model/dao" @@ -130,6 +132,36 @@ func (s *DefScheduler) CreateWaybillOnProviders4SavedOrder(ctx *jxcontext.Contex if forceCreate { s.stopTimer(savedOrderInfo) } + //门店发单开始扣钱 + if order.CreateDeliveryType == model.YES { + //暂时这么认为,len courierVendorIDs 为1表示是老板或者运营从小程序上点的立即发单,因为小程序上是点哪个发哪个 + //京西后台则是点一下发3个,len courierVendorIDs 是0 + //如果是小程序上点哪个扣哪个平台的钱 + //如果是后台,则选最高的那个扣 + var deliveryDee int64 + deliveryFeeMap, _ := s.QueryOrderWaybillFeeInfoEx(ctx, order.VendorOrderID, order.VendorID) + if len(courierVendorIDs) == 1 { + courierVendorID := courierVendorIDs[0] + if _, ok := deliveryFeeMap[courierVendorID]; ok { + deliveryDee = deliveryFeeMap[courierVendorID].DeliveryFee + } + } else if len(courierVendorIDs) == 0 { + var maxFee int64 + for _, v := range deliveryFeeMap { + if v.DeliveryFee > maxFee { + v.DeliveryFee = maxFee + } + } + deliveryDee = maxFee + } + handler := partner.CurStoreAcctManager + //此订单没有因为发运单而扣除过门店账户 + if isExist, err := handler.CheckStoreAcctExpendExist(jxutils.GetSaleStoreIDFromOrder(order), partner.StoreAcctTypeExpendCreateWaybillEx, order.VendorOrderID); err == nil && !isExist { + err = handler.InsertStoreAcctExpendAndUpdateStoreAcctBalance(ctx, jxutils.GetSaleStoreIDFromOrder(order), int(deliveryDee), partner.StoreAcctTypeExpendCreateWaybillEx, order.VendorOrderID) + } else if isExist { + globals.SugarLogger.Debugf("CreateWaybillOnProviders4SavedOrder orderID:%s userName:%s ,storeAcctExpend isExist", order.VendorOrderID, ctx.GetUserName()) + } + } globals.SugarLogger.Debugf("CreateWaybillOnProviders4SavedOrder orderID:%s userName:%s successfully", order.VendorOrderID, ctx.GetUserName()) return bills, err } @@ -141,7 +173,15 @@ func (s *DefScheduler) CreateWaybillOnProviders4SavedOrder(ctx *jxcontext.Contex return nil, err } -func (s *DefScheduler) CreateWaybillOnProvidersEx(ctx *jxcontext.Context, vendorOrderID string, vendorID int, courierVendorIDs []int, forceCreate bool, maxDeliveryFee int64) (bills []*model.Waybill, err error) { +func (s *DefScheduler) CreateWaybillOnProvidersEx(ctx *jxcontext.Context, vendorOrderID string, vendorID int, courierVendorIDs []int, forceCreate bool, maxDeliveryFee int64) (bills []*model.Waybill, errCode string, err error) { + savedOrderInfo := s.loadSavedOrderByID(vendorOrderID, vendorID, true) + if savedOrderInfo != nil { + order := savedOrderInfo.order + //1表示为门店发单,需要验证门店账户余额情况 + if errCode, err = s.CheckStoreBalance(ctx, order, courierVendorIDs); err != nil { + return nil, errCode, err + } + } jxutils.CallMsgHandler(func() { bills, err = func() (bills []*model.Waybill, err error) { userName := ctx.GetUserName() @@ -155,18 +195,6 @@ func (s *DefScheduler) CreateWaybillOnProvidersEx(ctx *jxcontext.Context, vendor if order.DeliveryType == model.OrderDeliveryTypeSelfTake { return nil, fmt.Errorf("订单:%s是自提单", vendorOrderID) } - //1表示为门店发单,需要验证门店账户余额情况 - if order.CreateDeliveryType == model.YES { - //暂时这么认为,len courierVendorIDs 为1表示是老板或者运营从小程序上点的立即发单,因为小程序上是点哪个发哪个 - //京西后台则是点一下发3个,len courierVendorIDs 是0 - //如果是小程序上点哪个扣哪个平台的钱 - //如果是后台,则选最高的那个扣 - if len(courierVendorIDs) == 1 { - - } else if len(courierVendorIDs) == 0 { - - } - } if !forceCreate { err = s.isPossibleSwitch2SelfDelivery(order) } @@ -188,7 +216,43 @@ func (s *DefScheduler) CreateWaybillOnProvidersEx(ctx *jxcontext.Context, vendor return bills, err }() }, jxutils.ComposeUniversalOrderID(vendorOrderID, vendorID)) - return bills, err + return bills, errCode, err +} + +func (s *DefScheduler) CheckStoreBalance(ctx *jxcontext.Context, order *model.GoodsOrder, courierVendorIDs []int) (errCode string, err error) { + if order.CreateDeliveryType == model.YES { + //暂时这么认为,len courierVendorIDs 为1表示是老板或者运营从小程序上点的立即发单,因为小程序上是点哪个发哪个 + //京西后台则是点一下发3个,len courierVendorIDs 是0 + //如果是小程序上点哪个扣哪个平台的钱 + //如果是后台,则选最高的那个扣 + storeAcct, err := cms.GetStoreAcctBalance(ctx, jxutils.GetSaleStoreIDFromOrder(order)) + deliveryFeeMap, _ := s.QueryOrderWaybillFeeInfoEx(ctx, order.VendorOrderID, order.VendorID) + if err != nil { + return errCode, fmt.Errorf("获取账户余额失败!") + } + if storeAcct.AccountBalance < partner.MinCreateWaybillBalance { + return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("门店账户余额小于[%v]元,不能发配送!", jxutils.IntPrice2Standard(partner.MinCreateWaybillBalance)) + } + if len(courierVendorIDs) == 1 { + courierVendorID := courierVendorIDs[0] + if _, ok := deliveryFeeMap[courierVendorID]; ok { + if deliveryFeeMap[courierVendorID].DeliveryFee > int64(storeAcct.AccountBalance) { + return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("门店账户余额小于[%v]元,不能发配送!", jxutils.IntPrice2Standard(deliveryFeeMap[courierVendorID].DeliveryFee)) + } + } + } else if len(courierVendorIDs) == 0 { + var maxFee int64 + for _, v := range deliveryFeeMap { + if v.DeliveryFee > maxFee { + v.DeliveryFee = maxFee + } + } + if maxFee > int64(storeAcct.AccountBalance) { + return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("门店账户余额小于[%v]元,不能发配送!", jxutils.IntPrice2Standard(maxFee)) + } + } + } + return errCode, err } // todo 这个函数可以和SelfDeliveringAndUpdateStatus合并 diff --git a/business/jxstore/cms/store_acct.go b/business/jxstore/cms/store_acct.go index fac82d992..29a0639f6 100644 --- a/business/jxstore/cms/store_acct.go +++ b/business/jxstore/cms/store_acct.go @@ -1,6 +1,7 @@ package cms import ( + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" @@ -86,9 +87,11 @@ func (s *StoreAcctManager) InsertStoreAcctExpendAndUpdateStoreAcctBalance(ctx *j var ( db = dao.GetDB() ) - if err = s.InsertStoreAcctExpend(ctx, db, storeID, price, acctType, vendorOrderID); err == nil { - s.UpdateStoreAcctBalance(ctx, storeID, price, false) - } + utils.CallFuncAsync(func() { + if err = s.InsertStoreAcctExpend(ctx, db, storeID, price, acctType, vendorOrderID); err == nil { + s.UpdateStoreAcctBalance(ctx, storeID, price, false) + } + }) return err } @@ -96,12 +99,21 @@ func (s *StoreAcctManager) InsertStoreAcctIncomeAndUpdateStoreAcctBalance(ctx *j var ( db = dao.GetDB() ) - if err = s.InsertStoreAcctIncome(ctx, db, storeID, price, acctType); err == nil { - s.UpdateStoreAcctBalance(ctx, storeID, price, true) - } + utils.CallFuncAsync(func() { + if err = s.InsertStoreAcctIncome(ctx, db, storeID, price, acctType); err == nil { + s.UpdateStoreAcctBalance(ctx, storeID, price, true) + } + }) return err } -func (s *StoreAcctManager) CheckStoreAcctExpendExist(storeID int, vendorOrderID string) (result bool, err error) { +func (s *StoreAcctManager) CheckStoreAcctExpendExist(storeID, acctType int, vendorOrderID string) (result bool, err error) { + var ( + db = dao.GetDB() + ) + //暂时这样,后应该会再查有没有对冲的入账记录来判断 + if results, err := dao.GetStoreAcctExpend(db, storeID, acctType, vendorOrderID, utils.ZeroTimeValue, utils.ZeroTimeValue); err == nil && len(results) > 0 { + return true, err + } return false, err } diff --git a/business/model/dao/store.go b/business/model/dao/store.go index 97789b6ea..6c486309b 100644 --- a/business/model/dao/store.go +++ b/business/model/dao/store.go @@ -1035,7 +1035,7 @@ func GetStoreAcctIncomeTotal(db *DaoDB, storeID, incomeType int, fromTime, toTim return income.IncomePrice, err } -func GetStoreAcctExpend(db *DaoDB, storeID, expendType int, fromTime, toTime time.Time) (storeAcctExpends []*model.StoreAcctExpend, err error) { +func GetStoreAcctExpend(db *DaoDB, storeID, expendType int, vendorOrderID string, fromTime, toTime time.Time) (storeAcctExpends []*model.StoreAcctExpend, err error) { sql := ` SELECT * FROM store_acct_expend @@ -1050,6 +1050,10 @@ func GetStoreAcctExpend(db *DaoDB, storeID, expendType int, fromTime, toTime tim sql += " AND type = ?" sqlParams = append(sqlParams, expendType) } + if vendorOrderID != "" { + sql += " AND vendor_order_id = ?" + sqlParams = append(sqlParams, vendorOrderID) + } if utils.IsTimeZero(fromTime) { sql += " AND created_at >= ?" sqlParams = append(sqlParams, fromTime) diff --git a/business/model/error_code.go b/business/model/error_code.go index 72446031b..b5136c777 100644 --- a/business/model/error_code.go +++ b/business/model/error_code.go @@ -17,6 +17,9 @@ const ( ErrCodeJsonActEarningPriceIsZero = "-103" ErrCodeJsonUserAlreadyExist = "-104" // 用户已经存在错,且能成功登录 ErrCodeJsonSyncErr = "-105" + + ErrCodeAccountBalanceNotEnough = "-201" //余额不足 + ErrCodeNotAuthBindWeixin = "-202" //没有绑定微信认证方式 ) var ( diff --git a/business/partner/partner_store_acct.go b/business/partner/partner_store_acct.go index 02a574a70..e913c8d04 100644 --- a/business/partner/partner_store_acct.go +++ b/business/partner/partner_store_acct.go @@ -6,7 +6,15 @@ import ( ) const ( - StoreAcctType1 = 1 //主动充值 + //账户收入类型 + StoreAcctTypeIncomePay = 1 //主动充值 + + //账户支出类型 + StoreAcctTypeExpendCreateWaybillEx = 2 //手动发单扣除的临时运费 +) + +const ( + MinCreateWaybillBalance = 1000 //余额小于这个值直接不能发 ) var ( @@ -26,5 +34,5 @@ type IStoreAcctManager interface { UpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price int, isIncome bool) (err error) InsertStoreAcctExpendAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int, vendorOrderID string) (err error) InsertStoreAcctIncomeAndUpdateStoreAcctBalance(ctx *jxcontext.Context, storeID, price, acctType int) (err error) - CheckStoreAcctExpendExist(storeID int, vendorOrderID string) (result bool, err error) + CheckStoreAcctExpendExist(storeID, acctType int, vendorOrderID string) (result bool, err error) } diff --git a/controllers/jx_order.go b/controllers/jx_order.go index 322370ded..65f779611 100644 --- a/controllers/jx_order.go +++ b/controllers/jx_order.go @@ -124,9 +124,9 @@ func (c *OrderController) CreateWaybillOnProviders() { c.callCreateWaybillOnProviders(func(params *tOrderCreateWaybillOnProvidersParams) (retVal interface{}, errCode string, err error) { var courierVendorIDs []int if err = jxutils.Strings2Objs(params.CourierVendorIDs, &courierVendorIDs); err == nil { - retVal, err = defsch.FixedScheduler.CreateWaybillOnProvidersEx(params.Ctx, params.VendorOrderID, params.VendorID, courierVendorIDs, params.ForceCreate, int64(params.MaxDeliveryFee)) + retVal, errCode, err = defsch.FixedScheduler.CreateWaybillOnProvidersEx(params.Ctx, params.VendorOrderID, params.VendorID, courierVendorIDs, params.ForceCreate, int64(params.MaxDeliveryFee)) } - return retVal, "", err + return retVal, errCode, err }) }