package timedTask import ( "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "jyOrderManager/internal/consts" "jyOrderManager/internal/jyutil" "jyOrderManager/internal/logic/order" "jyOrderManager/internal/logic/product" "log" "math" "net/rpc" "regexp" "strings" "time" ) var ( reg = regexp.MustCompile("[\\s()]+") ) type FilterStr struct { PaybackNum int paybackListArr []map[string]interface{} } func AutomaticPaymentCollection() { autoReturnTaskTime := g.Cfg().MustGet(context.Background(), "autoReturnTaskTime", 3).Int() for { AutomaticPayment() time.Sleep(gconv.Duration(autoReturnTaskTime) * time.Minute) } } func AutomaticPayment() { var ctx = context.Background() log.Println("自动回款匹配。。。开始") query := fmt.Sprintf(`select * from transaction where ISRELATION = 0 and OTHNAM is not null and OTHNAM != "" and BNKTIM > '%s' order by id`, time.Now().AddDate(0, -g.Cfg().MustGet(ctx, "automaticPaymentTime", 3).Int(), 0).Format("2006-01-02 15:04:05")) data, _ := g.DB("cbs").Query(ctx, query) if !data.IsEmpty() { returnOrderMap := make(map[string]int) orderData, _ := g.DB().Query(ctx, `SELECT a.*, a.pay_money+(select IFNULL(sum(payMoney),0) as return_money from moneyCorrection where orderCode=a.order_code) as new_pay_money, a.commission+(select IFNULL(sum(commission),0) as return_commission from moneyCorrection where orderCode=a.order_code) as new_commission, b.paybackNum, b.paybackList FROM dataexport_order a LEFT JOIN ( SELECT order_code, JSON_EXTRACT( plantList, "$.paybackNum" ) AS paybackNum, JSON_EXTRACT( plantList, "$.paybackList" ) AS paybackList FROM return_money_plant WHERE state != -1 and JSON_VALID( plantList ) ) b ON a.order_code = b.order_code WHERE ( a.return_status = 0 OR a.return_status = 2 ) AND a.audit_status = 3 AND ( a.order_status = 1 OR a.order_status = 0 )`) returnOrderData, _ := g.DB().Query(ctx, `SELECT order_code, COUNT(*) as total_count FROM return_money_record WHERE state =1 GROUP BY order_code `) if !returnOrderData.IsEmpty() { for _, i2 := range returnOrderData.List() { returnOrderMap[gconv.String(i2["order_code"])] = gconv.Int(i2["total_count"]) } } filterMap := make(map[string]FilterStr) if !orderData.IsEmpty() { //优化 获取filter字段中的数据 for _, o := range orderData.List() { var paybackList string if pList := gconv.String(o["paybackList"]); pList != "" && pList != `""` && strings.Contains(pList, "合计") { paybackList = strings.ReplaceAll(pList[1:len(pList)-1], "\\", "") } var paybackListArr []map[string]interface{} if paybackList != "" { _ = json.Unmarshal([]byte(paybackList), &paybackListArr) } paybackNum := strings.ReplaceAll(gconv.String(o["paybackNum"]), `"`, "") filterMap[gconv.String(o["order_code"])] = FilterStr{ gconv.Int(paybackNum), paybackListArr, } } } for _, v := range data.List() { returnMoney := int(math.Floor(float64(float64(gconv.Float64(v["TRSBAL"]))*100) + 0.5)) companyName := gconv.String(v["OTHNAM"]) remark := gconv.String(v["TXTDSM"]) remarks := gconv.String(v["NUSAGE"]) id := gconv.Int(v["id"]) returnTime := gconv.String(v["BNKTIM"]) BNKFLW := gconv.String(v["BNKFLW"]) BNKNAM := gconv.String(v["BNKNAM"]) if !orderData.IsEmpty() { for _, o := range orderData.List() { //filterMap := make(map[string]interface{}) //_ = json.Unmarshal([]byte(gconv.String(o["filter"])), &filterMap) money := gconv.Int(o["new_pay_money"]) - gconv.Int(o["new_commission"]) - gconv.Int(o["procedures_money"]) paymentUser := gconv.String(o["payment_user"]) if paymentUser == "" { paymentUser = gconv.String(o["company_name"]) } orderCode := gconv.String(o["order_code"]) if PaymentPlanMatching(money, returnMoney, paymentUser, companyName, remark, remarks, orderCode, filterMap[orderCode].PaybackNum, filterMap[orderCode].paybackListArr, returnOrderMap) { isExists, err := g.Redis("qmx_filter").Exists(ctx, "qmx_auto_return_"+fmt.Sprint(id)) if isExists == 0 || err != nil { log.Println("自动回款匹配成功", id, orderCode) var returned_money int if calculation, _ := g.DB().GetOne(ctx, fmt.Sprintf("SELECT SUM(return_money) as returned_money FROM return_money_record WHERE order_code=%s AND state=1", orderCode)); !calculation.IsEmpty() { returned_money = gconv.Int(calculation.Map()["returned_money"]) } //isFirstReturn := config.JysqlDB.Count("return_money_record", map[string]interface{}{"state": 1, "order_code": orderCode}) == 0 returnReq, _ := g.DB().Insert(ctx, "return_money_record", map[string]interface{}{ "order_code": orderCode, "return_time": returnTime, "return_money": returnMoney, "return_type": 3, "return_invoice_status": 0, "operate_time": time.Now().Format("2006-01-02 15:04:05"), "flow_money": returnMoney, "bank_name": BNKNAM, "bank_flow": BNKFLW, "operate_type": 2, "state": 1, "pay_account_name": paymentUser, }) returnId, _ := returnReq.LastInsertId() //计算已回款金额 if returned_money == 0 { if err = order.CommonChange(ctx, orderCode, returnTime, order.ReturnMoney); err != nil { log.Printf("%s 回款销售业绩生效异常 %v", orderCode, err) } } updateData := map[string]interface{}{"return_status": 2, "order_status": 1} if returned_money+returnMoney == money { g.Redis("qmx_filter").SetEX(ctx, "qmx_auto_return_"+fmt.Sprint(id), 1, 3600) updateData["return_status"] = 1 } if returnId > 0 { log.Println("自动回款创建回款记录成功", id, orderCode) g.DB().Update(ctx, "dataexport_order", updateData, map[string]interface{}{"order_code": orderCode}) g.DB("cbs").Update(ctx, "transaction", map[string]interface{}{"ISRELATION": 1, "return_id": fmt.Sprint(returnId)}, map[string]interface{}{"id": id}) log.Println("自动回款开通权益", orderCode, gconv.Int(o["return_status"]), updateData["return_status"], returned_money, returnMoney, money) if gconv.Int(o["return_status"]) != 1 && updateData["return_status"] == 1 { productDetail, err := g.DB().Ctx(ctx).Query(ctx, fmt.Sprintf(`SELECT * FROM jy_order_detail WHERE order_code ='%s' and returned_open =1 and is_service_open = 0 and status =1`, orderCode)) if err != nil || productDetail.IsEmpty() { continue } //全额回款开通权益 if !consts.PhoneRegex.MatchString(gconv.String(o["user_phone"])) { continue } uData, entId, userPositionId, err := jyutil.GetCreateUserData(gconv.String(o["user_phone"]), gconv.String(o["company_name"]), gconv.Int(o["buy_subject"]) == 2) if err != nil { continue } if err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { // 产品服务开通 for _, m := range productDetail.List() { if !jyutil.IsServiceOpen(m) { continue } //参数注入 m["userMap"] = map[string]interface{}{ "userData": uData, "entId": entId, "userPositionId": userPositionId, } m["phone"] = o["user_phone"] m["order_code"] = orderCode m["amount"] = m["final_price"] m["reqCompanyName"] = o["company_name"] m["reqSubject"] = o["buy_subject"] productCode := gconv.String(m["product_code"]) m["linked_orderId"] = m["linked_detail_id"] m["linkedOrderId"] = m["linked_detail_id"] log.Println("自动开启服务参数", m) pFunc, err := product.JyProFunc.GetProductInitFuncByCode(productCode) if err != nil { continue } pObj, err := pFunc(m) if err != nil { gerror.Wrap(err, fmt.Sprintf("获取%s商品异常", productCode)) continue } if err = pObj.OpenService(ctx, time.Now()); err != nil { continue } } if gconv.Int(o["buy_subject"]) == 2 { uData["userId"] = userPositionId } if orderUserId := gconv.String(o["user_id"]); orderUserId == "" || orderUserId != gconv.String(uData["userId"]) || (gconv.Int(o["buy_subject"]) == 2 && gconv.Int64(o["ent_id"]) != entId) { log.Printf("同步更新订单用户身份:orderUserId:%s,userId:%v,entId:%d\n", orderUserId, uData["userId"], entId) upData := g.Map{ "user_id": uData["userId"], } if entId > 0 { //企业服务 upData["ent_id"] = entId if personPhone := gconv.String(o["personPhone"]); personPhone != "" { jyutil.EndAddUser(ctx, entId, gconv.String(o["user_phone"]), personPhone, gconv.String(o["personName"])) } } //更新订单 _, err = g.DB().Update(ctx, consts.OrderListTableName, upData, "order_code=?", orderCode) if err != nil { return err } } return nil }); err != nil { log.Println(err) continue } } } else { log.Println("自动回款创建回款记录失败", id, orderCode) } } else { log.Println("自动回款重复匹配过滤", id, orderCode) } //回款关闭相应的支付码支付 go CancelOnlinePay(ctx, orderCode) } } } } } else { log.Println("回款信息查询为空") } log.Println("自动回款匹配。。。结束") } // PaymentPlanMatching 回款计划匹配 func PaymentPlanMatching(money, returnMoney int, paymentUser, companyName, remark, remarks, orderCode string, paybackNum int, paybackListArr []map[string]interface{}, returnOrderMap map[string]int) bool { pUser := reg.ReplaceAllString(paymentUser, "") if money == returnMoney && (pUser == companyName || remark == orderCode || remarks == orderCode) { return true } if paybackNum > 1 { //仅订单回款计划有多期时,才匹配回款计划,回款计划如只有1期,则无需匹配 isFirstReturn := returnOrderMap[orderCode] if isFirstReturn < paybackNum && len(paybackListArr) > 0 && len(paybackListArr) >= isFirstReturn { //② 如该订单已有X笔回款,则匹配第“X+1”期的回款计划,其他期的回款计划不进行匹配,例如:该笔订单无回款,则匹配第1期的回款计划;该笔订单有1笔回款,则匹配第2期的回款计划。 if gconv.String(paybackListArr[isFirstReturn]["code"]) != "合计" && returnMoney == gconv.Int(paybackListArr[isFirstReturn]["money"])*100 && (pUser == companyName) { return true } } //} } return false } func CancelOnlinePay(ctx context.Context, orderCode string) { if total, _ := g.DB().Ctx(ctx).Query(ctx, "SELECT count(*) from return_money_online WHERE status=0 and order_code=? and expire_time >?", orderCode, time.Now().Format("2006-01-02 15:04:05")); !total.IsEmpty() { r, err := rpc.DialHTTP("tcp", g.Cfg().MustGet(context.Background(), "jyPayRpc").String()) defer r.Close() res := "" err = r.Call("JyPayRpc.CloseReturnOrder", orderCode, &res) if err != nil { log.Printf("%s关闭支付宝微信支付码失败 %s", orderCode, err) } } }