|
@@ -0,0 +1,430 @@
|
|
|
+package order
|
|
|
+
|
|
|
+import (
|
|
|
+ "app.yhyue.com/moapp/jybase/common"
|
|
|
+ "context"
|
|
|
+ "fmt"
|
|
|
+ "github.com/gogf/gf/v2/frame/g"
|
|
|
+ "github.com/gogf/gf/v2/util/gconv"
|
|
|
+ uuid2 "github.com/google/uuid"
|
|
|
+ "github.com/pkg/errors"
|
|
|
+ "jyOrderManager/internal/jyutil"
|
|
|
+ "jyOrderManager/internal/model"
|
|
|
+ "log"
|
|
|
+ "sort"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+// OrderSaleOperation 查询/更新销售业绩
|
|
|
+//func OrderSaleOperation(context *admin.Context) (interface{}, error) {
|
|
|
+// param := new(struct {
|
|
|
+// DoType string `form:"doType" doc:"query|update"`
|
|
|
+// OrderCode string `form:"orderCode" doc:"订单号"`
|
|
|
+// Reason string `form:"reason" doc:"变更原因"`
|
|
|
+// model.SalesMoney string `form:"salesMoney" doc:"新业绩划分"`
|
|
|
+// NewValue []*model.SalesMoney
|
|
|
+// })
|
|
|
+// err := context.Form(param)
|
|
|
+// if err != nil || param == nil {
|
|
|
+// return nil, fmt.Errorf("参数异常")
|
|
|
+// }
|
|
|
+// if param.OrderCode == "" {
|
|
|
+// return nil, fmt.Errorf("缺少订单参数")
|
|
|
+// }
|
|
|
+//
|
|
|
+// switch param.DoType {
|
|
|
+// case "query": // 查询当前业绩
|
|
|
+// res := config.JysqlDB.SelectBySql("SELECT saler_name,saler_Id,saler_dept,money,distribution_channel FROM order_sale_record where ordercode=? and state=1", param.OrderCode)
|
|
|
+// if res == nil || len(*res) == 0 {
|
|
|
+// return nil, fmt.Errorf("未查询到业绩数据")
|
|
|
+// }
|
|
|
+// var rData []map[string]interface{}
|
|
|
+// for _, m := range *res {
|
|
|
+// rData = append(rData, map[string]interface{}{
|
|
|
+// "name": m["saler_name"],
|
|
|
+// "id": m["saler_Id"],
|
|
|
+// "saler_dept": m["saler_dept"],
|
|
|
+// "money": m["money"],
|
|
|
+// "distribution_channel": m["distribution_channel"],
|
|
|
+// })
|
|
|
+// }
|
|
|
+// return map[string]interface{}{
|
|
|
+// "list": rData,
|
|
|
+// "reason": config.SysConfigs.SaleChangeReason,
|
|
|
+// }, nil
|
|
|
+// case "update": //更新业绩
|
|
|
+// if err := gconv.Struct(param.model.SalesMoney, ¶m.NewValue); err != nil {
|
|
|
+// return nil, fmt.Errorf("参数校验异常")
|
|
|
+// }
|
|
|
+// if err := OrderSalerChange(param.NewValue, param.OrderCode, context.User.Username, param.Reason); err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+// return "success", nil
|
|
|
+// default:
|
|
|
+// return nil, fmt.Errorf("未知操作")
|
|
|
+// }
|
|
|
+//}
|
|
|
+
|
|
|
+// saleSaveRecordTmp 销售业绩暂存
|
|
|
+var saleSaveRecordTmp = func(ctx context.Context, orderCode, createPerson string, record []*model.SalesMoney) error {
|
|
|
+ if len(record) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ var (
|
|
|
+ saveList []map[string]interface{}
|
|
|
+ uuid = uuid2.New().String()
|
|
|
+ now = time.Now().Local().Format(time.DateTime)
|
|
|
+ )
|
|
|
+ for _, s := range record {
|
|
|
+ deptId, deptName, userName, err := jyutil.JyDepartmentManager.GetDeptInfoByEntId(ctx, s.Id)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("获取用户%d部门异常", s.Id)
|
|
|
+ }
|
|
|
+ saveList = append(saveList, map[string]interface{}{
|
|
|
+ "state": 2,
|
|
|
+ "ordercode": orderCode,
|
|
|
+ "saler_Id": s.Id,
|
|
|
+ "saler_name": userName,
|
|
|
+ "saler_dept": deptName,
|
|
|
+ "saler_dept_id": deptId,
|
|
|
+ "money": s.Money,
|
|
|
+ "change_value": s.Money,
|
|
|
+ "group_uuid": uuid,
|
|
|
+ "operator": createPerson,
|
|
|
+ "create_time": now,
|
|
|
+ "distribution_channel": s.Channel,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ res, err := g.DB().Save(ctx, "order_sale_record", saveList, 1)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("暂存销售业绩保存异常")
|
|
|
+ }
|
|
|
+ if num, _ := res.RowsAffected(); gconv.Int(num) != len(saveList) {
|
|
|
+ return fmt.Errorf("暂存销售业绩数量校验异常")
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// SaveOrUpdateSaleMoneyTmp 插入更新暂存销售业绩(未完成订单可修改,管理员可在订单改为完成时修改)
|
|
|
+func SaveOrUpdateSaleMoneyTmp(ctx context.Context, orderCode, createPerson string, record []*model.SalesMoney) error {
|
|
|
+ var oldSalesMoney []*model.SalesMoney
|
|
|
+ for _, row := range record {
|
|
|
+ if row.Channel == "" {
|
|
|
+ return fmt.Errorf("请选择销售渠道")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //对比是否改变销售业绩
|
|
|
+ recordRes, err := g.DB().Query(ctx, "SELECT ent_userId,money,distribution_channel FROM order_sale_record WHERE ordercode=? and state=2 order by ent_userId asc", orderCode)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, "查询业绩异常")
|
|
|
+ }
|
|
|
+ if !recordRes.IsEmpty() {
|
|
|
+ if recordRes.Len() == len(record) { //数量不对等
|
|
|
+ for _, m := range recordRes.List() {
|
|
|
+ oldSalesMoney = append(oldSalesMoney, &model.SalesMoney{
|
|
|
+ Id: common.IntAll(m["ent_userId"]),
|
|
|
+ Money: common.IntAll(m["money"]),
|
|
|
+ Channel: gconv.String(m["distribution_channel"]),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ sort.Slice(record, func(i, j int) bool {
|
|
|
+ return record[i].Id < record[j].Id
|
|
|
+ })
|
|
|
+ //业绩无变更
|
|
|
+ if gconv.String(record) == gconv.String(oldSalesMoney) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //更新变更后的业绩
|
|
|
+ _, err := g.DB().Update(ctx, "order_sale_record", g.Map{
|
|
|
+ "state": -2,
|
|
|
+ }, " state=2 and ordercode=? ", orderCode)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, "暂存业绩修改异常")
|
|
|
+ }
|
|
|
+ if saleSaveRecordTmp(ctx, orderCode, createPerson, record) != nil {
|
|
|
+ return fmt.Errorf("暂存新业绩销售异常")
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+ } else {
|
|
|
+ //新增销售业绩
|
|
|
+ return saleSaveRecordTmp(ctx, orderCode, createPerson, record)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// OrderMoneyMakeRed 订单红冲 销售业绩更改
|
|
|
+func OrderMoneyMakeRed(ctx context.Context, orderCode string, final int64) error {
|
|
|
+ var (
|
|
|
+ oldTotal int64 = 0
|
|
|
+ emptyMoneyRow, notEmptyMoneyRow []map[string]interface{}
|
|
|
+ )
|
|
|
+ oldRes, err := g.DB().Query(ctx, "SELECT ordercode,state,ent_userId,saler_name,saler_dept,saler_dept_id,money,change_value,group_uuid,last_group_uuid,change_reason,operator,statistics_time,create_time,distribution_channel FROM order_sale_record WHERE ordercode=? and state=1", orderCode)
|
|
|
+ if err != nil || oldRes.IsEmpty() {
|
|
|
+ return errors.Wrap(err, "业绩红冲未找到对应订单")
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, m := range oldRes.List() {
|
|
|
+ money := gconv.Int64(m["money"])
|
|
|
+ oldTotal += money
|
|
|
+ if money == 0 {
|
|
|
+ emptyMoneyRow = append(emptyMoneyRow, m)
|
|
|
+ } else {
|
|
|
+ notEmptyMoneyRow = append(notEmptyMoneyRow, m)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if oldTotal == 0 {
|
|
|
+ log.Printf("OrderMoneyMakeRed 业绩总数为空")
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ // 当前业绩改为历史业绩
|
|
|
+ _, err = g.DB().Update(ctx, "order_sale_record", g.Map{
|
|
|
+ "state": -1,
|
|
|
+ }, "state=1 and ordercode=?", orderCode)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, "")
|
|
|
+ }
|
|
|
+
|
|
|
+ var (
|
|
|
+ newUUid = uuid2.New().String()
|
|
|
+ nowTime = time.Now().Local().Format(time.DateTime)
|
|
|
+ )
|
|
|
+ for _, m := range emptyMoneyRow {
|
|
|
+ m["last_group_uuid"] = m["group_uuid"]
|
|
|
+ m["group_uuid"] = newUUid
|
|
|
+ m["create_time"] = nowTime
|
|
|
+ m["statistics_time"] = nowTime
|
|
|
+ m["change_value"] = 0
|
|
|
+ if _, err := g.DB().Save(ctx, "order_sale_record", m); err != nil {
|
|
|
+ return errors.Wrap(err, "业绩红冲 插入空业绩记录异常")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var surplus int64 = 0
|
|
|
+ for _, m := range notEmptyMoneyRow {
|
|
|
+ var (
|
|
|
+ money = gconv.Int64(m["money"])
|
|
|
+ newMoney = ((money * final) + surplus) / oldTotal
|
|
|
+ )
|
|
|
+ if t := ((money * final) + surplus) % oldTotal; t != 0 {
|
|
|
+ surplus += t
|
|
|
+ }
|
|
|
+ m["last_group_uuid"] = m["group_uuid"]
|
|
|
+ m["group_uuid"] = newUUid
|
|
|
+ m["create_time"] = nowTime
|
|
|
+ m["statistics_time"] = nowTime
|
|
|
+ m["money"] = newMoney
|
|
|
+ m["change_reason"] = "订单红冲"
|
|
|
+ m["change_value"] = newMoney - money
|
|
|
+ if _, err := g.DB().Save(ctx, "order_sale_record", m); err != nil {
|
|
|
+ return errors.Wrap(err, "业绩红冲 插入非空业绩记录异常")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// OrderSalerChange 业绩变更
|
|
|
+func OrderSalerChange(ctx context.Context, newSales []*model.SalesMoney, orderCode, operator, reason string) error {
|
|
|
+ var (
|
|
|
+ newMoneyTotal int = 0
|
|
|
+ oldSallerMap, oldSallerChannel = map[int]int{}, map[int]string{} //新业绩、旧业绩
|
|
|
+ lastUUid string
|
|
|
+ )
|
|
|
+
|
|
|
+ for _, row := range newSales {
|
|
|
+ newMoneyTotal += row.Money
|
|
|
+ if row.Channel == "" {
|
|
|
+ return fmt.Errorf("请选择销售渠道")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if newMoneyTotal == 0 {
|
|
|
+ return fmt.Errorf("请填写业绩信息")
|
|
|
+ }
|
|
|
+ if reason == "" {
|
|
|
+ return fmt.Errorf("请填写业绩业绩变更原因")
|
|
|
+ }
|
|
|
+ orderRes, err := g.DB().GetOne(ctx, "SELECT pay_money,order_status FROM dataexport_order WHERE ordercode=?", orderCode)
|
|
|
+ if err != nil || orderRes.IsEmpty() {
|
|
|
+ return fmt.Errorf("业绩变成 未查询到订单信息")
|
|
|
+ }
|
|
|
+ var (
|
|
|
+ orderMap = orderRes.Map()
|
|
|
+ pay_money = gconv.Int(orderMap["pay_money"])
|
|
|
+ order_status = gconv.Int(orderMap["order_status"])
|
|
|
+ )
|
|
|
+
|
|
|
+ if order_status != 1 {
|
|
|
+ return fmt.Errorf("该订单未支付")
|
|
|
+ }
|
|
|
+ if newMoneyTotal > pay_money {
|
|
|
+ return fmt.Errorf("销售业绩变更 合计需≤合同金额%.2f元", gconv.Float64(pay_money)/100)
|
|
|
+ }
|
|
|
+
|
|
|
+ var (
|
|
|
+ oldSalesMoney []*model.SalesMoney
|
|
|
+ oldMapping = map[int]map[string]interface{}{}
|
|
|
+ )
|
|
|
+ dbRes, err := g.DB().Query(ctx, "SELECT ordercode,state,ent_userId,saler_name,saler_dept,saler_dept_id,money,change_value,group_uuid,last_group_uuid,change_reason,operator,statistics_time,distribution_channel,create_time FROM order_sale_record WHERE ordercode=? and state=1 order by ent_userId asc", orderCode)
|
|
|
+ if err != nil || dbRes.IsEmpty() {
|
|
|
+ return fmt.Errorf("销售业绩变更 查询旧业绩数据异常")
|
|
|
+ }
|
|
|
+
|
|
|
+ //校验业绩是否变更
|
|
|
+ for _, m := range dbRes.List() {
|
|
|
+ var (
|
|
|
+ money = gconv.Int(m["money"])
|
|
|
+ salerId = gconv.Int(m["ent_userId"])
|
|
|
+ channel = gconv.String(m["distribution_channel"])
|
|
|
+ )
|
|
|
+ oldSallerMap[salerId] = money
|
|
|
+ oldSallerChannel[salerId] = channel
|
|
|
+ if lastUUid == "" {
|
|
|
+ lastUUid = gconv.String(m["group_uuid"])
|
|
|
+ }
|
|
|
+ oldMapping[salerId] = m
|
|
|
+ oldSalesMoney = append(oldSalesMoney, &model.SalesMoney{
|
|
|
+ Id: salerId,
|
|
|
+ Money: money,
|
|
|
+ Channel: channel,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ sort.Slice(newSales, func(i, j int) bool {
|
|
|
+ return newSales[i].Id < newSales[j].Id
|
|
|
+ })
|
|
|
+ //业绩无变更
|
|
|
+ if gconv.String(newSales) == gconv.String(oldSalesMoney) {
|
|
|
+ return fmt.Errorf("业绩未变更")
|
|
|
+ }
|
|
|
+
|
|
|
+ //开始操作
|
|
|
+ //var operaErr error
|
|
|
+ //ok := config.JysqlDB.ExecTx("销售业绩红冲", func(tx *sql.Tx) bool {
|
|
|
+ //旧业绩改为历史业绩
|
|
|
+ if _, err := g.DB().Update(ctx, "order_sale_record", g.Map{
|
|
|
+ "state": -1,
|
|
|
+ }, "state=1 and ordercode=?", orderCode); err != nil {
|
|
|
+ return errors.Wrap(err, "旧业绩更改失败")
|
|
|
+ }
|
|
|
+ var (
|
|
|
+ saveList []map[string]interface{}
|
|
|
+ newUUid = uuid2.New().String()
|
|
|
+ nowTime = time.Now().Local().Format(time.DateTime)
|
|
|
+ insertEd = map[int]bool{}
|
|
|
+ )
|
|
|
+ for _, row := range newSales {
|
|
|
+ deptId, deptName, userName, err := jyutil.JyDepartmentManager.GetDeptInfoByEntId(ctx, row.Id)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, fmt.Sprintf("%s 业绩变更获取 %d 部门异常\n", orderCode, row.Id))
|
|
|
+ }
|
|
|
+ changeValue := row.Money - oldSallerMap[row.Id]
|
|
|
+ if changeValue == 0 { //业绩未变动
|
|
|
+ m := oldMapping[row.Id]
|
|
|
+ m["last_group_uuid"] = lastUUid
|
|
|
+ m["group_uuid"] = newUUid
|
|
|
+ m["create_time"] = nowTime
|
|
|
+ m["statistics_time"] = nowTime
|
|
|
+ m["change_value"] = 0
|
|
|
+ if row.Channel != oldSallerChannel[row.Id] { //渠道更新
|
|
|
+ m["distribution_channel"] = row.Channel
|
|
|
+ }
|
|
|
+ saveList = append(saveList, m)
|
|
|
+ } else { //业绩变更
|
|
|
+ saveList = append(saveList, map[string]interface{}{
|
|
|
+ "state": 1,
|
|
|
+ "ordercode": orderCode,
|
|
|
+ "ent_userId": row.Id,
|
|
|
+ "saler_name": userName,
|
|
|
+ "saler_dept": deptName,
|
|
|
+ "saler_dept_id": deptId,
|
|
|
+ "change_value": changeValue,
|
|
|
+ "money": row.Money,
|
|
|
+ "group_uuid": newUUid,
|
|
|
+ "last_group_uuid": lastUUid,
|
|
|
+ "operator": operator,
|
|
|
+ "change_reason": reason,
|
|
|
+ "create_time": nowTime,
|
|
|
+ "statistics_time": nowTime,
|
|
|
+ "distribution_channel": row.Channel,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ insertEd[row.Id] = true
|
|
|
+ }
|
|
|
+ for salerId, m := range oldMapping {
|
|
|
+ if insertEd[salerId] {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ m["last_group_uuid"] = lastUUid
|
|
|
+ m["group_uuid"] = newUUid
|
|
|
+ m["create_time"] = nowTime
|
|
|
+ m["statistics_time"] = nowTime
|
|
|
+ m["change_reason"] = reason
|
|
|
+ m["operator"] = operator
|
|
|
+ if money := gconv.Int(m["money"]); money != 0 {
|
|
|
+ m["money"] = 0
|
|
|
+ m["change_value"] = -oldSallerMap[salerId]
|
|
|
+ } else {
|
|
|
+ m["change_value"] = 0
|
|
|
+ }
|
|
|
+ saveList = append(saveList, m)
|
|
|
+ }
|
|
|
+ if _, err := g.DB().Insert(ctx, "order_sale_record", saveList); err != nil {
|
|
|
+ return errors.Wrap(err, "业绩变更插入业绩异常")
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// TakeEffectSale 管理后台销售业绩生效
|
|
|
+// effectTime 业绩统计时间
|
|
|
+// 1.非0元订单,订单状态由“未完成”变更为“已完成”,且协议归档状态为“已归档”,且回款状态为“未回款”,则系统自动生成“业绩归属变更”数据,变更原因为“协议归档”
|
|
|
+// 2.协议归档状态为未归档,订单状态为“已完成”,订单首次回款后,则系统自动生成1条“业绩变更”数据,变更原因为“回款成功”
|
|
|
+func TakeEffectSale(ctx context.Context, orderCode, reason string, effectTime string) error {
|
|
|
+ affect, err := g.DB().Update(ctx, "order_sale_record", g.Map{
|
|
|
+ "state": 1,
|
|
|
+ "change_reason": reason,
|
|
|
+ "statistics_time": effectTime,
|
|
|
+ "operator": "系统自动",
|
|
|
+ }, "state=2 and ordercode=?", orderCode)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, fmt.Sprintf("TakeEffectSale %s 激活的销售业绩失败", orderCode))
|
|
|
+ }
|
|
|
+ rowCount, err := affect.RowsAffected()
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, "获取待激活业绩异常")
|
|
|
+ }
|
|
|
+ if rowCount == 0 {
|
|
|
+ return fmt.Errorf("TakeEffectSale %s 无待激活的销售业绩", orderCode)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// CommonChange 销售业绩生效+订单业绩统计时间更新
|
|
|
+// 仅【协议归档/回款(首次)】时
|
|
|
+// func CommonChange2(returnStatus, ContractStatus int, orderCode, contractArchiveTime string) {
|
|
|
+func CommonChange(ctx context.Context, orderCode, operationTime string, operationType int) error {
|
|
|
+ var (
|
|
|
+ reason = "回款成功"
|
|
|
+ affectTime = operationTime
|
|
|
+ )
|
|
|
+ if operationType == ReturnProtocol { //未回款、已归档
|
|
|
+ //校验是否首次归档
|
|
|
+ count, err := g.DB().GetCount(ctx, "SELECT count(*) FROM contract WHERE contract_archive_status=1 AND order_code=?", orderCode)
|
|
|
+ if err != nil {
|
|
|
+ return errors.Wrap(err, "查询是否首次回款异常")
|
|
|
+ }
|
|
|
+ if count > 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ reason = "协议归档"
|
|
|
+ }
|
|
|
+ if affectTime == "" {
|
|
|
+ affectTime = time.Now().Local().Format(time.DateTime)
|
|
|
+ }
|
|
|
+ if err := TakeEffectSale(ctx, orderCode, reason, affectTime); err != nil {
|
|
|
+ log.Printf("TakeEffectSale %d %s失败 %v", operationType, orderCode, err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if _, err := g.DB().Update(ctx, "dataexport_order", g.Map{
|
|
|
+ "sale_time": affectTime,
|
|
|
+ }, "order_code=?", orderCode); err != nil {
|
|
|
+ log.Printf("TakeEffectSale %d %s", operationType, err.Error())
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|