deposit.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package order
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "context"
  5. "fmt"
  6. "github.com/gogf/gf/v2/database/gdb"
  7. "github.com/gogf/gf/v2/errors/gerror"
  8. "github.com/gogf/gf/v2/frame/g"
  9. "github.com/gogf/gf/v2/util/gconv"
  10. "github.com/pkg/errors"
  11. "jyOrderManager/internal/consts"
  12. "jyOrderManager/internal/jyutil"
  13. "jyOrderManager/internal/logic/product"
  14. "jyOrderManager/internal/model"
  15. "log"
  16. "math"
  17. "time"
  18. )
  19. // todo 保证金--新增
  20. func SaveDepositInfo(ctx context.Context, orderCode, userName, dPaymentAccount string, money int64) error {
  21. timeStr := time.Now().Format("2006-01-02 15:04:05")
  22. if _, err := g.DB().Ctx(ctx).Insert(ctx, model.DepositTable, g.Map{
  23. "order_code": orderCode,
  24. "money": money,
  25. "payment_account": dPaymentAccount,
  26. "operate_time": timeStr,
  27. "operate_person": userName,
  28. "create_time": timeStr,
  29. }); err != nil {
  30. return gerror.Wrap(err, "保证金保存异常")
  31. }
  32. return nil
  33. }
  34. // todo 保证金编辑(可以新增
  35. func EditDeposit(ctx context.Context, sDeposit model.SDeposit) error {
  36. result, err := g.DB().Query(ctx, fmt.Sprintf(`SELECT * FROM %s odo WHERE odo.order_code = ? ORDER BY odo.operate_time DESC`, model.DepositTable), sDeposit.OrderCode)
  37. if err != nil {
  38. return errors.Wrap(err, "查询保证金信息异常")
  39. }
  40. if result.IsEmpty() {
  41. if sDeposit.DepositAmount > 0 {
  42. //存储
  43. err = SaveDepositInfo(ctx, sDeposit.OrderCode, jyutil.GetUserMsgFromCtx(ctx).EntUserName, sDeposit.DepositPaymentAccount, sDeposit.DepositAmount)
  44. } else {
  45. err = fmt.Errorf("保证金参数异常")
  46. }
  47. } else {
  48. //更新 todo 有保证金支付信息不鞥编辑更新
  49. var dpCount int
  50. dpCount, err = g.DB().GetCount(ctx, fmt.Sprintf(`SELECT count(*) FROM %s od WHERE od.order_code = ? AND od.pay_money > 0 AND od.is_del = 0 ORDER BY od.operate_time DESC ;`, model.DepositPaymentTable), sDeposit.OrderCode)
  51. if dpCount > 0 || err != nil {
  52. return errors.Wrap(err, "保证金编辑失败")
  53. }
  54. _, err = g.DB().Update(ctx, model.DepositTable, g.Map{
  55. "order_code": sDeposit.OrderCode,
  56. }, g.Map{
  57. "money": sDeposit.DepositAmount,
  58. "payment_account": sDeposit.DepositPaymentAccount,
  59. "operate_time": time.Now().Format(time.DateTime),
  60. "operate_person": jyutil.GetUserMsgFromCtx(ctx).EntUserName,
  61. })
  62. }
  63. return err
  64. }
  65. // todo 保证金-支付信息(批量|单条)
  66. func SaveDepositPayment(ctx context.Context, sDepositPayment model.SDepositPayment) error {
  67. var payWay string
  68. switch sDepositPayment.PayWay {
  69. case 1:
  70. payWay = "微信"
  71. case 2:
  72. payWay = "支付宝"
  73. case 3:
  74. payWay = "对公转账"
  75. case 4:
  76. payWay = "第三方平台"
  77. }
  78. if payWay == "" {
  79. return fmt.Errorf("pay_way 参数异常")
  80. }
  81. var (
  82. price, realPrice int64
  83. orderArr = make(map[string]map[string]interface{})
  84. )
  85. for _, dl := range sDepositPayment.DepositList {
  86. if dl.OrderCode == "" || dl.Money == 0 {
  87. continue
  88. }
  89. orderData, _ := g.DB().Ctx(ctx).GetOne(ctx, "select ((IFNULL(CASE WHEN a.is_backstage_order = 1 THEN a.pay_money ELSE a.order_money END, 0)) -IFNULL(a.procedures_money,0))-(select IFNULL(sum(b.return_money),0) from return_money_record b where b.order_code=a.order_code and b.state=1) + (select IFNULL(sum(c.refund_money),0) from refund_record c where c.order_code=a.order_code)+(select IFNULL(sum(payMoney),0) as return_money from moneyCorrection c where c.orderCode=a.order_code) as outstandingPayment, a.* from dataexport_order a where a.order_code=?", dl.OrderCode)
  90. if orderData.IsEmpty() {
  91. g.Log().Infof(ctx, "未查到%s当前订单回款信息", dl.OrderCode)
  92. continue
  93. }
  94. orderDataMap := orderData.Map()
  95. if dl.Money > gconv.Int64(orderDataMap["outstandingPayment"]) { //合同金额
  96. g.Log().Infof(ctx, errors.New(dl.OrderCode+"保证金金额过大").Error())
  97. return errors.New(dl.OrderCode + "保证金金额过大")
  98. }
  99. orderDataMap["realPrice"] = dl.Money //保证金
  100. orderDataMap["returnVoucherUrl"] = sDepositPayment.PayVoucher
  101. realPrice += dl.Money
  102. orderArr[dl.OrderCode] = orderDataMap
  103. price += gconv.Int64(orderDataMap["outstandingPayment"]) //剩余回款?
  104. }
  105. //cbs回款流水
  106. //查询回款流水记录
  107. if sDepositPayment.FlowType == 0 {
  108. transactionData, _ := g.DB("cbs").Ctx(ctx).GetOne(ctx, fmt.Sprintf(`SELECT return_id,BNKNAM,BNKFLW,id,ACTNBR,TRSBAL,BNKTIM,OTHNAM,NUSAGE FROM transaction WHERE id = %d`, sDepositPayment.TransactionId))
  109. if transactionData.IsEmpty() {
  110. return errors.New("未找到该流水")
  111. }
  112. money := int64(math.Floor(gconv.Float64(transactionData.Map()["TRSBAL"]))*100 + 0.5) //流水
  113. log.Println("CBS流水金额:", money, "回款总金额:", price, "保证金总金额:", realPrice)
  114. if money != realPrice {
  115. return errors.New("新增保证金失败,保证金金额不符合")
  116. }
  117. } else {
  118. if sDepositPayment.FlowMoney != realPrice {
  119. return errors.New("新增保证金失败,保证金金额不符合")
  120. }
  121. }
  122. for key, value := range orderArr {
  123. var (
  124. payMoney = gconv.Int64(value["realPrice"])
  125. )
  126. err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  127. _, err := g.DB().Insert(ctx, model.DepositPaymentTable, g.Map{ //保证金支付信息
  128. "order_code": key,
  129. "pay_time": sDepositPayment.PayTime,
  130. "pay_money": YuanToFen(payMoney),
  131. "pay_way": payWay,
  132. "remark": sDepositPayment.Remark,
  133. "state": 1,
  134. "operate_time": time.Now().Format(time.DateTime),
  135. "operate_person": jyutil.GetUserMsgFromCtx(ctx).EntUserName,
  136. "flow_money": YuanToFen(sDepositPayment.FlowMoney),
  137. "bank_name": sDepositPayment.BankName,
  138. "bank_flow": sDepositPayment.BankFlow,
  139. "pay_code": sDepositPayment.PayCode,
  140. "transaction_id": sDepositPayment.TransactionId,
  141. "pay_voucher": sDepositPayment.PayVoucher,
  142. "pay_account_name": sDepositPayment.PayAccountName,
  143. "create_time": time.Now().Format(time.DateTime),
  144. })
  145. if err != nil {
  146. g.Log().Errorf(ctx, "新增保证金支付信息异常 %s", err.Error())
  147. return errors.Wrap(err, "新增保证金支付信息异常")
  148. } else if realPrice == price { //保证金总金额 等于剩余需要回款的总金额
  149. //todo 1、是否需要关闭对应保证金的支付订单;2、保证金支付金额=合同金额 需要开通权限
  150. //是否需要开通权限 当前订单 保证金金额 == 剩余回款金额
  151. if payMoney == gconv.Int64(value["outstandingPayment"]) {
  152. productDetail, _ := 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`, key)) //是否选中自动开通权限
  153. if !productDetail.IsEmpty() {
  154. var (
  155. uData map[string]interface{}
  156. entId, userPositionId int64
  157. )
  158. uData, entId, userPositionId, err = jyutil.GetCreateUserData(gconv.String(value["user_phone"]), gconv.String(value["company_name"]), gconv.Int(value["buy_subject"]) == 2)
  159. if err != nil {
  160. return errors.New("用户企业信息初始化失败")
  161. }
  162. if err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  163. // 产品服务开通
  164. for _, m := range productDetail.List() {
  165. if !jyutil.IsServiceOpen(m) {
  166. continue
  167. }
  168. //参数注入
  169. m["userMap"] = map[string]interface{}{
  170. "userData": uData, "entId": entId, "userPositionId": userPositionId,
  171. }
  172. m["phone"] = value["user_phone"]
  173. m["order_code"] = key
  174. m["reqCompanyName"] = value["company_name"]
  175. m["amount"] = m["final_price"]
  176. m["reqSubject"] = value["buy_subject"]
  177. m["linked_orderId"] = m["linked_detail_id"]
  178. productCode := gconv.String(m["product_code"])
  179. pFunc, err4 := product.JyProFunc.GetProductInitFuncByCode(productCode)
  180. if err4 != nil {
  181. return err4
  182. }
  183. pObj, err5 := pFunc(m)
  184. if err5 != nil {
  185. return gerror.Wrap(err5, fmt.Sprintf("获取%s商品异常", productCode))
  186. }
  187. if err = pObj.OpenService(ctx, time.Now()); err != nil {
  188. return err
  189. }
  190. }
  191. if gconv.Int(value["buy_subject"]) == 2 {
  192. uData["userId"] = userPositionId
  193. }
  194. if orderUserId := gconv.String(value["user_id"]); orderUserId == "" || orderUserId != gconv.String(uData["userId"]) || (gconv.Int(value["buy_subject"]) == 2 && gconv.Int64(value["ent_id"]) != entId) {
  195. log.Printf("同步更新订单用户身份:orderUserId:%s,userId:%v,entId:%d\n", orderUserId, uData["userId"], entId)
  196. upData := g.Map{
  197. "user_id": uData["userId"],
  198. }
  199. if entId > 0 { //企业服务
  200. upData["ent_id"] = entId
  201. if personPhone := gconv.String(value["personPhone"]); personPhone != "" {
  202. jyutil.EndAddUser(ctx, entId, gconv.String(value["user_phone"]), personPhone, gconv.String(value["personName"]))
  203. }
  204. }
  205. //更新订单
  206. _, err = g.DB().Update(ctx, consts.OrderListTableName, upData, "order_code=?", key)
  207. }
  208. return err
  209. }); err != nil {
  210. log.Println(err)
  211. return err
  212. }
  213. }
  214. }
  215. }
  216. return err
  217. })
  218. return err
  219. }
  220. return nil
  221. }
  222. // todo 保证金支付款-退还/转回款
  223. func DepositRefundOrRetMoney(ctx context.Context, sDeposit model.SDeposit) error {
  224. //保证金支付信息 未删除
  225. depositPayment, err := g.DB().GetOne(ctx, fmt.Sprintf(`SELECT * FROM %s od WHERE od.order_code = ? AND od.pay_money > 0 AND od.is_del = 0 ORDER BY od.operate_time DESC ;`, model.DepositPaymentTable), sDeposit.OrderCode)
  226. if err != nil {
  227. return err
  228. }
  229. if depositPayment.IsEmpty() {
  230. return fmt.Errorf("未查到当前订单 有效的保证金信息")
  231. }
  232. payMoney := FenToYuanInt64(gconv.Int64(depositPayment.Map()["pay_money"]))
  233. if payMoney != sDeposit.RefundMoney+sDeposit.ReturnedMoney {
  234. return fmt.Errorf("保证金金额异常")
  235. }
  236. _, err = g.DB().Insert(ctx, model.DepositOperateTable, g.Map{
  237. "order_code": sDeposit.OrderCode,
  238. "refund_money": YuanToFen(sDeposit.RefundMoney),
  239. "refund_time": sDeposit.RefundTime,
  240. "returned_money": YuanToFen(sDeposit.ReturnedMoney),
  241. "operate_time": time.Now().Format(time.DateTime),
  242. "operate_person": jyutil.GetUserMsgFromCtx(ctx).EntUserName,
  243. })
  244. //todo 如果回款金额》0,增加回款记录;如果回款金额== 剩余支付金额 需要开通权益
  245. if sDeposit.ReturnedMoney > 0 {
  246. //获取订单信息
  247. var (
  248. record gdb.Record
  249. )
  250. record, err = g.DB().GetOne(ctx, `SELECT * FROM jianyu.dataexport_order do WHERE do.order_code = ?`, sDeposit.OrderCode)
  251. if err != nil || record.IsEmpty() {
  252. g.Log().Infof(ctx, "未查到 %s 订单信息", sDeposit.OrderCode)
  253. return err
  254. }
  255. var (
  256. orderId = record.Map()["id"] //订单id
  257. payWay = gconv.Int(depositPayment.Map()["pay_way"]) //支付方式,1-微信 2-支付宝 3-对公转账
  258. bankFlow = gconv.String(depositPayment.Map()["bank_flow"]) //对公转账 银行流水号,手动录入
  259. bankName = gconv.String(depositPayment.Map()["bank_name"]) //银行名称
  260. payVoucher = gconv.String(depositPayment.Map()["pay_voucher"]) //支付凭证
  261. payTime = gconv.String(depositPayment.Map()["pay_time"]) //支付时间
  262. payAccountName = gconv.String(depositPayment.Map()["pay_account_name"]) //支付户名
  263. payCode = gconv.String(depositPayment.Map()["pay_code"]) //支付宝、微信、第三方平台 支付单号
  264. transactionId = gconv.Int(depositPayment.Map()["transaction_id"]) //对公转账银行流水号 cbs 自动录入
  265. )
  266. var param = model.OrdersEditBatchReturn{
  267. ReturnType: payWay,
  268. FlowType: 0, //保证金转回款,即使保证金是CBS回款,转回款不走CBS逻辑
  269. ReturnCode: payCode,
  270. TransactionId: transactionId,
  271. OrderArr: []g.Map{
  272. {
  273. "orderId": orderId,
  274. "money": sDeposit.ReturnedMoney,
  275. },
  276. },
  277. ReturnVoucherUrl: payVoucher,
  278. ReturnRemarks: "",
  279. ReturnMoney: int(sDeposit.ReturnedMoney),
  280. PayAccountName: payAccountName,
  281. BNKTIM: payTime,
  282. BNKFLW: bankFlow,
  283. BNKNAM: bankName,
  284. }
  285. err = EditBatchReturn(ctx, param)
  286. if err != nil {
  287. return errors.Wrap(err, "订单回款失败")
  288. }
  289. }
  290. return err
  291. }
  292. // todo 保证金支付信息-删除
  293. func DelDepositPayment(ctx context.Context, orderCode string) error {
  294. result, err := g.DB().Query(ctx, fmt.Sprintf(`SELECT * FROM %s odo WHERE odo.order_code = ? AND odo.is_del = 0`, model.DepositPaymentTable), orderCode)
  295. if err != nil || !result.IsEmpty() {
  296. return errors.Wrap(err, "删除保证金支付信息失败或已删除")
  297. }
  298. queryMap := map[string]interface{}{
  299. "order_code": orderCode,
  300. }
  301. updateMap := map[string]interface{}{
  302. "is_del": 1,
  303. }
  304. if _, err = g.DB().Update(ctx, model.DepositTable, queryMap, updateMap); err != nil {
  305. return gerror.Wrap(err, "删除保证金支付信息异常")
  306. }
  307. return nil
  308. }
  309. // 保证金-详情
  310. func FindDepositDetailByOrderCode(ctx context.Context, orderCode string) (res map[string]interface{}) {
  311. querySql := fmt.Sprintf(`SELECT * FROM %s od WHERE od.order_code = ? AND od.money > 0`, model.DepositTable) //保证金大于0,是有效保证金;is_del是保证金支付信息 是否删除
  312. record, err := g.DB().GetOne(ctx, querySql, orderCode)
  313. if err != nil {
  314. g.Log().Errorf(ctx, "订单 %s 保证金查询异常 %s", orderCode, err.Error())
  315. return
  316. }
  317. if record.IsEmpty() {
  318. g.Log().Errorf(ctx, "订单 %s 暂无保证金数据", orderCode)
  319. return
  320. }
  321. result := record.Map()
  322. res = map[string]interface{}{}
  323. //保证金概览
  324. overviewMap := map[string]interface{}{
  325. "money": FenToYuanInt64(gconv.Int64(result["money"])), //保证金
  326. //"payMoney": FenToYuanInt64(gconv.Int64(result["pay_money"])), //已支付金额
  327. //"refundMoney": gconv.Int(result["refund_money"]), //退还金额
  328. //"returnedMoney": gconv.Int(result["returned_money"]), //转回款金额
  329. }
  330. //保证金支付信息 已支付
  331. paymentSql := fmt.Sprintf("SELECT * FROM %s odp WHERE odp.order_code = ? AND odp.is_del = 0 ORDER BY odp.operate_time DESC ", model.DepositPaymentTable)
  332. record, err = g.DB().GetOne(ctx, paymentSql, orderCode)
  333. if err == nil && !record.IsEmpty() {
  334. result = record.Map()
  335. overviewMap["payMoney"] = FenToYuanInt64(gconv.Int64(result["pay_money"])) //已支付金额
  336. payWayStr := "第三方支付"
  337. payWay := gconv.Int(result["pay_way"]) //支付方式,1-微信 2-支付宝 3-对公转账
  338. switch payWay {
  339. case 1:
  340. payWayStr = "微信"
  341. case 2:
  342. payWayStr = "支付宝"
  343. case 3:
  344. payWayStr = "对公转账"
  345. }
  346. res["payment"] = map[string]interface{}{
  347. "payTime": gconv.String(result["pay_time"]), //保证金支付时间
  348. "payMoney": FenToYuanInt64(gconv.Int64(result["pay_money"])), //已支付金额
  349. "payWay": payWayStr, //支付方式
  350. "proceduresMoney": FenToYuanInt64(gconv.Int64(result["procedures_money"])), //手续费
  351. "bankName": gconv.String(result["bank_name"]), //银行
  352. "bankFlow": gconv.String(result["bank_flow"]), //银行流水号
  353. "payAccountName": gconv.String(result["pay_account_name"]), //支付户名
  354. "flowMoney": FenToYuanInt64(gconv.Int64(result["flow_money"])), //流水金额
  355. "payVoucher": gconv.String(result["pay_voucher"]), //支付凭证
  356. "operateTime": gconv.String(result["operate_time"]), //操作时间
  357. "operatePerson": gconv.String(result["operate_person"]), //操作人
  358. }
  359. //保证金退还/转回款信息记录
  360. var (
  361. operateRS gdb.Result
  362. )
  363. operateRS, err = g.DB().Query(ctx, fmt.Sprintf(`SELECT * FROM %s odo WHERE odo.order_code = ? ORDER BY odo.operate_time DESC `, model.DepositOperateTable), orderCode)
  364. if err != nil || operateRS.IsEmpty() {
  365. g.Log().Info(ctx, "未查到保证金退还/转回款信息记录")
  366. } else {
  367. var (
  368. refundMoney, returnedMoney int64
  369. operates []map[string]interface{}
  370. )
  371. for _, v := range operateRS.List() {
  372. refundMoney = refundMoney + gconv.Int64(v["refund_money"])
  373. returnedMoney = returnedMoney + gconv.Int64(v["returned_money"])
  374. operates = append(operates, map[string]interface{}{
  375. "refundTime": gconv.String(v["refund_time"]), //退还时间
  376. "refundMoney": FenToYuanInt64(gconv.Int64(v["refund_money"])), //退还金额
  377. "returnedMoney": FenToYuanInt64(gconv.Int64(v["returned_money"])), //转回款金额
  378. "operateTime": gconv.String(v["operate_time"]), //操作时间
  379. })
  380. }
  381. overviewMap["refundMoney"] = FenToYuanInt64(refundMoney)
  382. overviewMap["returnedMoney"] = FenToYuanInt64(returnedMoney)
  383. res["operates"] = operates
  384. }
  385. }
  386. res["overview"] = overviewMap
  387. return
  388. }
  389. // 分转元 int64
  390. func FenToYuanInt64(fen int64) int64 {
  391. return fen / 100
  392. }
  393. // 分转元字符串
  394. func FenToYuanString(fen int64) string {
  395. return fmt.Sprintf("%d", fen/100)
  396. }
  397. // 元转分
  398. func YuanToFen(yuan int64) int64 {
  399. return yuan * 100
  400. }
  401. // HasDepositOperate 查询是否有保证金操作记录
  402. func HasDepositOperate(ctx context.Context, orderCode string) (bool, error) {
  403. count, err := g.DB().GetCount(ctx, "SELECT * FROM order_deposit_operate WHERE order_code=?", orderCode)
  404. if err != nil {
  405. log.Println("查询是否有保证金操作异常:", err, orderCode)
  406. return false, err
  407. }
  408. return count > 0, nil
  409. }
  410. // GetDepositPayMoney 获取保证金已支付金额
  411. func GetDepositPayMoney(ctx context.Context, orderCode string) (int64, error) {
  412. data, err := g.DB().Query(ctx, "SELECT pay_money FROM order_deposit_payment WHERE order_code=? and is_del=0 ", orderCode)
  413. if err != nil {
  414. log.Println("获取保证金已支付金额异常:", err, orderCode)
  415. return 0, err
  416. }
  417. if data.Len() == 0 {
  418. return 0, nil
  419. }
  420. dataMap := data[0].Map()
  421. return common.Int64All(dataMap["pay_money"]), nil
  422. }
  423. // GetDepositMoney 获取保证金金额
  424. func GetDepositMoney(ctx context.Context, orderCode string) (int64, error) {
  425. data, err := g.DB().Query(ctx, "SELECT money FROM order_deposit WHERE order_code=?", orderCode)
  426. if err != nil {
  427. log.Println("获取保证金已支付金额异常:", err, orderCode)
  428. return 0, err
  429. }
  430. if data.Len() == 0 {
  431. return 0, nil
  432. }
  433. dataMap := data[0].Map()
  434. return common.Int64All(dataMap["pay_money"]), nil
  435. }