orderHandler.go 15 KB

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