123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- package order
- import (
- "app.yhyue.com/moapp/jybase/common"
- "app.yhyue.com/moapp/jybase/date"
- "context"
- "encoding/json"
- "errors"
- "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/product"
- "jyOrderManager/internal/model"
- "jyOrderManager/internal/service"
- "log"
- "math"
- "strings"
- "time"
- )
- // 订单审核状态
- const (
- OrderUncommitted = 0 // 待提交
- OrderPending = 1 // 待审核
- OrderFirstPassed = 2 // 一审通过
- OrderPassed = 3 // 审核通过
- OrderSecondPassed = 4 // 审核通过
- OrderFirstReturn = -2 // 一审退回
- OrderSecondReturn = -3 // 二审退回
- OrderThreeReturn = -4 // 二审退回
- ReturnMoney = 1
- ReturnProtocol = 2
- )
- // 表名
- const (
- TableAuditRecords = "audit_records" // 审核记录表
- TableDataExportOrder = "dataexport_order" // 订单表
- )
- type ExamineDiscountStr struct {
- ExamineDiscount map[string][]Discount `json:"examineDiscount"`
- }
- type Discount struct {
- Min int `json:"min"`
- Max int `json:"max"`
- DiscountRate float64 `json:"discountRate"`
- }
- var (
- GiftDiscount float64
- ExamineDiscountConfig map[string][]Discount
- )
- func init() {
- err := g.Cfg().MustGet(context.Background(), "examineDiscount").Scan(&ExamineDiscountConfig)
- if err != nil {
- log.Println("examineDiscount", err)
- }
- GiftDiscount = g.Cfg().MustGet(context.Background(), "giftDiscount", 0.6).Float64()
- }
- // OrdersExamine 订单审核
- func OrdersExamine(ctx context.Context, param model.OrdersExamine) error {
- //查询订单
- orderData, err := g.DB().Ctx(ctx).GetOne(ctx, fmt.Sprintf(`SELECT * FROM dataexport_order WHERE order_code ='%s'`, param.OrderCode))
- if err != nil || orderData.IsEmpty() {
- return gerror.Wrap(err, "查询订单表异常")
- }
- oldAuditStatus := gconv.Int(orderData.Map()["audit_status"])
- if oldAuditStatus == 3 {
- return errors.New("订单审核已完成,无需审批")
- }
- newAuditStatus := 1
- operatorType := 2
- //通过
- switch param.State == 1 {
- case true:
- switch oldAuditStatus {
- case 1:
- newAuditStatus = 2
- case 2:
- newAuditStatus = 4
- operatorType = 3
- case 4:
- newAuditStatus = 3
- operatorType = 5 //三审
- }
- case false:
- switch oldAuditStatus {
- case 1:
- newAuditStatus = -2
- case 2:
- newAuditStatus = -3
- operatorType = 3
- case 4:
- newAuditStatus = -4
- operatorType = 5
- }
- }
- var (
- contractArchiveTime string
- auditStatus int
- )
- //数据库操作
- return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
- auditStatus = newAuditStatus
- var checkAuto bool
- productDetail, err := g.DB().Ctx(ctx).Query(ctx, fmt.Sprintf(`SELECT * FROM jy_order_detail WHERE order_code ='%s' and status =1`, param.OrderCode))
- if err != nil || productDetail.IsEmpty() {
- return err
- }
- if oldAuditStatus == 1 && param.State == 1 {
- //待一审 审核通过校验是否直接通过
- if CheckAutoAudit(ctx, orderData.Map(), productDetail.List()) {
- newAuditStatus = 3
- checkAuto = true
- }
- }
- upData := map[string]interface{}{
- "audit_status": newAuditStatus,
- }
- if newAuditStatus == 3 {
- //“协议归档状态”如若为“已归档”,则“订单状态”更新为“已完成”,如若为“未归档”,则订单状态仍为“未完成”
- contractData, err := g.DB().Ctx(ctx).GetOne(ctx, fmt.Sprintf(`SELECT contract_archive_status,contract_archive_time FROM contract where order_code = '%s'`, param.OrderCode))
- if err == nil && !contractData.IsEmpty() {
- if common.IntAll(contractData.Map()["contract_archive_status"]) == 1 {
- upData["order_status"] = 1
- contractArchiveTime = common.ObjToString(contractData.Map()["contract_archive_time"])
- }
- }
- //0元订单审核通过后直接开通权益
- if common.Float64All((orderData.Map())["pay_money"]) == 0 && consts.PhoneRegex.MatchString(common.ObjToString((orderData.Map())["user_phone"])) {
- upData["order_status"] = 1
- uData, entId, userPositionId, err := jyutil.GetCreateUserData(gconv.String(orderData.Map()["user_phone"]), gconv.String(orderData.Map()["company_name"]), gconv.Int(orderData.Map()["buy_subject"]) == 2)
- 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"] = orderData["user_phone"]
- m["order_code"] = param.OrderCode
- m["reqCompanyName"] = orderData.Map()["company_name"]
- m["amount"] = m["final_price"]
- m["reqSubject"] = orderData.Map()["buy_subject"]
- m["linked_orderId"] = m["linked_detail_id"]
- productCode := gconv.String(m["product_code"])
- pFunc, err := product.JyProFunc.GetProductInitFuncByCode(productCode)
- if err != nil {
- return err
- }
- pObj, err := pFunc(m)
- if err != nil {
- return gerror.Wrap(err, fmt.Sprintf("获取%s商品异常", productCode))
- }
- if err := pObj.OpenService(ctx, time.Now()); err != nil {
- return err
- }
- }
- if orderUserId := gconv.String(orderData.Map()["user_id"]); orderUserId == "" || orderUserId != gconv.String(uData["userId"]) {
- log.Printf("同步更新订单用户身份:orderUserId:%s,userId:%s,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(orderData.Map()["personPhone"]); personPhone != "" {
- jyutil.EndAddUser(ctx, entId, gconv.String(orderData.Map()["user_phone"]), personPhone, gconv.String(orderData.Map()["personName"]))
- }
- }
- //更新订单
- _, err = g.DB().Update(ctx, consts.OrderListTableName, upData, "order_code=?", param.OrderCode)
- if err != nil {
- return err
- }
- }
- return nil
- }); err != nil {
- log.Println(err)
- return err
- }
- }
- }
- //更新订单
- _, err = g.DB().Ctx(ctx).Update(ctx, "dataexport_order", upData, map[string]interface{}{"order_code": param.OrderCode})
- if err != nil {
- return err
- }
- //插入审核记录表
- tn := time.Now()
- insertData := map[string]interface{}{
- "operator": jyutil.GetUserMsgFromCtx(ctx).EntUserName, //审核操作人
- "create_time": tn.Format(date.Date_Full_Layout),
- "operator_type": operatorType,
- "audit_status": auditStatus,
- "back_reason": param.Reason,
- "order_code": param.OrderCode,
- "audit_type": 2,
- }
- _, err = g.DB().Ctx(ctx).Insert(ctx, "audit_records", insertData)
- if err != nil {
- return err
- }
- if checkAuto {
- // 给定的数据
- columns := strings.Split("operator,create_time,operator_type,audit_status,back_reason,order_code,audit_type", ",")
- values := []interface{}{"系统自动", time.Now().Add(time.Second).Format("2006-01-02 15:04:05"), 3, OrderSecondPassed, "系统自动审核通过", param.OrderCode, 2,
- "系统自动", time.Now().Add(2 * time.Second).Format("2006-01-02 15:04:05"), 5, OrderPassed, "系统自动审核通过", param.OrderCode, 2}
- // 构建SQL插入语句
- query := fmt.Sprintf("INSERT INTO audit_records (%s) VALUES (?, ?, ?, ?, ?, ?, ?), (?, ?, ?, ?, ?, ?, ?)", strings.Join(columns, ","))
- g.DB().Ctx(ctx).Exec(ctx, query, values...)
- }
- if contractArchiveTime != "" {
- _ = CommonChange(ctx, param.OrderCode, contractArchiveTime, ReturnProtocol)
- }
- return nil
- })
- }
- // CheckAutoAudit 校验自动审核
- func CheckAutoAudit(ctx context.Context, orderData map[string]interface{}, productList []map[string]interface{}) bool {
- if common.Float64All(orderData["order_money"]) == 0 || common.Float64All(orderData["pay_money"]) == 0 {
- return false
- }
- var contractPass bool
- //是否支持线上自动生成电子协议
- /*
- 判断是否符合合同
- (1)订单审核状态是“已通过”;
- (2)签约主体为“北京剑鱼信息技术有限公司”,注:如签约主体为拓普则线下生成合同;
- (3)协议状态为“签协议”(“已签协议”文案修改为“签协议”,涉及:创建订单、订单审核、订单详情)
- (4)产品类型是“超级订阅”(且付费类型为“购买”、“续费”),或产品类型是“大会员”且会员套餐为“商机版2.0”、“专家版2.0”(且服务类型为“新购服务”、“延长服务”),注:超级订阅/大会员升级和其他产品类型,线下生成合同。
- */
- if orderData["signing_subject"] != "h01" {
- log.Println("自动审核不通过signing_subject:", orderData["signing_subject"])
- return false
- }
- isEnt := gconv.Int(orderData["buy_subject"]) == 2
- var (
- insertData []map[string]interface{}
- activityProduct = make(map[string][]map[string]interface{})
- isXwlp bool
- beforePrice, afterPrice float64
- giftDiscountRate []float64
- )
- for _, m := range productList {
- productItem, err := service.Product().GetProduct(gconv.String(m["product_code"]))
- if err != nil {
- return false
- }
- productClass, err := service.Product().GetProductClass(productItem.ProductClassId)
- if err != nil {
- return false
- }
- //外采赠品
- // 需“判断订单中常规商品/活动产品的折扣率是否都符合自动审核规则“的同时,
- //除外采赠品外的其余产品的整体折扣率不得低于XX%,才能自动审核,否则需要人工审核。
- switch productClass.TopClass == "外采赠品" {
- case true:
- if productItem.ApprovalRules == nil || productItem.ApprovalRules["rate"] == nil ||
- gconv.Int(m["final_price"]) > gconv.Int(productItem.ApprovalRules["contract_amount_max"]) ||
- gconv.Int(m["final_price"]) < gconv.Int(productItem.ApprovalRules["contract_amount_mix"]) {
- return false
- }
- isXwlp = true
- giftDiscountRate = append(giftDiscountRate, gconv.Float64(productItem.ApprovalRules["rate"]))
- continue
- case false:
- beforePrice += gconv.Float64(m["original_price"])
- afterPrice += gconv.Float64(m["final_price"])
- }
- if common.Float64All(m["original_price"]) < 0 {
- return false
- }
- if activityCode := gconv.String(m["activity_code"]); activityCode != "" { //活动产品统一校验
- activityProduct[activityCode] = append(activityProduct[activityCode], m)
- continue
- }
- filterMap := make(map[string]interface{})
- filterData := common.ObjToString(m["filter"])
- if err := json.Unmarshal([]byte(filterData), &filterMap); err != nil {
- log.Println("filter unmarshal err:", orderData["order_code"], err.Error())
- return false
- }
- var (
- cycleType, cycleCount, monthCount int
- examineDiscount float64
- )
- conditionalMap := make(map[string]interface{})
- switch productType := common.InterfaceToStr(m["product_type"]); productType {
- case "VIP订阅":
- switch common.IntAll(m["service_type"]) {
- case 3: //升级
- monthCount = GetUserTime(gconv.String(orderData["user_phone"]), gconv.String(m["linked_detail_id"]), true, isEnt)
- default:
- cycleType = common.If(common.IntAll(filterMap["buy_type"]) > 0, common.IntAll(filterMap["buy_type"]), common.IntAll(filterMap["give_type"])).(int) //1天 2月 3年 4季度
- cycleCount = common.IntAll(filterMap["buy_cycle"]) + common.IntAll(filterMap["give_cycle"])
- switch cycleType { //(1天 2月 3年 4季度)
- case 3:
- monthCount = cycleCount * 12
- case 2:
- monthCount = cycleCount
- case 1:
- if cycleCount%30 > 0 {
- monthCount = cycleCount/30 + 1
- } else {
- monthCount = cycleCount / 30
- }
- case 4:
- monthCount = cycleCount * 3
- }
- }
- //折扣率满足一定条件
- for _, discount := range ExamineDiscountConfig[productType] {
- if monthCount >= discount.Min && monthCount < discount.Max {
- examineDiscount = discount.DiscountRate
- conditionalMap["min"] = discount.Min
- conditionalMap["max"] = discount.Max
- conditionalMap["product_type"] = productType
- conditionalMap["discountRate"] = discount.DiscountRate
- break
- }
- }
- case "大会员":
- if common.IntAll(filterMap["comboId"]) <= 0 {
- return false
- }
- //大会员 createType:1新建 2补充 3延长
- switch common.IntAll(m["service_type"]) {
- case 3: //升级
- monthCount = GetUserTime(gconv.String(orderData["user_phone"]), gconv.String(orderData["linked_detail_id"]), true, isEnt)
- default:
- cycleType = common.If(common.IntAll(filterMap["buy_type"]) > 0, common.IntAll(filterMap["buy_type"]), common.IntAll(filterMap["give_type"])).(int) //1天 2月 3年 4季度
- cycleCount = common.IntAll(filterMap["buy_cycle"]) + common.IntAll(filterMap["give_cycle"])
- switch cycleType { //(1天 2月 3年 4季度)
- case 3:
- monthCount = cycleCount * 12
- case 2:
- monthCount = cycleCount
- case 1:
- if cycleCount%30 > 0 {
- monthCount = cycleCount/30 + 1
- } else {
- monthCount = cycleCount / 30
- }
- case 4:
- monthCount = cycleCount * 3
- }
- }
- //折扣率满足一定条件
- for _, discount := range ExamineDiscountConfig[productType] {
- switch discount.Max == -1 {
- case true:
- if monthCount >= discount.Min {
- examineDiscount = discount.DiscountRate
- conditionalMap["min"] = discount.Min
- conditionalMap["max"] = discount.Max
- conditionalMap["product_type"] = productType
- conditionalMap["discountRate"] = discount.DiscountRate
- break
- }
- case false:
- if monthCount >= discount.Min && monthCount < discount.Max {
- examineDiscount = discount.DiscountRate
- conditionalMap["min"] = discount.Min
- conditionalMap["max"] = discount.Max
- conditionalMap["product_type"] = productType
- conditionalMap["discountRate"] = discount.DiscountRate
- break
- }
- }
- }
- default:
- examineDiscount = productClass.Rate
- }
- if examineDiscount <= 0 {
- log.Println("自动审核商品折扣率获取失败")
- return false
- }
- log.Println("自动审核商品折扣:", m["id"], cycleType, monthCount, roundToTwoDecimalPlaces(common.Float64All(m["final_price"])/common.Float64All(m["original_price"])), examineDiscount)
- contractPass = roundToTwoDecimalPlaces(common.Float64All(m["final_price"])/common.Float64All(m["original_price"])) >= examineDiscount
- if !contractPass {
- return false
- }
- conditionalStr, _ := json.Marshal(conditionalMap)
- insertData = append(insertData, map[string]interface{}{
- "create_time": time.Now().Format("2006-01-02 15:04:05"),
- "pay_money": gconv.Float64(m["final_price"]),
- "original_price": gconv.Float64(m["original_price"]),
- "discount_rate": common.Float64All(m["final_price"]) / common.Float64All(m["original_price"]),
- "order_code": gconv.Float64(m["order_code"]),
- "product_type": common.InterfaceToStr(m["product_type"]),
- "monthCount": monthCount,
- "conditional_remarks": string(conditionalStr),
- })
- }
- if len(activityProduct) > 0 { //校验活动产品
- for activityCode, activityData := range activityProduct {
- activity, err := g.DB().Ctx(ctx).GetOne(ctx, fmt.Sprintf(`SELECT rate FROM jy_product_activity WHERE code ='%s'`, activityCode))
- if err != nil || activity.IsEmpty() {
- return false
- }
- var (
- activityOriginalPrice, activityClosingPrice float64
- activityInsertData []map[string]interface{}
- )
- for _, datum := range activityData { //同种活动 统一计算折扣率
- activityOriginalPrice += gconv.Float64(datum["original_price"])
- activityClosingPrice += gconv.Float64(datum["final_price"])
- activityInsertData = append(activityInsertData, map[string]interface{}{
- "create_time": time.Now().Format("2006-01-02 15:04:05"),
- "pay_money": gconv.Float64(datum["final_price"]),
- "original_price": gconv.Float64(datum["original_price"]),
- "discount_rate": common.Float64All(datum["final_price"]) / common.Float64All(datum["original_price"]),
- "order_code": gconv.Float64(datum["order_code"]),
- "product_type": common.InterfaceToStr(datum["product_type"]),
- "monthCount": -1,
- "conditional_remarks": fmt.Sprintf("活动产品:活动id:%s 活动折扣率:%f", activityCode, gconv.Float64(activity.Map()["rate"])),
- })
- }
- contractPass = roundToTwoDecimalPlaces(activityClosingPrice/activityOriginalPrice) >= gconv.Float64(activity.Map()["rate"])
- if !contractPass {
- return false
- }
- //记录活动自动审核通过记录
- insertData = append(insertData, activityInsertData...)
- }
- }
- if isXwlp { //存在赠送产品 每个赠送产品单独计算折扣率
- if afterPrice == 0 {
- return false
- }
- for _, f := range giftDiscountRate {
- if beforePrice/afterPrice < f {
- return false
- }
- }
- }
- if len(insertData) > 0 {
- g.DB().Save(ctx, "automatic_audit_log", insertData)
- }
- return true
- }
- func roundToTwoDecimalPlaces(x float64) float64 {
- return math.Round(x*10000) / 10000
- }
- func GetUserTime(phone, orderId string, isVip, isEnt bool) (monthCount int) {
- switch isEnt {
- case false:
- //查询用户大会员权益剩余服务周期
- userData, ok := jyutil.MG.DB().FindOne("user", map[string]interface{}{
- "$or": []map[string]interface{}{
- {"s_phone": phone},
- {"s_m_phone": phone},
- },
- })
- if !ok || userData == nil || len(*userData) == 0 {
- return monthCount
- }
- var startTime, endTime time.Time
- if isVip {
- startTime = time.Unix(common.Int64All((*userData)["l_vip_starttime"]), 0).Local()
- endTime = time.Unix(common.Int64All((*userData)["l_vip_endtime"]), 0).Local()
- } else {
- startTime = time.Unix(common.Int64All((*userData)["i_member_starttime"]), 0).Local()
- endTime = time.Unix(common.Int64All((*userData)["i_member_endtime"]), 0).Local()
- }
- if startTime.Unix() < time.Now().Unix() {
- startTime = time.Now()
- }
- return GetMonthNum(startTime, endTime)
- case true:
- waitEmpower, err := g.DB().Ctx(context.Background()).GetOne(context.Background(), fmt.Sprintf(`
- SELECT e.start_time,e.end_time FROM entniche_order e
- INNER JOIN entniche_wait_empower w on e.wait_empower_id = w.id
- WHERE e.order_detail_id = %s`, orderId))
- if err == nil || waitEmpower.IsEmpty() {
- return monthCount
- }
- var startTime, endTime time.Time
- startTime = jyutil.StrToTime(gconv.String(waitEmpower.Map()["start_time"]), "2006-01-02 15:04:05")
- endTime = time.Unix(common.Int64All(waitEmpower.Map()["end_time"]), 0).Local()
- if startTime.Unix() < time.Now().Unix() {
- startTime = time.Now()
- }
- return GetMonthNum(startTime, endTime)
- }
- return monthCount
- }
- func GetMonthNum(startTime, endTime time.Time) int {
- // 定义开始时间和结束时间
- //start := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
- //end := time.Date(2024, time.March, 30, 0, 0, 0, 0, time.UTC)
- // 获取开始时间和结束时间的年份和月份
- startYear, startMonth, startDay := startTime.Date()
- endYear, endMonth, endDay := endTime.Date()
- // 计算月份差异
- months := (endYear-startYear)*12 + int(endMonth-startMonth)
- if endDay-startDay > 0 {
- months += 1
- }
- //fmt.Printf("月份差异为:%d\n", months)
- return months
- }
|