summary.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package api
  2. import (
  3. "box-cost/db/model"
  4. "box-cost/db/repo"
  5. "errors"
  6. "strings"
  7. "time"
  8. "github.com/gin-gonic/gin"
  9. "github.com/xuri/excelize/v2"
  10. "go.mongodb.org/mongo-driver/bson/primitive"
  11. )
  12. // 汇总
  13. func Summary(r *GinRouter) {
  14. // 下载详细汇总
  15. r.GET("/summary/download", SummaryDownload)
  16. // 下载简单汇总
  17. r.GET("/summary/sample/download", SummarySampleDownload)
  18. }
  19. type SupplierPlanSummary struct {
  20. Plans []*PlanSummary
  21. SupplierId primitive.ObjectID
  22. }
  23. type PlanSummary struct {
  24. Plan *model.ProductPlan
  25. IsSend, IsAck map[string]bool
  26. Reviewed map[string]int32
  27. State map[string]string
  28. CreateTimes map[string]time.Time
  29. }
  30. // /summary/download?planIds=id1,id2&supplierId=xxx
  31. func SummaryDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  32. // 获取planIds supplierId
  33. _planIds := c.Query("planIds") // id1,id2...
  34. _supplierId := c.Query("supplierId") // 供应商id
  35. planIds := strings.Split(_planIds, ",")
  36. planIds = filter(planIds, func(s string) bool {
  37. return s != ""
  38. })
  39. supplierId, _ := primitive.ObjectIDFromHex(_supplierId)
  40. // 获取详情
  41. if len(planIds) < 1 {
  42. return nil, errors.New("数据不存在")
  43. }
  44. summaryPlans := []*PlanSummary{}
  45. for _, _planId := range planIds {
  46. id, err := primitive.ObjectIDFromHex(_planId)
  47. if err != nil {
  48. return nil, errors.New("非法id")
  49. }
  50. plan := &model.ProductPlan{}
  51. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  52. CollectName: repo.CollectionProductPlan,
  53. Query: repo.Map{"_id": id},
  54. }, plan)
  55. if !found || err != nil {
  56. continue
  57. }
  58. summaryPlan := GetPlanStatus(plan, apictx)
  59. summaryPlans = append(summaryPlans, summaryPlan)
  60. }
  61. if len(summaryPlans) < 1 {
  62. return nil, errors.New("数据不存在")
  63. }
  64. // 实例化表格,传入数据
  65. f := excelize.NewFile()
  66. index := f.NewSheet("Sheet1")
  67. f.SetActiveSheet(index)
  68. f.SetDefaultFont("宋体")
  69. planSummaryExcel := NewPlanSummaryExcel(f)
  70. planSummaryExcel.Content = &SupplierPlanSummary{
  71. Plans: summaryPlans,
  72. SupplierId: supplierId,
  73. }
  74. // 绘制表格
  75. planSummaryExcel.Draws()
  76. c.Header("Content-Type", "application/octet-stream")
  77. c.Header("Content-Disposition", "attachment; filename="+"planSummary.xlsx")
  78. c.Header("Content-Transfer-Encoding", "binary")
  79. err := f.Write(c.Writer)
  80. if err != nil {
  81. return nil, err
  82. }
  83. return nil, nil
  84. }
  85. // /summary/sample/download?planIds=id1,id2&supplierId=xxx
  86. func SummarySampleDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  87. // 获取planIds supplierId
  88. _planIds := c.Query("planIds") // id1,id2...
  89. _supplierId := c.Query("supplierId") // 供应商id
  90. planIds := strings.Split(_planIds, ",")
  91. planIds = filter(planIds, func(s string) bool {
  92. return s != ""
  93. })
  94. supplierId, _ := primitive.ObjectIDFromHex(_supplierId)
  95. // 获取详情
  96. if len(planIds) < 1 {
  97. return nil, errors.New("数据不存在")
  98. }
  99. summaryPlans := []*PlanSummary{}
  100. for _, _planId := range planIds {
  101. id, err := primitive.ObjectIDFromHex(_planId)
  102. if err != nil {
  103. return nil, errors.New("非法id")
  104. }
  105. plan := &model.ProductPlan{}
  106. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  107. CollectName: repo.CollectionProductPlan,
  108. Query: repo.Map{"_id": id},
  109. }, plan)
  110. if !found || err != nil {
  111. continue
  112. }
  113. summaryPlan := GetPlanStatus(plan, apictx)
  114. summaryPlans = append(summaryPlans, summaryPlan)
  115. }
  116. if len(summaryPlans) < 1 {
  117. return nil, errors.New("数据不存在")
  118. }
  119. // 实例化表格,传入数据
  120. f := excelize.NewFile()
  121. index := f.NewSheet("Sheet1")
  122. f.SetActiveSheet(index)
  123. f.SetDefaultFont("宋体")
  124. planSummaryExcel := NewSummarySampleExcel(f)
  125. planSummaryExcel.Content = &SupplierPlanSummary{
  126. Plans: summaryPlans,
  127. SupplierId: supplierId,
  128. }
  129. // 绘制表格
  130. planSummaryExcel.Draws()
  131. c.Header("Content-Type", "application/octet-stream")
  132. c.Header("Content-Disposition", "attachment; filename="+"planSummary.xlsx")
  133. c.Header("Content-Transfer-Encoding", "binary")
  134. err := f.Write(c.Writer)
  135. if err != nil {
  136. return nil, err
  137. }
  138. return nil, nil
  139. }
  140. func filter(arr []string, f func(string) bool) []string {
  141. var filtered []string
  142. for _, s := range arr {
  143. if f(s) {
  144. filtered = append(filtered, s)
  145. }
  146. }
  147. return filtered
  148. }
  149. func GetPlanStatus(plan *model.ProductPlan, apictx *ApiSession) *PlanSummary {
  150. billStates := map[string]string{}
  151. billIsSend := map[string]bool{}
  152. billReviewed := map[string]int32{}
  153. billIsAck := map[string]bool{}
  154. billCreateTimes := map[string]time.Time{}
  155. if plan.Pack != nil && plan.Pack.Components != nil {
  156. for _, comp := range plan.Pack.Components {
  157. if comp.Stages != nil {
  158. for _, stage := range comp.Stages {
  159. if len(stage.BillId) > 0 {
  160. collectName := ""
  161. // 材料
  162. if stage.BillType == 1 {
  163. collectName = repo.CollectionBillPurchase
  164. }
  165. // 工艺
  166. if stage.BillType == 2 {
  167. collectName = repo.CollectionBillProduce
  168. }
  169. // 成品
  170. if stage.BillType == 3 {
  171. collectName = repo.CollectionBillProduct
  172. }
  173. ok, state := repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  174. CollectName: collectName,
  175. Query: repo.Map{"_id": stage.BillId},
  176. Project: []string{"status", "isSend", "reviewed", "isAck", "serialNumber", "remark", "createTime"}})
  177. if ok {
  178. billStates[stage.BillId] = state["status"].(string)
  179. if v, ok := state["isSend"]; ok {
  180. billIsSend[stage.BillId] = v.(bool)
  181. } else {
  182. billIsSend[stage.BillId] = false
  183. }
  184. if v, ok := state["reviewed"]; ok {
  185. billReviewed[stage.BillId] = v.(int32)
  186. } else {
  187. billReviewed[stage.BillId] = -1
  188. }
  189. if v, ok := state["isAck"]; ok {
  190. billIsAck[stage.BillId] = v.(bool)
  191. } else {
  192. billIsAck[stage.BillId] = false
  193. }
  194. if v, ok := state["createTime"]; ok {
  195. billCreateTimes[stage.BillId] = v.(primitive.DateTime).Time()
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. }
  203. return &PlanSummary{
  204. Plan: plan,
  205. IsSend: billIsSend,
  206. IsAck: billIsAck,
  207. Reviewed: billReviewed,
  208. State: billStates,
  209. CreateTimes: billCreateTimes,
  210. }
  211. }