order.go 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. package controllers
  2. import (
  3. "encoding/json"
  4. "eta/eta_mini_crm_ht/models"
  5. "eta/eta_mini_crm_ht/models/request"
  6. "eta/eta_mini_crm_ht/models/response"
  7. "eta/eta_mini_crm_ht/utils"
  8. "fmt"
  9. "github.com/rdlucklib/rdluck_tools/paging"
  10. "github.com/xuri/excelize/v2"
  11. "math/rand"
  12. "net/http"
  13. "net/url"
  14. "strconv"
  15. "sync"
  16. "time"
  17. )
  18. var (
  19. productCols = map[string]utils.ExcelColMapping{
  20. "A": {"订单编号", "OrderID"},
  21. "B": {"姓名", "RealName"},
  22. "C": {"手机号", "Mobile"},
  23. "D": {"商品名称", "ProductName"},
  24. "E": {"商品类型", "ProductType"},
  25. "F": {"商品价格", "Price"},
  26. "G": {"有效期", "ValidDate"},
  27. "H": {"订单状态", "Status"},
  28. "I": {"支付渠道", "PaymentWay"},
  29. "J": {"支付金额", "TotalAmount"},
  30. "K": {"售后状态", "RefundStatus"},
  31. "L": {"付款时间", "PaymentTime"},
  32. "M": {"下单时间", "CreatedTime"},
  33. }
  34. tradeCols = map[string]utils.ExcelColMapping{
  35. "A": {"支付订单", "TransactionId"},
  36. "B": {"订单编号", "OrderID"},
  37. "C": {"姓名", "RealName"},
  38. "D": {"手机号", "Mobile"},
  39. "E": {"商品名称", "ProductName"},
  40. "F": {"支付金额", "Amount"},
  41. "G": {"支付状态", "PaymentStatus"},
  42. "H": {"支付渠道", "PaymentWay"},
  43. "I": {"支付账号", "PaymentAccount"},
  44. "J": {"收款方", "MerchantId"},
  45. "K": {"完成支付时间", "DealTime"},
  46. "L": {"创建时间", "CreatedTime"},
  47. }
  48. refundCols = map[string]utils.ExcelColMapping{
  49. "A": {"退款订单", "TransactionId"},
  50. "B": {"订单编号", "OrderID"},
  51. "C": {"姓名", "RealName"},
  52. "D": {"手机号", "Mobile"},
  53. "E": {"退款金额", "Amount"},
  54. "F": {"退回账号", "PaymentAccount"},
  55. "G": {"退款状态", "PaymentStatus"},
  56. "H": {"完成退款时间", "DealTime"},
  57. "I": {"创建时间", "CreatedTime"},
  58. }
  59. ProductOrderStatus = map[models.OrderStatus]string{
  60. "pending": "待支付",
  61. "processing": "支付中",
  62. "paid": "已支付",
  63. "closed": "已关闭",
  64. "refund": "售后",
  65. }
  66. TradeOrderStatus = map[models.PaymentStatus]string{
  67. "pending": "待支付",
  68. "failed": "支付失败",
  69. "done": "支付成功",
  70. }
  71. RefundOrderStatus = map[models.PaymentStatus]string{
  72. "pending": "退款中",
  73. "failed": "退款失败",
  74. "done": "退款成功",
  75. }
  76. RefundStatusMap = map[models.RefundStatus]string{
  77. "pending": "待退款",
  78. "processing": "退款中",
  79. "failed": "退款失败",
  80. "success": "退款成功",
  81. "canceled": "已取消",
  82. }
  83. ProductTypeMap = map[models.MerchantProductType]string{
  84. "report": "报告",
  85. "video": "视频",
  86. "audio": "音频",
  87. "package": "套餐",
  88. }
  89. PaymentWayMap = map[models.PaymentWay]string{
  90. "wechat": "微信",
  91. "alipay": "支付宝",
  92. }
  93. )
  94. type OrderController struct {
  95. BaseAuthController
  96. }
  97. // ProductOrderList
  98. // @Title 商品订单列表
  99. // @Description 商品订单列表
  100. // @Param PageSize query int true "每页数据条数"
  101. // @Param CurrentIndex query int true "当前页页码,从1开始"
  102. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  103. // @Param KeyWord query string true "报告标题/创建人"
  104. // @Param SortType query string true "排序方式"
  105. // @Success 200 {object} models.ReportAuthorResp
  106. // @router /productOrderList [get]
  107. func (this *OrderController) ProductOrderList() {
  108. br := new(models.BaseResponse).Init()
  109. defer func() {
  110. this.Data["json"] = br
  111. this.ServeJSON()
  112. }()
  113. pageSize, _ := this.GetInt("PageSize")
  114. currentIndex, _ := this.GetInt("CurrentIndex")
  115. sortType := this.GetString("SortType")
  116. KeyWord := this.GetString("KeyWord")
  117. PaymentDate := this.GetString("PaymentDate")
  118. PaymentWay := this.GetString("PaymentWay")
  119. CreatedDate := this.GetString("CreatedDate")
  120. ProductType := this.GetString("ProductType")
  121. RefundStatus := this.GetString("RefundStatus")
  122. OrderStatus := this.GetString("OrderStatus")
  123. var condition string
  124. if pageSize <= 0 {
  125. pageSize = utils.PageSize20
  126. }
  127. if currentIndex <= 0 {
  128. currentIndex = 1
  129. }
  130. if KeyWord != "" {
  131. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%'or order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  132. }
  133. sortCondition := " ORDER BY created_time "
  134. if sortType == "" {
  135. sortType = "DESC"
  136. }
  137. if CreatedDate != "" {
  138. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  139. }
  140. if PaymentDate != "" {
  141. condition += " AND Date(payment_time) = '" + PaymentDate + "'"
  142. }
  143. if PaymentWay != "" {
  144. condition += " AND payment_way='" + PaymentWay + "'"
  145. }
  146. if OrderStatus != "" {
  147. switch OrderStatus {
  148. case "pending":
  149. condition += " AND status='pending'"
  150. case "paid":
  151. condition += " AND status='paid'"
  152. case "closed":
  153. condition += " AND status='closed'"
  154. case "refund":
  155. condition += " AND status='refund'"
  156. if RefundStatus != "" {
  157. switch RefundStatus {
  158. case "pending":
  159. condition += " AND refund_status='pending'"
  160. case "processing":
  161. condition += " AND refund_status='processing'"
  162. case "failed":
  163. condition += " AND refund_status='failed'"
  164. case "success":
  165. condition += " AND refund_status='success'"
  166. }
  167. }
  168. default:
  169. br.Msg = "无效的订单状态"
  170. br.ErrMsg = "无效的订单状态:" + OrderStatus
  171. return
  172. }
  173. }
  174. if ProductType != "" {
  175. switch ProductType {
  176. case "report":
  177. condition += " AND product_type='" + string(models.ProductReport) + "'"
  178. case "audio":
  179. condition += " AND product_type='" + string(models.ProductAudio) + "'"
  180. case "video":
  181. condition += " AND product_type='" + string(models.ProductVideo) + "'"
  182. case "package":
  183. condition += " AND product_type='" + string(models.ProductPackage) + "'"
  184. default:
  185. br.Msg = "无效的产品类型"
  186. br.ErrMsg = "无效的产品类型:" + ProductType
  187. return
  188. }
  189. }
  190. sortCondition = sortCondition + sortType
  191. total, err := models.GetProductOrderCountByCondition(condition)
  192. if err != nil {
  193. br.Msg = "获取商品列表失败"
  194. br.ErrMsg = "获取商品列表失败,Err:" + err.Error()
  195. return
  196. }
  197. startSize := utils.StartIndex(currentIndex, pageSize)
  198. List, err := models.GetProductOrderByCondition(condition, sortCondition, startSize, pageSize)
  199. if err != nil {
  200. br.Msg = "获取商品列表失败"
  201. br.ErrMsg = "获取商品列表失败,Err:" + err.Error()
  202. return
  203. }
  204. var ListView []*models.ProductOrderView
  205. var wg sync.WaitGroup
  206. wg.Add(len(List))
  207. for _, orderItem := range List {
  208. go func(orderItem *models.ProductOrder) {
  209. defer wg.Done()
  210. view := &models.ProductOrderView{
  211. OrderID: orderItem.OrderID,
  212. RealName: orderItem.RealName,
  213. Mobile: fmt.Sprintf("+%s %s", orderItem.AreaCode, orderItem.Mobile),
  214. ProductType: ProductTypeMap[orderItem.ProductType],
  215. ProductName: orderItem.ProductName,
  216. TotalAmount: orderItem.TotalAmount,
  217. TradeNO: orderItem.TradeNO,
  218. RefundAmount: orderItem.RefundAmount,
  219. RefundTradeId: orderItem.RefundTradeId,
  220. PaymentWay: PaymentWayMap[orderItem.PaymentWay],
  221. PaymentAmount: orderItem.PaymentAmount,
  222. Status: ProductOrderStatus[orderItem.Status],
  223. RefundStatus: RefundStatusMap[orderItem.RefundStatus],
  224. Remark: orderItem.Remark,
  225. CreatedTime: orderItem.CreatedTime.Format(time.DateTime),
  226. }
  227. if orderItem.TradeNO != "" {
  228. view.PaymentTime = orderItem.PaymentTime.Format(time.DateTime)
  229. tradeOrder, tradeErr := models.GetTradeOrderByNo(orderItem.TradeNO)
  230. if tradeErr != nil {
  231. utils.FileLog.Error("获取支付订单失败,支付订单号:" + orderItem.TradeNO + ",err:" + tradeErr.Error())
  232. } else {
  233. view.PaymentAmount = fmt.Sprintf("%s %.2f", tradeOrder.Currency, tradeOrder.Amount)
  234. }
  235. }
  236. if orderItem.Status == models.OrderStatusPaid {
  237. access, accessErr := models.GetAccess(orderItem.ProductID, orderItem.TemplateUserID)
  238. if accessErr != nil {
  239. utils.FileLog.Error("获取用户订阅记录失败,templateUserId:" + string(rune(orderItem.TemplateUserID)) + "productId:" + string(rune(orderItem.ProductID)) + ",err:" + accessErr.Error())
  240. } else {
  241. if access.ProductType == models.ProductPackage {
  242. view.ValidDuration = fmt.Sprintf("%s~%s", access.BeginDate.Format(time.DateOnly), access.EndDate.Format(time.DateOnly))
  243. } else {
  244. view.ValidDuration = "永久有效"
  245. }
  246. }
  247. }
  248. if orderItem.Status == models.OrderStatusRefund && orderItem.RefundStatus == models.RefundStatusSuccess {
  249. view.RefundFinishTime = orderItem.RefundFinishTime.Format(time.DateTime)
  250. }
  251. ListView = append(ListView, view)
  252. }(orderItem)
  253. }
  254. wg.Wait()
  255. page := paging.GetPaging(currentIndex, pageSize, total)
  256. resp := new(response.ProductOrderListResp)
  257. resp.List = ListView
  258. resp.Paging = page
  259. br.Ret = 200
  260. br.Success = true
  261. br.Data = resp
  262. br.Msg = "获取成功"
  263. }
  264. // TradeOrderList
  265. // @Title 支付订单列表
  266. // @Description 支付订单列表
  267. // @Param PageSize query int true "每页数据条数"
  268. // @Param CurrentIndex query int true "当前页页码,从1开始"
  269. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  270. // @Param KeyWord query string true "报告标题/创建人"
  271. // @Param SortType query string true "排序方式"
  272. // @Success 200 {object} models.ReportAuthorResp
  273. // @router /tradeOrderList [get]
  274. func (this *OrderController) TradeOrderList() {
  275. br := new(models.BaseResponse).Init()
  276. defer func() {
  277. this.Data["json"] = br
  278. this.ServeJSON()
  279. }()
  280. pageSize, _ := this.GetInt("PageSize")
  281. currentIndex, _ := this.GetInt("CurrentIndex")
  282. sortType := this.GetString("SortType")
  283. KeyWord := this.GetString("KeyWord")
  284. DealDate := this.GetString("DealDate")
  285. PaymentWay := this.GetString("PaymentWay")
  286. CreatedDate := this.GetString("CreatedDate")
  287. OrderStatus := this.GetString("OrderStatus")
  288. IsRefund, _ := this.GetBool("IsRefund", false)
  289. var condition string
  290. if pageSize <= 0 {
  291. pageSize = utils.PageSize20
  292. }
  293. if currentIndex <= 0 {
  294. currentIndex = 1
  295. }
  296. if IsRefund {
  297. condition += " AND payment_type ='" + string(models.PaymentTypeRefund) + "'"
  298. } else {
  299. condition += " AND payment_type ='" + string(models.PaymentTypePay) + "'"
  300. }
  301. if KeyWord != "" {
  302. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  303. }
  304. sortCondition := " ORDER BY created_time "
  305. if sortType == "" {
  306. sortType = "DESC"
  307. }
  308. if CreatedDate != "" {
  309. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  310. }
  311. if DealDate != "" {
  312. condition += " AND Date(deal_time) = '" + DealDate + "'"
  313. }
  314. if PaymentWay != "" {
  315. condition += " AND payment_way='" + PaymentWay + "'"
  316. }
  317. if OrderStatus != "" {
  318. switch OrderStatus {
  319. case "pending":
  320. condition += " AND payment_status='pending'"
  321. case "done":
  322. condition += " AND payment_status='done'"
  323. case "failed":
  324. condition += " AND payment_status='failed'"
  325. default:
  326. br.Msg = "无效的支付订单状态"
  327. br.ErrMsg = "无效的支付订单状态:" + OrderStatus
  328. return
  329. }
  330. }
  331. sortCondition = sortCondition + sortType
  332. total, err := models.GetTradeOrderCountByCondition(condition)
  333. if err != nil {
  334. br.Msg = "获取支付明细列表失败"
  335. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  336. return
  337. }
  338. startSize := utils.StartIndex(currentIndex, pageSize)
  339. List, err := models.GetTradeOrderByCondition(condition, sortCondition, startSize, pageSize)
  340. if err != nil {
  341. br.Msg = "获取支付明细列表失败"
  342. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  343. return
  344. }
  345. var ListView []*models.TradeOrderView
  346. var wg sync.WaitGroup
  347. wg.Add(len(List))
  348. for i := 0; i < len(List); i++ {
  349. go func(order *models.TradeOrder) {
  350. defer wg.Done()
  351. productOrder, pdErr := models.GetProductOrderByID(order.ProductOrderId)
  352. if pdErr != nil {
  353. utils.FileLog.Error("获取商品订单信息失败,Err:" + pdErr.Error())
  354. }
  355. view := &models.TradeOrderView{
  356. RealName: productOrder.RealName,
  357. Mobile: fmt.Sprintf("+%s %s", productOrder.AreaCode, productOrder.Mobile),
  358. ProductName: productOrder.ProductName,
  359. Amount: order.Amount,
  360. TransactionID: order.TransactionId,
  361. ProductOrderID: order.ProductOrderId,
  362. PaymentWay: PaymentWayMap[order.PaymentWay],
  363. PaymentAccount: order.PaymentAccount,
  364. MerchantID: order.MerchantId,
  365. DealTime: order.DealTime.Format(time.DateTime),
  366. CreatedTime: order.CreatedTime.Format(time.DateTime),
  367. }
  368. if IsRefund {
  369. view.PaymentStatus = RefundOrderStatus[order.PaymentStatus]
  370. } else {
  371. view.PaymentStatus = TradeOrderStatus[order.PaymentStatus]
  372. }
  373. ListView = append(ListView, view)
  374. }(List[i])
  375. }
  376. wg.Wait()
  377. page := paging.GetPaging(currentIndex, pageSize, total)
  378. resp := new(response.TradeOrderListResp)
  379. resp.List = ListView
  380. resp.Paging = page
  381. br.Ret = 200
  382. br.Success = true
  383. br.Data = resp
  384. br.Msg = "获取成功"
  385. }
  386. // ExportProductOrder
  387. // @Title 临时用户列表
  388. // @Description 临时用户列表
  389. // @Param PageSize query int true "每页数据条数"
  390. // @Param CurrentIndex query int true "当前页页码,从1开始"
  391. // @Param Keyword query string false "手机号"
  392. // @Param SortParam query string false "排序字段参数,用来排序的字段, 枚举值:0:注册时间,1:阅读数,2:最近一次阅读时间"
  393. // @Param SortType query string true "如何排序,是正序还是倒序,0:倒序,1:正序"
  394. // @Success 200 {object} response.TemplateUserListResp
  395. // @router /productOrder/export [get]
  396. func (this *OrderController) ExportProductOrder() {
  397. br := new(models.BaseResponse).Init()
  398. defer func() {
  399. this.Data["json"] = br
  400. this.ServeJSON()
  401. }()
  402. pageSize, _ := this.GetInt("PageSize")
  403. currentIndex, _ := this.GetInt("CurrentIndex")
  404. sortType := this.GetString("SortType")
  405. KeyWord := this.GetString("KeyWord")
  406. PaymentDate := this.GetString("PaymentDate")
  407. PaymentWay := this.GetString("PaymentWay")
  408. CreatedDate := this.GetString("CreatedDate")
  409. ProductType := this.GetString("ProductType")
  410. RefundStatus := this.GetString("RefundStatus")
  411. OrderStatus := this.GetString("OrderStatus")
  412. var condition string
  413. if pageSize <= 0 {
  414. pageSize = utils.PageSize20
  415. }
  416. if currentIndex <= 0 {
  417. currentIndex = 1
  418. }
  419. if KeyWord != "" {
  420. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  421. }
  422. sortCondition := " ORDER BY created_time "
  423. if sortType == "" {
  424. sortType = "DESC"
  425. }
  426. if CreatedDate != "" {
  427. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  428. }
  429. if PaymentDate != "" {
  430. condition += " AND Date(payment_time) = '" + PaymentDate + "'"
  431. }
  432. if PaymentWay != "" {
  433. condition += " AND payment_way='" + PaymentWay + "'"
  434. }
  435. if OrderStatus != "" {
  436. switch OrderStatus {
  437. case "pending":
  438. condition += " AND status='pending'"
  439. case "paid":
  440. condition += " AND status='paid'"
  441. case "closed":
  442. condition += " AND status='closed'"
  443. case "refund":
  444. condition += " AND status='refund'"
  445. if RefundStatus != "" {
  446. switch RefundStatus {
  447. case "pending":
  448. condition += " AND refund_status='pending'"
  449. case "processing":
  450. condition += " AND refund_status='processing'"
  451. case "failed":
  452. condition += " AND refund_status='failed'"
  453. case "success":
  454. condition += " AND refund_status='success'"
  455. }
  456. }
  457. default:
  458. br.Msg = "无效的订单状态"
  459. br.ErrMsg = "无效的订单状态:" + OrderStatus
  460. return
  461. }
  462. }
  463. if ProductType != "" {
  464. switch ProductType {
  465. case "report":
  466. condition += " AND product_type='" + string(models.ProductReport) + "'"
  467. case "audio":
  468. condition += " AND product_type='" + string(models.ProductAudio) + "'"
  469. case "video":
  470. condition += " AND product_type='" + string(models.ProductVideo) + "'"
  471. case "package":
  472. condition += " AND product_type='" + string(models.ProductPackage) + "'"
  473. default:
  474. br.Msg = "无效的产品类型"
  475. br.ErrMsg = "无效的产品类型:" + ProductType
  476. return
  477. }
  478. }
  479. sortCondition = sortCondition + sortType
  480. List, err := models.GetProductOrderListByCondition(condition, sortCondition)
  481. if err != nil {
  482. br.Msg = "导出商品订单失败"
  483. br.ErrMsg = "导出商品订单失败,Err:" + err.Error()
  484. return
  485. }
  486. var ListView []models.ProductOrderView
  487. var wg sync.WaitGroup
  488. for _, orderItem := range List {
  489. go func(orderItem models.ProductOrder) {
  490. defer wg.Done()
  491. view := models.ProductOrderView{
  492. OrderID: orderItem.OrderID,
  493. RealName: orderItem.RealName,
  494. Mobile: fmt.Sprintf("+%s %s", orderItem.AreaCode, orderItem.Mobile),
  495. ProductType: ProductTypeMap[orderItem.ProductType],
  496. ProductName: orderItem.ProductName,
  497. TotalAmount: orderItem.TotalAmount,
  498. TradeNO: orderItem.TradeNO,
  499. RefundAmount: orderItem.RefundAmount,
  500. RefundTradeId: orderItem.RefundTradeId,
  501. PaymentWay: PaymentWayMap[orderItem.PaymentWay],
  502. PaymentAmount: orderItem.PaymentAmount,
  503. Status: ProductOrderStatus[orderItem.Status],
  504. RefundStatus: RefundStatusMap[orderItem.RefundStatus],
  505. Remark: orderItem.Remark,
  506. CreatedTime: orderItem.CreatedTime.Format(time.DateTime),
  507. }
  508. if orderItem.TradeNO != "" {
  509. view.PaymentTime = orderItem.PaymentTime.Format(time.DateTime)
  510. tradeOrder, tradeErr := models.GetTradeOrderByNo(orderItem.TradeNO)
  511. if tradeErr != nil {
  512. utils.FileLog.Error("获取支付订单失败,支付订单号:" + orderItem.TradeNO + ",err:" + tradeErr.Error())
  513. } else {
  514. view.PaymentAmount = fmt.Sprintf("%s %.2f", tradeOrder.Currency, tradeOrder.Amount)
  515. }
  516. }
  517. if orderItem.Status == models.OrderStatusPaid {
  518. access, accessErr := models.GetAccess(orderItem.ProductID, orderItem.TemplateUserID)
  519. if accessErr != nil {
  520. utils.FileLog.Error("获取用户订阅记录失败,templateUserId:" + string(rune(orderItem.TemplateUserID)) + "productId:" + string(rune(orderItem.ProductID)) + ",err:" + accessErr.Error())
  521. } else {
  522. if access.ProductType == models.ProductPackage {
  523. view.ValidDuration = fmt.Sprintf("%s~%s", access.BeginDate.Format(time.DateOnly), access.EndDate.Format(time.DateOnly))
  524. } else {
  525. view.ValidDuration = "永久有效"
  526. }
  527. }
  528. }
  529. if orderItem.Status == models.OrderStatusRefund && orderItem.RefundStatus == models.RefundStatusSuccess {
  530. view.RefundFinishTime = orderItem.RefundFinishTime.Format(time.DateTime)
  531. }
  532. ListView = append(ListView, view)
  533. }(orderItem)
  534. }
  535. wg.Wait()
  536. year, month, day := time.Now().Date()
  537. yearStr := strconv.Itoa(year)[2:]
  538. fileName := fmt.Sprintf("商品订单%s.%d.%d.xlsx", yearStr, month, day)
  539. file, err := utils.ExportExcel("商品订单", productCols, ListView)
  540. _ = this.downloadExcelFile(file, fileName)
  541. br.Ret = 200
  542. br.Success = true
  543. br.Msg = "下载成功"
  544. }
  545. // ExportTradeOrder
  546. // @Title 临时用户列表
  547. // @Description 临时用户列表
  548. // @Param PageSize query int true "每页数据条数"
  549. // @Param CurrentIndex query int true "当前页页码,从1开始"
  550. // @Param Keyword query string false "手机号"
  551. // @Param SortParam query string false "排序字段参数,用来排序的字段, 枚举值:0:注册时间,1:阅读数,2:最近一次阅读时间"
  552. // @Param SortType query string true "如何排序,是正序还是倒序,0:倒序,1:正序"
  553. // @Success 200 {object} response.TemplateUserListResp
  554. // @router /tradeOrder/export [get]
  555. func (this *OrderController) ExportTradeOrder() {
  556. br := new(models.BaseResponse).Init()
  557. defer func() {
  558. this.Data["json"] = br
  559. this.ServeJSON()
  560. }()
  561. pageSize, _ := this.GetInt("PageSize")
  562. currentIndex, _ := this.GetInt("CurrentIndex")
  563. sortType := this.GetString("SortType")
  564. KeyWord := this.GetString("KeyWord")
  565. DealDate := this.GetString("DealDate")
  566. PaymentWay := this.GetString("PaymentWay")
  567. CreatedDate := this.GetString("CreatedDate")
  568. OrderStatus := this.GetString("OrderStatus")
  569. IsRefund, _ := this.GetBool("IsRefund", false)
  570. var condition string
  571. if pageSize <= 0 {
  572. pageSize = utils.PageSize20
  573. }
  574. if currentIndex <= 0 {
  575. currentIndex = 1
  576. }
  577. if IsRefund {
  578. condition += " AND payment_type ='" + string(models.PaymentTypeRefund) + "'"
  579. } else {
  580. condition += " AND payment_type ='" + string(models.PaymentTypePay) + "'"
  581. }
  582. if KeyWord != "" {
  583. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  584. }
  585. sortCondition := " ORDER BY created_time "
  586. if sortType == "" {
  587. sortType = "DESC"
  588. }
  589. if CreatedDate != "" {
  590. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  591. }
  592. if DealDate != "" {
  593. condition += " AND Date(deal_time) = '" + DealDate + "'"
  594. }
  595. if PaymentWay != "" {
  596. condition += " AND payment_way='" + PaymentWay + "'"
  597. }
  598. if OrderStatus != "" {
  599. switch OrderStatus {
  600. case "pending":
  601. condition += " AND payment_status='pending'"
  602. case "done":
  603. condition += " AND payment_status='done'"
  604. case "failed":
  605. condition += " AND payment_status='failed'"
  606. default:
  607. br.Msg = "无效的支付订单状态"
  608. br.ErrMsg = "无效的支付订单状态:" + OrderStatus
  609. return
  610. }
  611. }
  612. sortCondition = sortCondition + sortType
  613. List, err := models.GetTradeOrderListByCondition(condition, sortCondition)
  614. if err != nil {
  615. br.Msg = "获取支付明细列表失败"
  616. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  617. return
  618. }
  619. var ListView []models.TradeOrderView
  620. var wg sync.WaitGroup
  621. wg.Add(len(List))
  622. for i := 0; i < len(List); i++ {
  623. go func(order *models.TradeOrder) {
  624. defer wg.Done()
  625. productOrder, pdErr := models.GetProductOrderByID(order.ProductOrderId)
  626. if pdErr != nil {
  627. utils.FileLog.Error("获取商品订单信息失败,Err:" + pdErr.Error())
  628. }
  629. view := models.TradeOrderView{
  630. RealName: productOrder.RealName,
  631. Mobile: fmt.Sprintf("+%s %s", productOrder.AreaCode, productOrder.Mobile),
  632. ProductName: productOrder.ProductName,
  633. Amount: order.Amount,
  634. TransactionID: order.TransactionId,
  635. ProductOrderID: order.ProductOrderId,
  636. PaymentWay: PaymentWayMap[order.PaymentWay],
  637. PaymentAccount: order.PaymentAccount,
  638. MerchantID: order.MerchantId,
  639. DealTime: order.DealTime.Format(time.DateTime),
  640. CreatedTime: order.CreatedTime.Format(time.DateTime),
  641. }
  642. if IsRefund {
  643. view.PaymentStatus = RefundOrderStatus[order.PaymentStatus]
  644. } else {
  645. view.PaymentStatus = TradeOrderStatus[order.PaymentStatus]
  646. }
  647. ListView = append(ListView, view)
  648. }(List[i])
  649. }
  650. wg.Wait()
  651. year, month, day := time.Now().Date()
  652. yearStr := strconv.Itoa(year)[2:]
  653. if IsRefund {
  654. fileName := fmt.Sprintf("退款明细%s.%d.%d.xlsx", yearStr, month, day)
  655. file, _ := utils.ExportExcel("退款明细", refundCols, ListView)
  656. _ = this.downloadExcelFile(file, fileName)
  657. } else {
  658. fileName := fmt.Sprintf("支付明细%s.%d.%d.xlsx", yearStr, month, day)
  659. file, _ := utils.ExportExcel("支付明细", tradeCols, ListView)
  660. _ = this.downloadExcelFile(file, fileName)
  661. }
  662. br.Ret = 200
  663. br.Success = true
  664. br.Msg = "下载成功"
  665. }
  666. // encodeChineseFilename 将中文文件名编码为 ISO-8859-1
  667. func (this *OrderController) downloadExcelFile(file *excelize.File, filename string) (err error) {
  668. // 对文件名进行 ISO-8859-1 编码
  669. fn := url.QueryEscape(filename)
  670. if filename == fn {
  671. fn = "filename=" + fn
  672. } else {
  673. fn = "filename=" + filename + "; filename*=utf-8''" + fn
  674. }
  675. this.Ctx.ResponseWriter.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
  676. this.Ctx.ResponseWriter.Header().Set("Content-Disposition", "attachment; "+fn)
  677. this.Ctx.ResponseWriter.Header().Set("Content-Description", "File Transfer")
  678. this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/octet-stream")
  679. this.Ctx.ResponseWriter.Header().Set("Content-Transfer-Encoding", "binary")
  680. this.Ctx.ResponseWriter.Header().Set("Expires", "0")
  681. this.Ctx.ResponseWriter.Header().Set("Cache-Control", "must-revalidate")
  682. this.Ctx.ResponseWriter.Header().Set("Pragma", "public")
  683. this.Ctx.ResponseWriter.Header().Set("File-Name", filename)
  684. // 写入文件
  685. if err = file.Write(this.Ctx.ResponseWriter); err != nil {
  686. utils.FileLog.Error("导出excel文件失败:", err)
  687. http.Error(this.Ctx.ResponseWriter, "导出excel文件失败", http.StatusInternalServerError)
  688. }
  689. return
  690. }
  691. // Refund
  692. // @Title 退款
  693. // @Description 退款
  694. // @Param PageSize query int true "每页数据条数"
  695. // @Param CurrentIndex query int true "当前页页码,从1开始"
  696. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  697. // @Param KeyWord query string true "报告标题/创建人"
  698. // @Param SortType query string true "排序方式"
  699. // @Success 200 {object} models.ReportAuthorResp
  700. // @router /refund [post]
  701. func (this *OrderController) Refund() {
  702. br := new(models.BaseResponse).Init()
  703. defer func() {
  704. this.Data["json"] = br
  705. this.ServeJSON()
  706. }()
  707. var req request.RefundReq
  708. if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
  709. br.Msg = "参数解析失败"
  710. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  711. return
  712. }
  713. if req.ProductOrderNo == "" {
  714. br.Msg = "商品订单号不能为空"
  715. br.ErrMsg = "商品订单号不能为空"
  716. return
  717. }
  718. productOrder, err := models.GetProductOrderByID(req.ProductOrderNo)
  719. if err != nil {
  720. br.Msg = "获取商品订单失败"
  721. br.ErrMsg = "获取商品订单失败,err:" + err.Error()
  722. return
  723. }
  724. if productOrder.Status == models.OrderStatusPending {
  725. br.Msg = "退款失败,"
  726. br.ErrMsg = "退款失败,退款状态异常,当前订单已关闭"
  727. return
  728. }
  729. if productOrder.Status == models.OrderStatusRefund && productOrder.RefundStatus != models.RefundStatusFailed {
  730. br.Msg = "退款失败,"
  731. br.ErrMsg = "退款失败,当前订单退款处理中"
  732. return
  733. }
  734. tradeOrder, err := models.GetTradeOrderByNo(productOrder.TradeNO)
  735. if err != nil {
  736. br.Msg = "退款失败,获取原订单失败"
  737. br.ErrMsg = "退款失败,获取原订单失败,err:" + err.Error()
  738. return
  739. }
  740. if tradeOrder.PaymentType != models.PaymentTypePay {
  741. br.Msg = "退款失败,原订单非支付订单"
  742. br.ErrMsg = "退款失败,原订单非支付订单"
  743. return
  744. }
  745. if tradeOrder.PaymentStatus == models.PaymentStatusDone {
  746. br.Msg = "退款失败,原订单未完成支付"
  747. br.ErrMsg = "退款失败,原订单未完成支付"
  748. return
  749. }
  750. aa := GenerateProductOrderNo()
  751. refundOrder := &models.TradeOrder{
  752. TransactionId: aa,
  753. OrgTransactionId: productOrder.TradeNO,
  754. ProductOrderId: productOrder.OrderID,
  755. PaymentAccount: tradeOrder.PaymentAccount,
  756. PaymentWay: tradeOrder.PaymentWay,
  757. Amount: tradeOrder.Amount,
  758. Currency: tradeOrder.Currency,
  759. UserId: tradeOrder.UserId,
  760. TemplateUserId: tradeOrder.TemplateUserId,
  761. PaymentType: models.PaymentTypeRefund,
  762. PaymentStatus: models.PaymentStatusProcessing,
  763. CreatedTime: time.Now(),
  764. }
  765. productOrder.RefundStatus = models.RefundStatusPending
  766. productOrder.Status = models.OrderStatusRefund
  767. productOrder.RefundTradeId = refundOrder.TransactionId
  768. productOrder.Remark = req.Remark
  769. productOrder.RefundAmount = tradeOrder.Amount
  770. err = refundOrder.Refund(productOrder)
  771. if err != nil {
  772. br.Msg = "退款失败"
  773. br.ErrMsg = "退款失败,,Err:" + err.Error()
  774. return
  775. }
  776. br.Ret = 200
  777. br.Success = true
  778. br.Msg = "退款处理成功"
  779. }
  780. func GenerateProductOrderNo() string {
  781. timestamp := time.Now().UnixNano() / 1000000 // 毫秒级时间戳
  782. // 生成随机数
  783. rand.New(rand.NewSource(time.Now().UnixNano()))
  784. randomPart := rand.Intn(999999)
  785. // 格式化订单号
  786. orderNumber := fmt.Sprintf("R%d%06d", timestamp, randomPart)
  787. return orderNumber
  788. }
  789. // RefundDetail
  790. // @Title 退款详情
  791. // @Description 退款详情
  792. // @Param PageSize query int true "每页数据条数"
  793. // @Param CurrentIndex query int true "当前页页码,从1开始"
  794. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  795. // @Param KeyWord query string true "报告标题/创建人"
  796. // @Param SortType query string true "排序方式"
  797. // @Success 200 {object} models.ReportAuthorResp
  798. // @router /refundDetail [get]
  799. func (this *OrderController) RefundDetail() {
  800. br := new(models.BaseResponse).Init()
  801. defer func() {
  802. this.Data["json"] = br
  803. this.ServeJSON()
  804. }()
  805. ProductOrderNo := this.GetString("ProductOrderNo")
  806. if ProductOrderNo == "" {
  807. br.Msg = "商品订单号不能为空"
  808. br.ErrMsg = "商品订单号不能为空"
  809. return
  810. }
  811. productOrder, err := models.GetProductOrderByID(ProductOrderNo)
  812. if err != nil {
  813. br.Msg = "获取商品订单失败"
  814. br.ErrMsg = "获取商品订单失败,err:" + err.Error()
  815. return
  816. }
  817. if productOrder.Status != models.OrderStatusRefund && productOrder.RefundStatus != models.RefundStatusSuccess {
  818. br.Msg = "当前订单未完成退款"
  819. br.ErrMsg = "当前订单未完成退款"
  820. return
  821. }
  822. refundOrder, err := models.GetTradeOrderByNo(productOrder.RefundTradeId)
  823. if err != nil {
  824. br.Msg = "获取退款订单失败"
  825. br.ErrMsg = "获取退款订单失败,err:" + err.Error()
  826. return
  827. }
  828. refundResp := response.RefundResp{
  829. Account: refundOrder.PaymentAccount,
  830. RealName: productOrder.RealName,
  831. RefundAmount: productOrder.RefundAmount,
  832. RefundFinishTime: productOrder.RefundFinishTime.Format(time.DateTime),
  833. Remark: productOrder.Remark,
  834. }
  835. br.Ret = 200
  836. br.Success = true
  837. br.Data = refundResp
  838. br.Msg = "退款详情获取成功"
  839. return
  840. }