report.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package api
  2. import (
  3. "box-cost/db/model"
  4. "box-cost/db/repo"
  5. "box-cost/log"
  6. "errors"
  7. "fmt"
  8. "github.com/gin-gonic/gin"
  9. "github.com/go-redis/redis/v8"
  10. "github.com/xuri/excelize/v2"
  11. "go.mongodb.org/mongo-driver/bson"
  12. "go.mongodb.org/mongo-driver/bson/primitive"
  13. )
  14. // 统计报表
  15. func Report(r *GinRouter) {
  16. r.POST("/report/list", ReportList)
  17. r.POST("/report/download", ReportDownload)
  18. }
  19. type ReportListReq struct {
  20. Supplier string
  21. TimeRange []string
  22. PackIds []primitive.ObjectID
  23. PlanIds []primitive.ObjectID
  24. Page int64
  25. Size int64
  26. }
  27. func ReportList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  28. // 财务管理】 添加统计报表功能。按 时间范围, 供应商(单选) 包装(多选) 计划(多选) 四个维度进行过滤,形成报表。可以下载
  29. var form ReportListReq
  30. err := c.ShouldBindJSON(&form)
  31. if err != nil {
  32. return nil, errors.New("参数错误")
  33. }
  34. var page int64 = 1
  35. var size int64 = 10
  36. if form.Page > 0 {
  37. page = form.Page
  38. } else {
  39. page = 1
  40. }
  41. if form.Size > 0 {
  42. size = form.Size
  43. } else {
  44. size = 10
  45. }
  46. start := (page - 1) * size
  47. end := page*size - 1
  48. // 条件处理
  49. query := make(map[string]interface{}, 0)
  50. if form.Supplier != "" {
  51. query["supplier"] = form.Supplier
  52. }
  53. // 时间范围
  54. if len(form.TimeRange) == 2 {
  55. start, end := getTimeRange(form.TimeRange[0], form.TimeRange[1])
  56. query["createTime"] = bson.M{"$gte": start, "$lte": end}
  57. }
  58. // 包装
  59. if len(form.PackIds) > 0 {
  60. packQuery := []bson.M{}
  61. for _, packId := range form.PackIds {
  62. packQuery = append(packQuery, bson.M{"packId": packId})
  63. }
  64. query["$or"] = packQuery
  65. }
  66. // 计划
  67. if len(form.PlanIds) > 0 {
  68. planQuery := bson.A{}
  69. for _, planId := range form.PlanIds {
  70. planQuery = append(planQuery, bson.M{"planId": planId})
  71. }
  72. query["$or"] = planQuery
  73. }
  74. // 获取采购单符合条件的信息
  75. purchases := []model.PurchaseBill{}
  76. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  77. CollectName: repo.CollectionBillPurchase,
  78. Query: query,
  79. }, &purchases)
  80. // 获取加工单符合条件的信息
  81. produces := []model.ProduceBill{}
  82. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  83. CollectName: repo.CollectionBillProduce,
  84. Query: query,
  85. }, &produces)
  86. // 组装数据
  87. cacheKey := "report:list"
  88. apictx.Svc.Redis.Del(apictx.CreateRepoCtx().Ctx, cacheKey)
  89. // key存在时
  90. // if apictx.Svc.Redis.Exists(apictx.CreateRepoCtx().Ctx, cacheKey).Val() == 1 {
  91. // ret := apictx.Svc.Redis.ZRange(apictx.CreateRepoCtx().Ctx, cacheKey, start, end)
  92. // retList = ret.Val()
  93. // } else {
  94. // }
  95. mlen := len(purchases) + len(produces)
  96. type MapList map[string]interface{}
  97. lists := make([]MapList, mlen)
  98. if len(purchases) > 0 {
  99. for _, purchase := range purchases {
  100. apictx.Svc.Redis.ZAdd(apictx.CreateRepoCtx().Ctx, cacheKey, &redis.Z{
  101. Score: float64(purchase.CreateTime.Unix()),
  102. Member: purchase.Id.Hex(),
  103. })
  104. list := MapList{purchase.Id.Hex(): purchase, "type": "purchase"}
  105. lists = append(lists, list)
  106. }
  107. }
  108. if len(produces) > 0 {
  109. for _, produce := range produces {
  110. apictx.Svc.Redis.ZAdd(apictx.CreateRepoCtx().Ctx, cacheKey, &redis.Z{
  111. Score: float64(produce.CreateTime.Unix()),
  112. Member: produce.Id.Hex(),
  113. })
  114. list := MapList{produce.Id.Hex(): produce, "type": "produce"}
  115. lists = append(lists, list)
  116. }
  117. }
  118. // 当前key存在时
  119. retList := make([]map[string]interface{}, 0)
  120. // 所有id
  121. ids := make([]map[string]string, 0)
  122. if apictx.Svc.Redis.Exists(apictx.CreateRepoCtx().Ctx, cacheKey).Val() == 1 {
  123. // ret := apictx.Svc.Redis.ExpireLT(apictx.CreateRepoCtx().Ctx, cacheKey, 20*time.Second)
  124. // 按创建时间升序排
  125. result := apictx.Svc.Redis.ZRange(apictx.CreateRepoCtx().Ctx, cacheKey, start, end)
  126. if result.Err() != nil {
  127. log.Error(err)
  128. return nil, errors.New("缓存数据内部错误")
  129. }
  130. retids := apictx.Svc.Redis.ZRange(apictx.CreateRepoCtx().Ctx, cacheKey, 0, -1)
  131. // 所有id
  132. if len(retids.Val()) > 0 {
  133. for _, id := range retids.Val() {
  134. for _, item := range lists {
  135. if _, ok := item[id]; ok {
  136. ids = append(ids, map[string]string{"id": id, "type": item["type"].(string)})
  137. }
  138. }
  139. }
  140. }
  141. // 返回的列表
  142. if len(result.Val()) > 0 {
  143. for _, id := range result.Val() {
  144. for _, item := range lists {
  145. if _, ok := item[id]; ok {
  146. retList = append(retList, item)
  147. }
  148. }
  149. }
  150. }
  151. }
  152. type PageResult struct {
  153. List []map[string]interface{} `json:"list"`
  154. Total int64 `json:"total"`
  155. Page int64 `json:"page"`
  156. Size int64 `json:"size"`
  157. Ids []map[string]string `json:"ids"`
  158. }
  159. out := &PageResult{
  160. List: retList,
  161. Total: int64(mlen),
  162. Page: page,
  163. Size: size,
  164. Ids: ids,
  165. }
  166. return out, nil
  167. }
  168. type ReportDownloadReq struct {
  169. Id string
  170. Type string
  171. }
  172. func ReportDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  173. var form []ReportDownloadReq
  174. err := c.ShouldBindJSON(&form)
  175. if err != nil {
  176. return nil, errors.New("参数错误")
  177. }
  178. if len(form) > 0 {
  179. info := model.Setting{}
  180. repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  181. CollectName: "infos",
  182. }, &info)
  183. f := excelize.NewFile()
  184. // Create a new sheet.
  185. index := f.NewSheet("Sheet1")
  186. f.SetActiveSheet(index)
  187. f.SetDefaultFont("宋体")
  188. offset := 0
  189. for _, req := range form {
  190. // 是采购单
  191. if req.Type == "purchase" {
  192. purchaseId, err := primitive.ObjectIDFromHex(req.Id)
  193. if err == nil {
  194. purchase := model.PurchaseBill{}
  195. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  196. CollectName: repo.CollectionBillPurchase,
  197. Query: repo.Map{"_id": purchaseId},
  198. }, &purchase)
  199. if found {
  200. purchaseExcel := NewPurchaseBill(f)
  201. purchaseExcel.Content = &purchase
  202. purchaseExcel.Title = fmt.Sprintf("%s原材料采购单", info.CompanyName)
  203. //设置对应的数据
  204. purchaseExcel.Offset = offset
  205. purchaseExcel.Draws()
  206. offset += 15
  207. }
  208. }
  209. }
  210. // 是加工单
  211. if req.Type == "produce" {
  212. produceId, err := primitive.ObjectIDFromHex(req.Id)
  213. if err == nil {
  214. produce := model.ProduceBill{}
  215. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  216. CollectName: repo.CollectionBillProduce,
  217. Query: repo.Map{"_id": produceId},
  218. }, &produce)
  219. if found {
  220. produceExcel := NewProduceBill(f)
  221. produceExcel.Content = &produce
  222. produceExcel.Title = fmt.Sprintf("%s加工单", info.CompanyName)
  223. //设置对应的数据
  224. produceExcel.Offset = offset
  225. produceExcel.Draws()
  226. offset += 15
  227. }
  228. }
  229. }
  230. }
  231. c.Header("Content-Type", "application/octet-stream")
  232. c.Header("Content-Disposition", "attachment; filename="+"report.xlsx")
  233. c.Header("Content-Transfer-Encoding", "binary")
  234. err = f.Write(c.Writer)
  235. if err != nil {
  236. return nil, err
  237. }
  238. }
  239. return nil, nil
  240. }