deposit.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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_voucher": sDepositPayment.PayVoucher,
  140. "pay_account_name": sDepositPayment.PayAccountName,
  141. "create_time": time.Now().Format(time.DateTime),
  142. })
  143. if err != nil {
  144. g.Log().Errorf(ctx, "新增保证金支付信息异常 %s", err.Error())
  145. return errors.Wrap(err, "新增保证金支付信息异常")
  146. } else if realPrice == price { //保证金总金额 等于剩余需要回款的总金额
  147. //todo 1、是否需要关闭对应保证金的支付订单;2、保证金支付金额=合同金额 需要开通权限
  148. //是否需要开通权限 当前订单 保证金金额 == 剩余回款金额
  149. if payMoney == gconv.Int64(value["outstandingPayment"]) {
  150. 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)) //是否选中自动开通权限
  151. if !productDetail.IsEmpty() {
  152. var (
  153. uData map[string]interface{}
  154. entId, userPositionId int64
  155. )
  156. uData, entId, userPositionId, err = jyutil.GetCreateUserData(gconv.String(value["user_phone"]), gconv.String(value["company_name"]), gconv.Int(value["buy_subject"]) == 2)
  157. if err != nil {
  158. return errors.New("用户企业信息初始化失败")
  159. }
  160. if err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  161. // 产品服务开通
  162. for _, m := range productDetail.List() {
  163. if !jyutil.IsServiceOpen(m) {
  164. continue
  165. }
  166. //参数注入
  167. m["userMap"] = map[string]interface{}{
  168. "userData": uData, "entId": entId, "userPositionId": userPositionId,
  169. }
  170. m["phone"] = value["user_phone"]
  171. m["order_code"] = key
  172. m["reqCompanyName"] = value["company_name"]
  173. m["amount"] = m["final_price"]
  174. m["reqSubject"] = value["buy_subject"]
  175. m["linked_orderId"] = m["linked_detail_id"]
  176. productCode := gconv.String(m["product_code"])
  177. pFunc, err4 := product.JyProFunc.GetProductInitFuncByCode(productCode)
  178. if err4 != nil {
  179. return err4
  180. }
  181. pObj, err5 := pFunc(m)
  182. if err5 != nil {
  183. return gerror.Wrap(err5, fmt.Sprintf("获取%s商品异常", productCode))
  184. }
  185. if err = pObj.OpenService(ctx, time.Now()); err != nil {
  186. return err
  187. }
  188. }
  189. if gconv.Int(value["buy_subject"]) == 2 {
  190. uData["userId"] = userPositionId
  191. }
  192. 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) {
  193. log.Printf("同步更新订单用户身份:orderUserId:%s,userId:%v,entId:%d\n", orderUserId, uData["userId"], entId)
  194. upData := g.Map{
  195. "user_id": uData["userId"],
  196. }
  197. if entId > 0 { //企业服务
  198. upData["ent_id"] = entId
  199. if personPhone := gconv.String(value["personPhone"]); personPhone != "" {
  200. jyutil.EndAddUser(ctx, entId, gconv.String(value["user_phone"]), personPhone, gconv.String(value["personName"]))
  201. }
  202. }
  203. //更新订单
  204. _, err = g.DB().Update(ctx, consts.OrderListTableName, upData, "order_code=?", key)
  205. }
  206. return err
  207. }); err != nil {
  208. log.Println(err)
  209. return err
  210. }
  211. }
  212. }
  213. }
  214. return err
  215. })
  216. return err
  217. }
  218. return nil
  219. }
  220. // todo 保证金支付款-退还/转回款
  221. func DepositRefundOrRetMoney(ctx context.Context, sDeposit model.SDeposit) error {
  222. //保证金信息 未删除
  223. deposits, 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)
  224. if err != nil {
  225. return err
  226. }
  227. if deposits.IsEmpty() {
  228. return fmt.Errorf("未查到当前订单 有效的保证金信息")
  229. }
  230. payMoney := FenToYuanInt64(gconv.Int64(deposits.Map()["pay_money"]))
  231. if payMoney != sDeposit.RefundMoney+sDeposit.ReturnedMoney {
  232. return fmt.Errorf("保证金金额异常")
  233. }
  234. _, err = g.DB().Insert(ctx, model.DepositOperateTable, g.Map{
  235. "order_code": sDeposit.OrderCode,
  236. "refund_money": YuanToFen(sDeposit.RefundMoney),
  237. "refund_time": sDeposit.RefundTime,
  238. "returned_money": YuanToFen(sDeposit.ReturnedMoney),
  239. "operate_time": time.Now().Format(time.DateTime),
  240. "operate_person": jyutil.GetUserMsgFromCtx(ctx).EntUserName,
  241. })
  242. //todo 如果回款金额》0,增加回款记录;如果回款金额== 剩余支付金额 需要开通权益
  243. if sDeposit.ReturnedMoney > 0 {
  244. //获取订单信息
  245. var (
  246. record gdb.Record
  247. )
  248. record, err = g.DB().GetOne(ctx, `SELECT * FROM jianyu.dataexport_order do WHERE do.order_code = ?`, sDeposit.OrderCode)
  249. if err != nil || record.IsEmpty() {
  250. g.Log().Infof(ctx, "未查到 %s 订单信息", sDeposit.OrderCode)
  251. return err
  252. }
  253. var (
  254. orderId = record.Map()["id"] //订单id
  255. payWay = deposits.Map()["pay_way"] //支付方式
  256. bankFlow = gconv.String(deposits.Map()["bank_flow"]) //银行流水号
  257. bankName = gconv.String(deposits.Map()["bank_name"]) //银行名称
  258. payVoucher = gconv.String(deposits.Map()["pay_voucher"]) //支付凭证
  259. payTime = gconv.String(deposits.Map()["pay_time"]) //支付时间
  260. payAccountName = gconv.String(deposits.Map()["pay_account_name"]) //支付户名
  261. transactionId = gconv.Int(deposits.Map()["transaction_id"]) //支付单号
  262. )
  263. var param = model.OrdersEditBatchReturn{
  264. ReturnType: 1,
  265. FlowType: 0,
  266. ReturnCode: "",
  267. TransactionId: transactionId,
  268. OrderArr: []g.Map{
  269. {
  270. "orderId": orderId,
  271. "money": sDeposit.ReturnedMoney,
  272. },
  273. },
  274. ReturnVoucherUrl: payVoucher,
  275. ReturnRemarks: "",
  276. ReturnMoney: int(sDeposit.ReturnedMoney),
  277. PayAccountName: payAccountName,
  278. BNKTIM: payTime,
  279. BNKFLW: bankFlow,
  280. BNKNAM: bankName,
  281. }
  282. err = EditBatchReturn(ctx, param)
  283. if err != nil {
  284. return errors.Wrap(err, "订单回款失败")
  285. }
  286. }
  287. return err
  288. }
  289. // todo 保证金支付信息-删除
  290. func DelDepositPayment(ctx context.Context, orderCode string) error {
  291. result, err := g.DB().Query(ctx, fmt.Sprintf(`SELECT * FROM %s odo WHERE odo.order_code = ? AND odo.is_del = 0`, model.DepositPaymentTable), orderCode)
  292. if err != nil || !result.IsEmpty() {
  293. return errors.Wrap(err, "删除保证金支付信息失败或已删除")
  294. }
  295. queryMap := map[string]interface{}{
  296. "order_code": orderCode,
  297. }
  298. updateMap := map[string]interface{}{
  299. "is_del": 1,
  300. }
  301. if _, err = g.DB().Update(ctx, model.DepositTable, queryMap, updateMap); err != nil {
  302. return gerror.Wrap(err, "删除保证金支付信息异常")
  303. }
  304. return nil
  305. }
  306. // 保证金-详情
  307. func FindDepositDetailByOrderCode(ctx context.Context, orderCode string) (res map[string]interface{}) {
  308. querySql := fmt.Sprintf(`SELECT * FROM %s od WHERE od.order_code = ? AND od.money > 0`, model.DepositTable) //保证金大于0,是有效保证金;is_del是保证金支付信息 是否删除
  309. record, err := g.DB().GetOne(ctx, querySql, orderCode)
  310. if err != nil {
  311. g.Log().Errorf(ctx, "订单 %s 保证金查询异常 %s", orderCode, err.Error())
  312. return
  313. }
  314. if record.IsEmpty() {
  315. g.Log().Errorf(ctx, "订单 %s 暂无保证金数据", orderCode)
  316. return
  317. }
  318. result := record.Map()
  319. res = map[string]interface{}{}
  320. //保证金概览
  321. overviewMap := map[string]interface{}{
  322. "money": FenToYuanInt64(gconv.Int64(result["money"])), //保证金
  323. //"payMoney": FenToYuanInt64(gconv.Int64(result["pay_money"])), //已支付金额
  324. //"refundMoney": gconv.Int(result["refund_money"]), //退还金额
  325. //"returnedMoney": gconv.Int(result["returned_money"]), //转回款金额
  326. }
  327. //保证金支付信息 已支付
  328. paymentSql := fmt.Sprintf("SELECT * FROM %s odp WHERE odp.order_code = ? AND odp.is_del = 0 ORDER BY odp.operate_time DESC ", model.DepositPaymentTable)
  329. record, err = g.DB().GetOne(ctx, paymentSql, orderCode)
  330. if err == nil && !record.IsEmpty() {
  331. result = record.Map()
  332. overviewMap["payMoney"] = FenToYuanInt64(gconv.Int64(result["pay_money"])) //已支付金额
  333. payWayStr := "第三方支付"
  334. payWay := gconv.Int(result["pay_way"]) //支付方式,1-微信 2-支付宝 3-对公转账
  335. switch payWay {
  336. case 1:
  337. payWayStr = "微信"
  338. case 2:
  339. payWayStr = "支付宝"
  340. case 3:
  341. payWayStr = "对公转账"
  342. }
  343. res["payment"] = map[string]interface{}{
  344. "payTime": gconv.String(result["pay_time"]), //保证金支付时间
  345. "payMoney": FenToYuanInt64(gconv.Int64(result["pay_money"])), //已支付金额
  346. "payWay": payWayStr, //支付方式
  347. "proceduresMoney": FenToYuanInt64(gconv.Int64(result["procedures_money"])), //手续费
  348. "bankName": gconv.String(result["bank_name"]), //银行
  349. "bankFlow": gconv.String(result["bank_flow"]), //银行流水号
  350. "payAccountName": gconv.String(result["pay_account_name"]), //支付户名
  351. "flowMoney": FenToYuanInt64(gconv.Int64(result["flow_money"])), //流水金额
  352. "payVoucher": gconv.String(result["pay_voucher"]), //支付凭证
  353. "operateTime": gconv.String(result["operate_time"]), //操作时间
  354. "operatePerson": gconv.String(result["operate_person"]), //操作人
  355. }
  356. //保证金退还/转回款信息记录
  357. var (
  358. operateRS gdb.Result
  359. )
  360. 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)
  361. if err != nil || operateRS.IsEmpty() {
  362. g.Log().Info(ctx, "未查到保证金退还/转回款信息记录")
  363. } else {
  364. var (
  365. refundMoney, returnedMoney int64
  366. operates []map[string]interface{}
  367. )
  368. for _, v := range operateRS.List() {
  369. refundMoney = refundMoney + gconv.Int64(v["refund_money"])
  370. returnedMoney = returnedMoney + gconv.Int64(v["returned_money"])
  371. operates = append(operates, map[string]interface{}{
  372. "refundTime": gconv.String(v["refund_time"]), //退还时间
  373. "refundMoney": FenToYuanInt64(gconv.Int64(v["refund_money"])), //退还金额
  374. "returnedMoney": FenToYuanInt64(gconv.Int64(v["returned_money"])), //转回款金额
  375. "operateTime": gconv.String(v["operate_time"]), //操作时间
  376. })
  377. }
  378. overviewMap["refundMoney"] = FenToYuanInt64(refundMoney)
  379. overviewMap["returnedMoney"] = FenToYuanInt64(returnedMoney)
  380. res["operates"] = operates
  381. }
  382. }
  383. res["overview"] = overviewMap
  384. return
  385. }
  386. // 分转元 int64
  387. func FenToYuanInt64(fen int64) int64 {
  388. return fen / 100
  389. }
  390. // 分转元字符串
  391. func FenToYuanString(fen int64) string {
  392. return fmt.Sprintf("%d", fen/100)
  393. }
  394. // 元转分
  395. func YuanToFen(yuan int64) int64 {
  396. return yuan * 100
  397. }
  398. // HasDepositOperate 查询是否有保证金操作记录
  399. func HasDepositOperate(ctx context.Context, orderCode string) (bool, error) {
  400. count, err := g.DB().GetCount(ctx, "SELECT * FROM order_deposit_operate WHERE order_code=?", orderCode)
  401. if err != nil {
  402. log.Println("查询是否有保证金操作异常:", err, orderCode)
  403. return false, err
  404. }
  405. return count > 0, nil
  406. }
  407. // GetDepositPayMoney 获取保证金已支付金额
  408. func GetDepositPayMoney(ctx context.Context, orderCode string) (int64, error) {
  409. data, err := g.DB().Query(ctx, "SELECT pay_money FROM order_deposit WHERE order_code=? and state=1 and is_del=0 ", orderCode)
  410. if err != nil {
  411. log.Println("获取保证金已支付金额异常:", err, orderCode)
  412. return 0, err
  413. }
  414. if data.Len() == 0 {
  415. return 0, nil
  416. }
  417. dataMap := data[0].Map()
  418. return common.Int64All(dataMap["pay_money"]), nil
  419. }