summary.go 6.4 KB

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