order.go 28 KB

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