order.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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 + "%' 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. PaymentWay: PaymentWayMap[orderItem.PaymentWay],
  220. Status: ProductOrderStatus[orderItem.Status],
  221. RefundStatus: RefundStatusMap[orderItem.RefundStatus],
  222. Remark: orderItem.Remark,
  223. CreatedTime: orderItem.CreatedTime.Format(time.DateTime),
  224. }
  225. if orderItem.TradeNO != "" {
  226. view.PaymentTime = orderItem.PaymentTime.Format(time.DateTime)
  227. tradeOrder, tradeErr := models.GetTradeOrderByNo(orderItem.TradeNO)
  228. if tradeErr != nil {
  229. utils.FileLog.Error("获取支付订单失败,支付订单号:" + orderItem.TradeNO + ",err:" + tradeErr.Error())
  230. } else {
  231. view.PaymentAmount = fmt.Sprintf("%s %.2f", tradeOrder.Currency, tradeOrder.Amount)
  232. }
  233. }
  234. if orderItem.Status == models.OrderStatusPaid {
  235. access, accessErr := models.GetAccess(orderItem.ProductID, orderItem.TemplateUserID)
  236. if accessErr != nil {
  237. utils.FileLog.Error("获取用户订阅记录失败,templateUserId:" + string(rune(orderItem.TemplateUserID)) + "productId:" + string(rune(orderItem.ProductID)) + ",err:" + accessErr.Error())
  238. } else {
  239. if access.ProductType == models.ProductPackage {
  240. view.ValidDuration = fmt.Sprintf("%s~%s", access.BeginDate.Format(time.DateOnly), access.EndDate.Format(time.DateOnly))
  241. } else {
  242. view.ValidDuration = "永久有效"
  243. }
  244. }
  245. }
  246. if orderItem.Status == models.OrderStatusRefund && orderItem.RefundStatus == models.RefundStatusSuccess {
  247. view.RefundFinishTime = orderItem.RefundFinishTime.Format(time.DateTime)
  248. }
  249. ListView = append(ListView, view)
  250. }(orderItem)
  251. }
  252. wg.Wait()
  253. page := paging.GetPaging(currentIndex, pageSize, total)
  254. resp := new(response.ProductOrderListResp)
  255. resp.List = ListView
  256. resp.Paging = page
  257. br.Ret = 200
  258. br.Success = true
  259. br.Data = resp
  260. br.Msg = "获取成功"
  261. }
  262. // TradeOrderList
  263. // @Title 支付订单列表
  264. // @Description 支付订单列表
  265. // @Param PageSize query int true "每页数据条数"
  266. // @Param CurrentIndex query int true "当前页页码,从1开始"
  267. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  268. // @Param KeyWord query string true "报告标题/创建人"
  269. // @Param SortType query string true "排序方式"
  270. // @Success 200 {object} models.ReportAuthorResp
  271. // @router /tradeOrderList [get]
  272. func (this *OrderController) TradeOrderList() {
  273. br := new(models.BaseResponse).Init()
  274. defer func() {
  275. this.Data["json"] = br
  276. this.ServeJSON()
  277. }()
  278. pageSize, _ := this.GetInt("PageSize")
  279. currentIndex, _ := this.GetInt("CurrentIndex")
  280. sortType := this.GetString("SortType")
  281. KeyWord := this.GetString("KeyWord")
  282. DealDate := this.GetString("DealDate")
  283. PaymentWay := this.GetString("PaymentWay")
  284. CreatedDate := this.GetString("CreatedDate")
  285. OrderStatus := this.GetString("OrderStatus")
  286. IsRefund, _ := this.GetBool("IsRefund", false)
  287. var condition string
  288. if pageSize <= 0 {
  289. pageSize = utils.PageSize20
  290. }
  291. if currentIndex <= 0 {
  292. currentIndex = 1
  293. }
  294. if IsRefund {
  295. condition += " AND payment_type ='" + string(models.PaymentTypeRefund) + "'"
  296. } else {
  297. condition += " AND payment_type ='" + string(models.PaymentTypePay) + "'"
  298. }
  299. if KeyWord != "" {
  300. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  301. }
  302. sortCondition := " ORDER BY created_time "
  303. if sortType == "" {
  304. sortType = "DESC"
  305. }
  306. if CreatedDate != "" {
  307. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  308. }
  309. if DealDate != "" {
  310. condition += " AND Date(deal_time) = '" + DealDate + "'"
  311. }
  312. if PaymentWay != "" {
  313. condition += " AND payment_way='" + PaymentWay + "'"
  314. }
  315. if OrderStatus != "" {
  316. switch OrderStatus {
  317. case "pending":
  318. condition += " AND payment_status='pending'"
  319. case "done":
  320. condition += " AND payment_status='done'"
  321. case "failed":
  322. condition += " AND payment_status='failed'"
  323. default:
  324. br.Msg = "无效的支付订单状态"
  325. br.ErrMsg = "无效的支付订单状态:" + OrderStatus
  326. return
  327. }
  328. }
  329. sortCondition = sortCondition + sortType
  330. total, err := models.GetTradeOrderCountByCondition(condition)
  331. if err != nil {
  332. br.Msg = "获取支付明细列表失败"
  333. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  334. return
  335. }
  336. startSize := utils.StartIndex(currentIndex, pageSize)
  337. List, err := models.GetTradeOrderByCondition(condition, sortCondition, startSize, pageSize)
  338. if err != nil {
  339. br.Msg = "获取支付明细列表失败"
  340. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  341. return
  342. }
  343. var ListView []*models.TradeOrderView
  344. var wg sync.WaitGroup
  345. wg.Add(len(List))
  346. for i := 0; i < len(List); i++ {
  347. go func(order *models.TradeOrder) {
  348. defer wg.Done()
  349. productOrder, pdErr := models.GetProductOrderByID(order.ProductOrderId)
  350. if pdErr != nil {
  351. utils.FileLog.Error("获取商品订单信息失败,Err:" + pdErr.Error())
  352. }
  353. view := &models.TradeOrderView{
  354. RealName: productOrder.RealName,
  355. Mobile: fmt.Sprintf("+%s %s", productOrder.AreaCode, productOrder.Mobile),
  356. ProductName: productOrder.ProductName,
  357. Amount: order.Amount,
  358. TransactionID: order.TransactionId,
  359. ProductOrderID: order.ProductOrderId,
  360. PaymentWay: PaymentWayMap[order.PaymentWay],
  361. PaymentAccount: order.PaymentAccount,
  362. MerchantID: order.MerchantId,
  363. DealTime: order.DealTime.Format(time.DateTime),
  364. CreatedTime: order.CreatedTime.Format(time.DateTime),
  365. }
  366. if IsRefund {
  367. view.PaymentStatus = RefundOrderStatus[order.PaymentStatus]
  368. } else {
  369. view.PaymentStatus = TradeOrderStatus[order.PaymentStatus]
  370. }
  371. ListView = append(ListView, view)
  372. }(List[i])
  373. }
  374. wg.Wait()
  375. page := paging.GetPaging(currentIndex, pageSize, total)
  376. resp := new(response.TradeOrderListResp)
  377. resp.List = ListView
  378. resp.Paging = page
  379. br.Ret = 200
  380. br.Success = true
  381. br.Data = resp
  382. br.Msg = "获取成功"
  383. }
  384. // ExportProductOrder
  385. // @Title 临时用户列表
  386. // @Description 临时用户列表
  387. // @Param PageSize query int true "每页数据条数"
  388. // @Param CurrentIndex query int true "当前页页码,从1开始"
  389. // @Param Keyword query string false "手机号"
  390. // @Param SortParam query string false "排序字段参数,用来排序的字段, 枚举值:0:注册时间,1:阅读数,2:最近一次阅读时间"
  391. // @Param SortType query string true "如何排序,是正序还是倒序,0:倒序,1:正序"
  392. // @Success 200 {object} response.TemplateUserListResp
  393. // @router /productOrder/export [get]
  394. func (this *OrderController) ExportProductOrder() {
  395. br := new(models.BaseResponse).Init()
  396. defer func() {
  397. this.Data["json"] = br
  398. this.ServeJSON()
  399. }()
  400. pageSize, _ := this.GetInt("PageSize")
  401. currentIndex, _ := this.GetInt("CurrentIndex")
  402. sortType := this.GetString("SortType")
  403. KeyWord := this.GetString("KeyWord")
  404. PaymentDate := this.GetString("PaymentDate")
  405. PaymentWay := this.GetString("PaymentWay")
  406. CreatedDate := this.GetString("CreatedDate")
  407. ProductType := this.GetString("ProductType")
  408. RefundStatus := this.GetString("RefundStatus")
  409. OrderStatus := this.GetString("OrderStatus")
  410. var condition string
  411. if pageSize <= 0 {
  412. pageSize = utils.PageSize20
  413. }
  414. if currentIndex <= 0 {
  415. currentIndex = 1
  416. }
  417. if KeyWord != "" {
  418. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  419. }
  420. sortCondition := " ORDER BY created_time "
  421. if sortType == "" {
  422. sortType = "DESC"
  423. }
  424. if CreatedDate != "" {
  425. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  426. }
  427. if PaymentDate != "" {
  428. condition += " AND Date(payment_time) = '" + PaymentDate + "'"
  429. }
  430. if PaymentWay != "" {
  431. condition += " AND payment_way='" + PaymentWay + "'"
  432. }
  433. if OrderStatus != "" {
  434. switch OrderStatus {
  435. case "pending":
  436. condition += " AND status='pending'"
  437. case "paid":
  438. condition += " AND status='paid'"
  439. case "closed":
  440. condition += " AND status='closed'"
  441. case "refund":
  442. condition += " AND status='refund'"
  443. if RefundStatus != "" {
  444. switch RefundStatus {
  445. case "pending":
  446. condition += " AND refund_status='pending'"
  447. case "processing":
  448. condition += " AND refund_status='processing'"
  449. case "failed":
  450. condition += " AND refund_status='failed'"
  451. case "success":
  452. condition += " AND refund_status='success'"
  453. }
  454. }
  455. default:
  456. br.Msg = "无效的订单状态"
  457. br.ErrMsg = "无效的订单状态:" + OrderStatus
  458. return
  459. }
  460. }
  461. if ProductType != "" {
  462. switch ProductType {
  463. case "report":
  464. condition += " AND product_type='" + string(models.ProductReport) + "'"
  465. case "audio":
  466. condition += " AND product_type='" + string(models.ProductAudio) + "'"
  467. case "video":
  468. condition += " AND product_type='" + string(models.ProductVideo) + "'"
  469. case "package":
  470. condition += " AND product_type='" + string(models.ProductPackage) + "'"
  471. default:
  472. br.Msg = "无效的产品类型"
  473. br.ErrMsg = "无效的产品类型:" + ProductType
  474. return
  475. }
  476. }
  477. sortCondition = sortCondition + sortType
  478. List, err := models.GetProductOrderListByCondition(condition, sortCondition)
  479. if err != nil {
  480. br.Msg = "导出商品订单失败"
  481. br.ErrMsg = "导出商品订单失败,Err:" + err.Error()
  482. return
  483. }
  484. var ListView []models.ProductOrderView
  485. for _, order := range List {
  486. view := models.ProductOrderView{
  487. OrderID: order.OrderID,
  488. RealName: order.RealName,
  489. Mobile: fmt.Sprintf("+%s %s", order.AreaCode, order.Mobile),
  490. ProductType: ProductTypeMap[order.ProductType],
  491. ProductName: order.ProductName,
  492. TotalAmount: order.TotalAmount,
  493. TradeNO: order.TradeNO,
  494. RefundAmount: order.RefundAmount,
  495. PaymentWay: PaymentWayMap[order.PaymentWay],
  496. PaymentTime: order.PaymentTime.Format(time.DateTime),
  497. Status: ProductOrderStatus[order.Status],
  498. RefundStatus: RefundStatusMap[order.RefundStatus],
  499. RefundFinishTime: order.RefundFinishTime.Format(time.DateTime),
  500. Remark: order.Remark,
  501. CreatedTime: order.CreatedTime.Format(time.DateTime),
  502. }
  503. ListView = append(ListView, view)
  504. }
  505. year, month, day := time.Now().Date()
  506. yearStr := strconv.Itoa(year)[2:]
  507. fileName := fmt.Sprintf("商品订单%s.%d.%d.xlsx", yearStr, month, day)
  508. file, err := utils.ExportExcel("商品订单", productCols, ListView)
  509. _ = this.downloadExcelFile(file, fileName)
  510. br.Ret = 200
  511. br.Success = true
  512. br.Msg = "下载成功"
  513. }
  514. // ExportTradeOrder
  515. // @Title 临时用户列表
  516. // @Description 临时用户列表
  517. // @Param PageSize query int true "每页数据条数"
  518. // @Param CurrentIndex query int true "当前页页码,从1开始"
  519. // @Param Keyword query string false "手机号"
  520. // @Param SortParam query string false "排序字段参数,用来排序的字段, 枚举值:0:注册时间,1:阅读数,2:最近一次阅读时间"
  521. // @Param SortType query string true "如何排序,是正序还是倒序,0:倒序,1:正序"
  522. // @Success 200 {object} response.TemplateUserListResp
  523. // @router /tradeOrder/export [get]
  524. func (this *OrderController) ExportTradeOrder() {
  525. br := new(models.BaseResponse).Init()
  526. defer func() {
  527. this.Data["json"] = br
  528. this.ServeJSON()
  529. }()
  530. pageSize, _ := this.GetInt("PageSize")
  531. currentIndex, _ := this.GetInt("CurrentIndex")
  532. sortType := this.GetString("SortType")
  533. KeyWord := this.GetString("KeyWord")
  534. DealDate := this.GetString("DealDate")
  535. PaymentWay := this.GetString("PaymentWay")
  536. CreatedDate := this.GetString("CreatedDate")
  537. OrderStatus := this.GetString("OrderStatus")
  538. IsRefund, _ := this.GetBool("IsRefund", false)
  539. var condition string
  540. if pageSize <= 0 {
  541. pageSize = utils.PageSize20
  542. }
  543. if currentIndex <= 0 {
  544. currentIndex = 1
  545. }
  546. if IsRefund {
  547. condition += " AND payment_type ='" + string(models.PaymentTypeRefund) + "'"
  548. } else {
  549. condition += " AND payment_type ='" + string(models.PaymentTypePay) + "'"
  550. }
  551. if KeyWord != "" {
  552. condition += " AND (product_name like '%" + KeyWord + "%' or real_name like '%" + KeyWord + "%' order_id like '%" + KeyWord + "%' or mobile like '%" + KeyWord + "%')"
  553. }
  554. sortCondition := " ORDER BY created_time "
  555. if sortType == "" {
  556. sortType = "DESC"
  557. }
  558. if CreatedDate != "" {
  559. condition += " AND Date(created_time) = '" + CreatedDate + "'"
  560. }
  561. if DealDate != "" {
  562. condition += " AND Date(deal_time) = '" + DealDate + "'"
  563. }
  564. if PaymentWay != "" {
  565. condition += " AND payment_way='" + PaymentWay + "'"
  566. }
  567. if OrderStatus != "" {
  568. switch OrderStatus {
  569. case "pending":
  570. condition += " AND payment_status='pending'"
  571. case "done":
  572. condition += " AND payment_status='done'"
  573. case "failed":
  574. condition += " AND payment_status='failed'"
  575. default:
  576. br.Msg = "无效的支付订单状态"
  577. br.ErrMsg = "无效的支付订单状态:" + OrderStatus
  578. return
  579. }
  580. }
  581. sortCondition = sortCondition + sortType
  582. List, err := models.GetTradeOrderListByCondition(condition, sortCondition)
  583. if err != nil {
  584. br.Msg = "获取支付明细列表失败"
  585. br.ErrMsg = "获取支付明细列表失败,Err:" + err.Error()
  586. return
  587. }
  588. var ListView []models.TradeOrderView
  589. var wg sync.WaitGroup
  590. wg.Add(len(List))
  591. for i := 0; i < len(List); i++ {
  592. go func(order *models.TradeOrder) {
  593. defer wg.Done()
  594. productOrder, pdErr := models.GetProductOrderByID(order.ProductOrderId)
  595. if pdErr != nil {
  596. utils.FileLog.Error("获取商品订单信息失败,Err:" + pdErr.Error())
  597. }
  598. view := models.TradeOrderView{
  599. RealName: productOrder.RealName,
  600. Mobile: fmt.Sprintf("+%s %s", productOrder.AreaCode, productOrder.Mobile),
  601. ProductName: productOrder.ProductName,
  602. Amount: order.Amount,
  603. TransactionID: order.TransactionId,
  604. ProductOrderID: order.ProductOrderId,
  605. PaymentWay: PaymentWayMap[order.PaymentWay],
  606. PaymentAccount: order.PaymentAccount,
  607. MerchantID: order.MerchantId,
  608. DealTime: order.DealTime.Format(time.DateTime),
  609. CreatedTime: order.CreatedTime.Format(time.DateTime),
  610. }
  611. if IsRefund {
  612. view.PaymentStatus = RefundOrderStatus[order.PaymentStatus]
  613. } else {
  614. view.PaymentStatus = TradeOrderStatus[order.PaymentStatus]
  615. }
  616. ListView = append(ListView, view)
  617. }(List[i])
  618. }
  619. wg.Wait()
  620. year, month, day := time.Now().Date()
  621. yearStr := strconv.Itoa(year)[2:]
  622. if IsRefund {
  623. fileName := fmt.Sprintf("退款明细%s.%d.%d.xlsx", yearStr, month, day)
  624. file, _ := utils.ExportExcel("退款明细", refundCols, ListView)
  625. _ = this.downloadExcelFile(file, fileName)
  626. } else {
  627. fileName := fmt.Sprintf("支付明细%s.%d.%d.xlsx", yearStr, month, day)
  628. file, _ := utils.ExportExcel("支付明细", tradeCols, ListView)
  629. _ = this.downloadExcelFile(file, fileName)
  630. }
  631. br.Ret = 200
  632. br.Success = true
  633. br.Msg = "下载成功"
  634. }
  635. // encodeChineseFilename 将中文文件名编码为 ISO-8859-1
  636. func (this *OrderController) downloadExcelFile(file *excelize.File, filename string) (err error) {
  637. // 对文件名进行 ISO-8859-1 编码
  638. fn := url.QueryEscape(filename)
  639. if filename == fn {
  640. fn = "filename=" + fn
  641. } else {
  642. fn = "filename=" + filename + "; filename*=utf-8''" + fn
  643. }
  644. this.Ctx.ResponseWriter.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
  645. this.Ctx.ResponseWriter.Header().Set("Content-Disposition", "attachment; "+fn)
  646. this.Ctx.ResponseWriter.Header().Set("Content-Description", "File Transfer")
  647. this.Ctx.ResponseWriter.Header().Set("Content-Type", "application/octet-stream")
  648. this.Ctx.ResponseWriter.Header().Set("Content-Transfer-Encoding", "binary")
  649. this.Ctx.ResponseWriter.Header().Set("Expires", "0")
  650. this.Ctx.ResponseWriter.Header().Set("Cache-Control", "must-revalidate")
  651. this.Ctx.ResponseWriter.Header().Set("Pragma", "public")
  652. this.Ctx.ResponseWriter.Header().Set("File-Name", filename)
  653. // 写入文件
  654. if err = file.Write(this.Ctx.ResponseWriter); err != nil {
  655. utils.FileLog.Error("导出excel文件失败:", err)
  656. http.Error(this.Ctx.ResponseWriter, "导出excel文件失败", http.StatusInternalServerError)
  657. }
  658. return
  659. }
  660. // Refund
  661. // @Title 退款
  662. // @Description 退款
  663. // @Param PageSize query int true "每页数据条数"
  664. // @Param CurrentIndex query int true "当前页页码,从1开始"
  665. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  666. // @Param KeyWord query string true "报告标题/创建人"
  667. // @Param SortType query string true "排序方式"
  668. // @Success 200 {object} models.ReportAuthorResp
  669. // @router /refund [post]
  670. func (this *OrderController) Refund() {
  671. br := new(models.BaseResponse).Init()
  672. defer func() {
  673. this.Data["json"] = br
  674. this.ServeJSON()
  675. }()
  676. var req request.RefundReq
  677. if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
  678. br.Msg = "参数解析失败"
  679. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  680. return
  681. }
  682. if req.ProductOrderNo == "" {
  683. br.Msg = "商品订单号不能为空"
  684. br.ErrMsg = "商品订单号不能为空"
  685. return
  686. }
  687. productOrder, err := models.GetProductOrderByID(req.ProductOrderNo)
  688. if err != nil {
  689. br.Msg = "获取商品订单失败"
  690. br.ErrMsg = "获取商品订单失败,err:" + err.Error()
  691. return
  692. }
  693. if productOrder.Status == models.OrderStatusPending {
  694. br.Msg = "退款失败,"
  695. br.ErrMsg = "退款失败,退款状态异常,当前订单已关闭"
  696. return
  697. }
  698. if productOrder.Status == models.OrderStatusRefund && productOrder.RefundStatus != models.RefundStatusFailed {
  699. br.Msg = "退款失败,"
  700. br.ErrMsg = "退款失败,当前订单退款处理中"
  701. return
  702. }
  703. tradeOrder, err := models.GetTradeOrderByNo(productOrder.TradeNO)
  704. if err != nil {
  705. br.Msg = "退款失败,获取原订单失败"
  706. br.ErrMsg = "退款失败,获取原订单失败,err:" + err.Error()
  707. return
  708. }
  709. if tradeOrder.PaymentType != models.PaymentTypePay {
  710. br.Msg = "退款失败,原订单非支付订单"
  711. br.ErrMsg = "退款失败,原订单非支付订单"
  712. return
  713. }
  714. if tradeOrder.PaymentStatus == models.PaymentStatusDone {
  715. br.Msg = "退款失败,原订单未完成支付"
  716. br.ErrMsg = "退款失败,原订单未完成支付"
  717. return
  718. }
  719. aa := GenerateProductOrderNo()
  720. refundOrder := &models.TradeOrder{
  721. TransactionId: aa,
  722. OrgTransactionId: productOrder.TradeNO,
  723. ProductOrderId: productOrder.OrderID,
  724. PaymentAccount: tradeOrder.PaymentAccount,
  725. PaymentWay: tradeOrder.PaymentWay,
  726. Amount: tradeOrder.Amount,
  727. Currency: tradeOrder.Currency,
  728. UserId: tradeOrder.UserId,
  729. TemplateUserId: tradeOrder.TemplateUserId,
  730. PaymentType: models.PaymentTypeRefund,
  731. PaymentStatus: models.PaymentStatusProcessing,
  732. CreatedTime: time.Now(),
  733. }
  734. productOrder.RefundStatus = models.RefundStatusPending
  735. productOrder.Status = models.OrderStatusRefund
  736. productOrder.RefundTradeId = refundOrder.TransactionId
  737. productOrder.Remark = req.Remark
  738. productOrder.RefundAmount = tradeOrder.Amount
  739. err = refundOrder.Refund(productOrder)
  740. if err != nil {
  741. br.Msg = "退款失败"
  742. br.ErrMsg = "退款失败,,Err:" + err.Error()
  743. return
  744. }
  745. br.Ret = 200
  746. br.Success = true
  747. br.Msg = "退款处理成功"
  748. }
  749. func GenerateProductOrderNo() string {
  750. timestamp := time.Now().UnixNano() / 1000000 // 毫秒级时间戳
  751. // 生成随机数
  752. rand.New(rand.NewSource(time.Now().UnixNano()))
  753. randomPart := rand.Intn(999999)
  754. // 格式化订单号
  755. orderNumber := fmt.Sprintf("R%d%06d", timestamp, randomPart)
  756. return orderNumber
  757. }
  758. // RefundDetail
  759. // @Title 退款详情
  760. // @Description 退款详情
  761. // @Param PageSize query int true "每页数据条数"
  762. // @Param CurrentIndex query int true "当前页页码,从1开始"
  763. // @Param ClassifyIds query string true "二级分类id,可多选用英文,隔开"
  764. // @Param KeyWord query string true "报告标题/创建人"
  765. // @Param SortType query string true "排序方式"
  766. // @Success 200 {object} models.ReportAuthorResp
  767. // @router /refundDetail [get]
  768. func (this *OrderController) RefundDetail() {
  769. br := new(models.BaseResponse).Init()
  770. defer func() {
  771. this.Data["json"] = br
  772. this.ServeJSON()
  773. }()
  774. ProductOrderNo := this.GetString("ProductOrderNo")
  775. if ProductOrderNo == "" {
  776. br.Msg = "商品订单号不能为空"
  777. br.ErrMsg = "商品订单号不能为空"
  778. return
  779. }
  780. productOrder, err := models.GetProductOrderByID(ProductOrderNo)
  781. if err != nil {
  782. br.Msg = "获取商品订单失败"
  783. br.ErrMsg = "获取商品订单失败,err:" + err.Error()
  784. return
  785. }
  786. if productOrder.Status != models.OrderStatusRefund && productOrder.RefundStatus != models.RefundStatusSuccess {
  787. br.Msg = "当前订单未完成退款"
  788. br.ErrMsg = "当前订单未完成退款"
  789. return
  790. }
  791. refundOrder, err := models.GetTradeOrderByNo(productOrder.RefundTradeId)
  792. if err != nil {
  793. br.Msg = "获取退款订单失败"
  794. br.ErrMsg = "获取退款订单失败,err:" + err.Error()
  795. return
  796. }
  797. refundResp := response.RefundResp{
  798. Account: refundOrder.PaymentAccount,
  799. RealName: productOrder.RealName,
  800. RefundAmount: productOrder.RefundAmount,
  801. RefundFinishTime: productOrder.RefundFinishTime.Format(time.DateTime),
  802. Remark: productOrder.Remark,
  803. }
  804. br.Ret = 200
  805. br.Success = true
  806. br.Data = refundResp
  807. br.Msg = "退款详情获取成功"
  808. return
  809. }