orderHandler.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. package controller
  2. import (
  3. . "app.yhyue.com/moapp/jybase/api"
  4. "app.yhyue.com/moapp/jybase/common"
  5. "app.yhyue.com/moapp/jybase/date"
  6. "context"
  7. "fmt"
  8. "github.com/gogf/gf/v2/database/gdb"
  9. "github.com/gogf/gf/v2/errors/gerror"
  10. "github.com/gogf/gf/v2/frame/g"
  11. "github.com/gogf/gf/v2/net/ghttp"
  12. "github.com/gogf/gf/v2/util/gconv"
  13. "github.com/pkg/errors"
  14. "jyOrderManager/internal/jyutil"
  15. "jyOrderManager/internal/logic/order"
  16. "jyOrderManager/internal/logic/product"
  17. "jyOrderManager/internal/model"
  18. "jyOrderManager/internal/service"
  19. "strings"
  20. "time"
  21. )
  22. var checkOrderProduct = func(ctx context.Context, orderCode string, param model.OrderParams, oldOrderRes ...g.Map) (productArr []product.JyProduct, removeOrderDetailIds []int64, masterKey string, priceFinal, priceOriginal, commissionCheck int, err error) {
  23. var (
  24. actProduct = map[string]map[string]product.JyProduct{}
  25. orderMap g.Map
  26. existsOrderDetailIds = map[int64]bool{}
  27. update = false
  28. )
  29. if len(oldOrderRes) > 0 {
  30. orderMap, update = oldOrderRes[0], true
  31. }
  32. // 订单参数基础校验
  33. if param.EmptyPhone != 1 && param.PersonPhone == "" {
  34. err = fmt.Errorf("订单参数异常")
  35. return
  36. }
  37. if update { //待审核和已完成订单禁止修改
  38. var orderDetailRes gdb.Result
  39. orderDetailRes, err = g.DB().Query(ctx, "SELECT id FROM jy_order_detail WHERE order_code=?", param.OrderCode)
  40. if err != nil || orderDetailRes.IsEmpty() {
  41. err = gerror.Wrapf(err, "为查询到订单明细")
  42. return
  43. }
  44. var (
  45. orderStatus = gconv.Int(orderMap["order_status"])
  46. auditStatus = gconv.Int(orderMap["audit_status"])
  47. )
  48. if auditStatus > 0 || orderStatus == 1 {
  49. err = errors.New("当前订单状态禁止修改")
  50. return
  51. }
  52. for _, m := range orderDetailRes.List() {
  53. existsOrderDetailIds[gconv.Int64(m["id"])] = true
  54. }
  55. }
  56. var (
  57. maxPrice int
  58. )
  59. //大会员超级订阅同订单不能多次购买
  60. hasVipCheckMap := map[string]bool{}
  61. for _, tParam := range param.ProductArr {
  62. orderDetailId := gconv.Int64(tParam["id"])
  63. if update {
  64. if orderDetailId == 0 {
  65. err = fmt.Errorf("商品修改缺少id")
  66. return
  67. }
  68. existsOrderDetailIds[orderDetailId] = false
  69. }
  70. //参数注入
  71. if param.EmptyPhone != 1 {
  72. tParam["phone"] = param.PersonPhone //开通手机号
  73. }
  74. tParam["order_code"] = orderCode //订单号
  75. tParam["reqSubject"] = param.BuySubject //购买主体
  76. tParam["reqCompanyName"] = param.CompanyName //公司名称
  77. var (
  78. productCode = gconv.String(tParam["product_code"])
  79. amount = gconv.Int(tParam["amount"])
  80. originalPrice = gconv.Int(tParam["original_price"])
  81. )
  82. productClass, pErr := service.Product().GetProductClassByProductCode(productCode)
  83. if pErr != nil {
  84. err = fmt.Errorf("请勿重复选购会员商品")
  85. return
  86. }
  87. if productClass.Code == "dyh" || productClass.Code == "cjdy" {
  88. if hasVipCheckMap[productClass.Code] {
  89. err = fmt.Errorf("请勿重复选购会员商品")
  90. return
  91. }
  92. hasVipCheckMap[productClass.Code] = true
  93. }
  94. //计算销售费用
  95. if productClass.TopClass == "外采赠品" {
  96. commissionCheck += originalPrice - amount
  97. }
  98. pFunc, pErr := product.JyProFunc.GetProductInitFuncByCode(productCode)
  99. if pErr != nil {
  100. err = gerror.Wrapf(pErr, "获取商品异常")
  101. return
  102. }
  103. pObj, pErr := pFunc(tParam)
  104. if pErr != nil {
  105. err = gerror.Wrap(pErr, fmt.Sprintf("获取%s商品异常", productCode))
  106. return
  107. }
  108. //获取价格最贵的商品作为主商品
  109. if amount > maxPrice {
  110. maxPrice = amount
  111. masterKey = fmt.Sprintf("%s_%d", productCode, amount)
  112. }
  113. var (
  114. actCode = gconv.String(tParam["activityCode"]) //活动code
  115. checkCode = common.If(common.If(actCode != "", 2, 1).(int) == 2 || param.EmptyPhone == 1, 2, 1).(int) //1全额校验 2不校验是否满足购买需求(活动和暂无手机号)
  116. )
  117. if actCode != "" { //活动商品
  118. if _, ok := actProduct[actCode]; ok {
  119. actProduct[actCode][productCode] = pObj
  120. } else {
  121. actProduct[actCode] = map[string]product.JyProduct{productCode: pObj}
  122. }
  123. } else { //单个商品价格
  124. if originalPrice := gconv.Int(originalPrice); originalPrice > 0 {
  125. priceOriginal += originalPrice
  126. }
  127. if amount > 0 {
  128. priceFinal += amount
  129. }
  130. }
  131. if err = pObj.Check(ctx, checkCode); err != nil {
  132. return
  133. }
  134. productArr = append(productArr, pObj)
  135. }
  136. if len(productArr) == 0 {
  137. err = fmt.Errorf("订单商品为空")
  138. return
  139. }
  140. // 活动商品校验完整,防止缺少增加商品
  141. if len(actProduct) > 0 {
  142. now := time.Now()
  143. for actCode, productList := range actProduct {
  144. act := service.Product().GetActivityByCode(actCode)
  145. //当前用户是否有权限
  146. if !service.Product().PowerCheck(act.Code, jyutil.GetUserDeptIdFromCtx(ctx)) {
  147. err = fmt.Errorf("没有创建%s活动的权限", act.Name)
  148. return
  149. }
  150. if act == nil {
  151. err = fmt.Errorf("未知活动code %s", actCode)
  152. return
  153. }
  154. if now.After(act.EndTime) || now.Before(act.StartTime) {
  155. err = fmt.Errorf("活动%s不在有效期", actCode)
  156. return
  157. }
  158. if len(productList) != len(act.Products) {
  159. err = fmt.Errorf("活动产品不完整 %s", actCode)
  160. return
  161. }
  162. if act.Price > 0 {
  163. priceOriginal += act.Price
  164. }
  165. if param.ActPrice["actCode"] > 0 {
  166. priceFinal += param.ActPrice["actCode"]
  167. }
  168. }
  169. }
  170. for orderDetailId, ok := range existsOrderDetailIds {
  171. if ok {
  172. removeOrderDetailIds = append(removeOrderDetailIds, orderDetailId)
  173. }
  174. }
  175. return
  176. }
  177. // SaveOrderHandler 创建订单
  178. func SaveOrderHandler(r *ghttp.Request) {
  179. rData, err := func() (interface{}, error) {
  180. var (
  181. param model.OrderParams
  182. ctx = r.Context()
  183. uMsg = jyutil.GetUserMsgFromCtx(ctx)
  184. userName = uMsg.EntUserName
  185. entUserId = uMsg.EntUserId
  186. masterKey string
  187. priceFinal, priceOriginal, commissionCheck int
  188. productArr []product.JyProduct
  189. orderCode = fmt.Sprintf("%s%s", time.Now().Format("150405"), common.GetRandom(6))
  190. )
  191. err := gconv.Struct(r.GetBody(), &param)
  192. if err != nil {
  193. return nil, gerror.Wrapf(err, "数据校验异常")
  194. }
  195. //产品参数校验
  196. productArr, _, masterKey, priceFinal, priceOriginal, commissionCheck, err = checkOrderProduct(ctx, orderCode, param)
  197. if err != nil {
  198. return nil, err
  199. }
  200. if priceFinal != param.ContractMoney || priceOriginal != param.OrderMoney {
  201. return nil, fmt.Errorf("价格核对异常")
  202. }
  203. if commissionCheck != param.ChannelCommission {
  204. return nil, fmt.Errorf("销售费用合算异常")
  205. }
  206. //数据库操作
  207. if err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  208. //todo 插入订单表
  209. if _, err := g.DB().Ctx(ctx).Insert(ctx, "dataexport_order", g.Map{
  210. "order_code": orderCode,
  211. "order_money": param.OrderMoney,
  212. "pay_money": param.ContractMoney,
  213. "pay_way": param.PayType,
  214. "product_type": getProductNameByMasterKey(masterKey),
  215. "order_status": 0,
  216. "user_phone": param.PersonPhone,
  217. "personPhone": param.ContactsPhone,
  218. "personName": param.ContactsName,
  219. "company_name": param.CompanyName,
  220. "is_backstage_order": 1,
  221. "commission": param.ChannelCommission,
  222. "order_channel": param.OrderChannel,
  223. "create_time": time.Now().Format("2006-01-02 15:04:05"),
  224. "create_person": userName,
  225. "last_update_person": userName,
  226. "salesperson_entUserId": entUserId,
  227. "signing_subject": param.PaybackCompany,
  228. "audit_status": common.If(param.Save == 1, 0, 1),
  229. "buy_subject": param.BuySubject,
  230. "payment_user": param.PaymentUser,
  231. "zero_type": param.ZeroOrderType,
  232. "remark": param.OrderRemark,
  233. "user_id": jyutil.GetCommonUserIdByPhone(ctx, param.PersonPhone, param.CompanyName, param.BuySubject),
  234. }); err != nil {
  235. return gerror.Wrap(err, "插入订单表异常")
  236. }
  237. //todo 订单详情表
  238. for _, p := range productArr {
  239. //是否是主商品
  240. if err := p.SaveUpdate(ctx, masterKey); err != nil {
  241. return gerror.Wrapf(err, "插入商品明细异常")
  242. }
  243. }
  244. //todo 销售业绩
  245. if err := order.SaveOrUpdateSaleMoneyTmp(ctx, orderCode, userName, param.SaleMoney, param.ContractMoney-param.ChannelCommission); err != nil {
  246. return gerror.Wrapf(err, "销售业绩异常")
  247. }
  248. //todo 合同
  249. if err := order.SaveOrUpdateContract(ctx, orderCode, param.CompanyName, param.ContractMoney, param.Contract); err != nil {
  250. return gerror.Wrapf(err, "合同异常")
  251. }
  252. //todo 回款计划
  253. if err := order.SaveOrUpdateReturnPlant(ctx, orderCode, param.ContractMoney, param.ReturnPlant); err != nil {
  254. return gerror.Wrapf(err, "回款计划异常")
  255. }
  256. if param.Save == 2 {
  257. //todo 审核记录
  258. if _, err = g.DB().Save(ctx, "audit_records", map[string]interface{}{
  259. "operator": userName,
  260. "create_time": date.NowFormat(date.Date_Full_Layout),
  261. "operator_type": 1,
  262. "audit_status": 1,
  263. "order_code": orderCode,
  264. "audit_type": 2,
  265. }); err != nil {
  266. return gerror.Wrapf(err, "审核记录异常")
  267. }
  268. }
  269. return nil
  270. }); err != nil {
  271. return nil, gerror.Wrapf(err, "数据库操作异常")
  272. }
  273. return orderCode, nil
  274. }()
  275. if err != nil {
  276. g.Log().Errorf(r.Context(), "创建订单异常 %v", err)
  277. }
  278. r.Response.WriteJson(NewResult(rData, err))
  279. }
  280. // UpdateOrderHandler 订单修改
  281. func UpdateOrderHandler(r *ghttp.Request) {
  282. rData, err := func() (interface{}, error) {
  283. var (
  284. param model.OrderParams
  285. ctx = r.Context()
  286. uMsg = jyutil.GetUserMsgFromCtx(ctx)
  287. userName = uMsg.EntUserName
  288. entUserId = uMsg.EntUserId
  289. masterKey string
  290. priceFinal, priceOriginal int
  291. )
  292. err := gconv.Struct(r.GetBody(), &param)
  293. if err != nil {
  294. return nil, gerror.Wrapf(err, "数据校验异常")
  295. }
  296. if param.OrderCode == "" {
  297. return nil, gerror.New("缺少订单编号")
  298. }
  299. orderRes, err := g.DB().GetOne(ctx, "SELECT * FROM dataexport_order WHERE order_code=?", param.OrderCode)
  300. if err != nil || orderRes.IsEmpty() {
  301. err = gerror.Wrapf(err, "未知订单")
  302. return nil, err
  303. }
  304. //产品参数校验
  305. productArr, removeIds, masterKey, priceFinal, priceOriginal, commissionCheck, err := checkOrderProduct(ctx, param.OrderCode, param, orderRes.Map())
  306. if err != nil {
  307. return nil, err
  308. }
  309. if priceFinal != param.ContractMoney || priceOriginal != param.OrderMoney {
  310. return nil, fmt.Errorf("价格核对异常")
  311. }
  312. if commissionCheck != param.ChannelCommission {
  313. return nil, fmt.Errorf("销售费用合算异常")
  314. }
  315. //数据库操作
  316. if err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  317. upOrder := g.Map{
  318. "order_money": param.OrderMoney,
  319. "pay_money": param.ContractMoney,
  320. "pay_way": param.PayType,
  321. "product_type": getProductNameByMasterKey(masterKey),
  322. "order_status": param.OrderStatus,
  323. "user_phone": param.PersonPhone,
  324. "company_name": param.CompanyName,
  325. "is_backstage_order": 1,
  326. "commission": param.ChannelCommission,
  327. "order_channel": param.OrderChannel,
  328. "create_person": userName,
  329. "last_update_person": userName,
  330. "salesperson_entUserId": entUserId,
  331. "signing_subject": param.PaybackCompany,
  332. "audit_status": common.If(param.Save == 1, 0, 1),
  333. "buy_subject": param.BuySubject,
  334. "payment_user": param.PaymentUser,
  335. "zero_type": param.ZeroOrderType,
  336. "remark": param.OrderRemark,
  337. "user_id": jyutil.GetCommonUserIdByPhone(ctx, param.PersonPhone, param.CompanyName, param.BuySubject),
  338. }
  339. //退回单子重新编辑提交后更改审核状态
  340. if auditStatus := gconv.Int(orderRes.Map()["audit_status"]); auditStatus < 0 {
  341. upOrder["order_status"] = 0
  342. upOrder["audit_status"] = SwitchAudit(auditStatus)
  343. }
  344. //编辑回退订单或未完成订单
  345. if _, err = g.DB().Ctx(ctx).Update(ctx, "dataexport_order", upOrder, "order_code=? and order_status=0 ", param.OrderCode); err != nil {
  346. return gerror.Wrap(err, "修改订单表内容异常")
  347. }
  348. //todo 删除已经不存在的商品
  349. for _, id := range removeIds {
  350. if _, err := g.DB().Update(ctx, "jy_order_detail", g.Map{
  351. "status": 2,
  352. }, "id=? and order_code=?", id, param.OrderCode); err != nil {
  353. return gerror.Wrapf(err, "删除旧订单明细内容异常")
  354. }
  355. }
  356. //todo 订单详情表
  357. for _, p := range productArr {
  358. if err := p.SaveUpdate(ctx, masterKey); err != nil {
  359. return gerror.Wrapf(err, "插入商品明细异常")
  360. }
  361. }
  362. //todo 销售业绩 p610.管理后台创建订单,订单状态为已完成(不包含从未完成改成已完成,未提交的状态),“销售人员”、“销售业绩”、“销售渠道”不支持编辑;
  363. if gconv.Int(orderRes["order_status"]) == 0 {
  364. err = order.SaveOrUpdateSaleMoneyTmp(ctx, param.OrderCode, userName, param.SaleMoney, param.ContractMoney-param.ChannelCommission)
  365. if err != nil {
  366. return err
  367. }
  368. }
  369. //todo 合同
  370. if err := order.SaveOrUpdateContract(ctx, param.OrderCode, param.CompanyName, param.ContractMoney, param.Contract); err != nil {
  371. return gerror.Wrapf(err, "合同异常")
  372. }
  373. //todo 回款计划
  374. if err := order.SaveOrUpdateReturnPlant(ctx, param.OrderCode, param.ContractMoney, param.ReturnPlant); err != nil {
  375. return gerror.Wrapf(err, "回款计划异常")
  376. }
  377. return nil
  378. }); err != nil {
  379. return nil, gerror.Wrapf(err, "数据库操作异常")
  380. }
  381. return nil, err
  382. }()
  383. if err != nil {
  384. g.Log().Errorf(r.Context(), "订单修改异常 %v", err)
  385. }
  386. r.Response.WriteJson(NewResult(rData, err))
  387. }
  388. // GetContractPdfHandler 电子pdf合同
  389. func GetContractPdfHandler(r *ghttp.Request) {
  390. rData, err := func() (interface{}, error) {
  391. rj, err := r.GetJson()
  392. if err != nil {
  393. return nil, errors.Wrap(err, "请求参数格式异常")
  394. }
  395. var (
  396. orderCode = rj.Get("orderCode").String()
  397. ctx = r.Context()
  398. uMsg = jyutil.GetUserMsgFromCtx(ctx)
  399. userName = uMsg.EntUserName
  400. )
  401. pdfPath, err := order.GetContractPdf(ctx, orderCode, userName)
  402. if err != nil {
  403. return nil, err
  404. }
  405. return pdfPath, nil
  406. }()
  407. if err != nil {
  408. g.Log().Errorf(r.Context(), "生成电子pdf合同出错 %v", err)
  409. }
  410. r.Response.WriteJson(NewResult(rData, err))
  411. }
  412. func getProductNameByMasterKey(masterKey string) string {
  413. if arr := strings.Split(masterKey, "_"); len(arr) > 0 {
  414. var productCode = arr[0]
  415. mp, err := service.Product().GetProduct(productCode)
  416. if err != nil {
  417. return ""
  418. }
  419. mc, err := service.Product().GetProductClass(mp.ProductClassId)
  420. if err != nil {
  421. return ""
  422. }
  423. if mc.ClassName == "超级订阅" {
  424. return "VIP订阅"
  425. }
  426. return mc.ClassName
  427. }
  428. return ""
  429. }
  430. // 订单审核状态
  431. const (
  432. OrderUncommitted = 0 // 待提交
  433. OrderPending = 1 // 待审核
  434. OrderFirstPassed = 2 // 一审通过
  435. OrderPassed = 3 // 审核通过
  436. OrderSecondPassed = 4 // 审核通过
  437. OrderFirstReturn = -2 // 一审退回
  438. OrderSecondReturn = -3 // 二审退回
  439. OrderThreeReturn = -4 // 二审退回
  440. )
  441. // SwitchAudit 订单审核轨迹状态流转
  442. func SwitchAudit(auditStatus int) (saveAuditStatus int) {
  443. // 我的订单-编辑订单 只能编辑订单审核状态为已退回、待提交 不开通权限
  444. switch auditStatus {
  445. case OrderUncommitted:
  446. saveAuditStatus = OrderPending // 待一审
  447. case OrderFirstReturn:
  448. saveAuditStatus = OrderPending // 待一审
  449. case OrderSecondReturn:
  450. saveAuditStatus = OrderFirstPassed // 一审通过 待二审
  451. case OrderThreeReturn: //三审退回状态下,编辑订单后,审核状态是二审通过
  452. saveAuditStatus = OrderSecondPassed // 一审通过 待二审
  453. }
  454. return
  455. }