summary.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. package api
  2. import (
  3. "box-cost/db/model"
  4. "box-cost/db/repo"
  5. "box-cost/log"
  6. "errors"
  7. "strings"
  8. "time"
  9. "github.com/gin-gonic/gin"
  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 Summary(r *GinRouter) {
  16. // 下载详细汇总
  17. r.GET("/summary/download", SummaryDownload)
  18. // 下载简单汇总
  19. r.GET("/summary/sample/download", SummarySampleDownload)
  20. // !10.27 时间和供应商查询
  21. // summary/supplier/plan query={"supplierId":"xxx","timeRange":["xxx","xxx"]}
  22. // 返回planIds数组 []string
  23. r.GET("/summary/supplier/plan", SummarySupplierPlan)
  24. }
  25. type SupplierPlanSummary struct {
  26. Plans []*PlanSummary
  27. SupplierId primitive.ObjectID
  28. ApiSession *ApiSession
  29. }
  30. type PlanSummary struct {
  31. Plan *model.ProductPlan
  32. IsSend map[string]bool
  33. IsAck map[string]bool
  34. Reviewed map[string]int32
  35. State map[string]string
  36. CreateTimes map[string]time.Time
  37. SerialNumber map[string]string
  38. SendTo map[string]string
  39. }
  40. func SummarySupplierPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  41. _, _, query := UtilQueryPageSize(c)
  42. supplierId := primitive.NilObjectID
  43. if _supplierId, ok := query["supplierId"]; ok {
  44. supplierId, _ = primitive.ObjectIDFromHex(_supplierId.(string))
  45. delete(query, "supplierId")
  46. }
  47. if _timeRange, ok := query["timeRange"]; ok {
  48. timeRange, _ := _timeRange.([]interface{})
  49. if len(timeRange) == 2 {
  50. start, end := getTimeRange(timeRange[0].(string), timeRange[1].(string))
  51. query["createTime"] = bson.M{"$gte": start, "$lte": end}
  52. }
  53. delete(query, "timeRange")
  54. }
  55. // 遍历判断包含供应商的数据,返回planIds
  56. plans := []*model.ProductPlan{}
  57. err := repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  58. CollectName: repo.CollectionProductPlan,
  59. Query: query,
  60. Project: []string{"_id", "pack"},
  61. Sort: bson.M{"createTime": -1},
  62. }, &plans)
  63. if err != nil {
  64. log.Error(err)
  65. return nil, errors.New("查询数据错误!")
  66. }
  67. planIds := []primitive.ObjectID{}
  68. if len(plans) < 1 {
  69. return planIds, nil
  70. }
  71. // 遍历
  72. flag := false
  73. for _, plan := range plans {
  74. // 选供应商
  75. if !supplierId.IsZero() {
  76. for _, comp := range plan.Pack.Components {
  77. if comp.Id == "" || len(comp.Stages) == 0 {
  78. continue
  79. }
  80. for _, stage := range comp.Stages {
  81. // 只要任意一个stage中存在选中的供应商,那么这个计划包含这个供应商,这时应该跳出来
  82. if stage.SupplierInfo == nil {
  83. continue
  84. }
  85. if stage.SupplierInfo.Id == supplierId {
  86. planIds = append(planIds, plan.Id)
  87. flag = true
  88. break
  89. }
  90. }
  91. if flag {
  92. break
  93. }
  94. }
  95. } else {
  96. planIds = append(planIds, plan.Id)
  97. }
  98. if flag {
  99. continue
  100. }
  101. }
  102. return planIds, nil
  103. }
  104. // /summary/download?planIds=id1,id2&supplierId=xxx
  105. func SummaryDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  106. // 获取planIds supplierId
  107. _planIds := c.Query("planIds") // id1,id2...
  108. _supplierId := c.Query("supplierId") // 供应商id
  109. planIds := strings.Split(_planIds, ",")
  110. supplierId, _ := primitive.ObjectIDFromHex(_supplierId)
  111. // 获取详情
  112. if len(planIds) < 1 {
  113. return nil, errors.New("数据不存在")
  114. }
  115. summaryPlans := []*PlanSummary{}
  116. for _, _planId := range planIds {
  117. id, _ := primitive.ObjectIDFromHex(_planId)
  118. if id.IsZero() {
  119. return nil, errors.New("非法id")
  120. }
  121. plan := &model.ProductPlan{}
  122. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  123. CollectName: repo.CollectionProductPlan,
  124. Query: repo.Map{"_id": id},
  125. }, plan)
  126. if !found || err != nil {
  127. continue
  128. }
  129. summaryPlan := GetPlanStatus(plan, apictx)
  130. summaryPlans = append(summaryPlans, summaryPlan)
  131. }
  132. if len(summaryPlans) < 1 {
  133. return nil, errors.New("数据不存在")
  134. }
  135. // 实例化表格,传入数据
  136. f := excelize.NewFile()
  137. index := f.NewSheet("Sheet1")
  138. f.SetActiveSheet(index)
  139. f.SetDefaultFont("宋体")
  140. planSummaryExcel := NewPlanSummaryExcel(f)
  141. planSummaryExcel.Content = &SupplierPlanSummary{
  142. Plans: summaryPlans,
  143. SupplierId: supplierId,
  144. ApiSession: apictx,
  145. }
  146. // 绘制表格
  147. planSummaryExcel.Draws()
  148. c.Header("Content-Type", "application/octet-stream")
  149. c.Header("Content-Disposition", "attachment; filename="+"planSummary.xlsx")
  150. c.Header("Content-Transfer-Encoding", "binary")
  151. err := f.Write(c.Writer)
  152. if err != nil {
  153. return nil, err
  154. }
  155. return nil, nil
  156. }
  157. // /summary/sample/download?planIds=id1,id2&supplierId=xxx
  158. func SummarySampleDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  159. // 获取planIds supplierId
  160. _planIds := c.Query("planIds") // id1,id2...
  161. _supplierId := c.Query("supplierId") // 供应商id
  162. planIds := strings.Split(_planIds, ",")
  163. supplierId, _ := primitive.ObjectIDFromHex(_supplierId)
  164. // 获取详情
  165. if len(planIds) < 1 {
  166. return nil, errors.New("数据不存在")
  167. }
  168. summaryPlans := []*PlanSummary{}
  169. for _, _planId := range planIds {
  170. id, _ := primitive.ObjectIDFromHex(_planId)
  171. if id.IsZero() {
  172. return nil, errors.New("非法id")
  173. }
  174. plan := &model.ProductPlan{}
  175. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  176. CollectName: repo.CollectionProductPlan,
  177. Query: repo.Map{"_id": id},
  178. }, plan)
  179. if !found || err != nil {
  180. continue
  181. }
  182. summaryPlan := GetPlanStatus(plan, apictx)
  183. summaryPlans = append(summaryPlans, summaryPlan)
  184. }
  185. if len(summaryPlans) < 1 {
  186. return nil, errors.New("数据不存在")
  187. }
  188. // 实例化表格,传入数据
  189. f := excelize.NewFile()
  190. index := f.NewSheet("Sheet1")
  191. f.SetActiveSheet(index)
  192. f.SetDefaultFont("宋体")
  193. planSummaryExcel := NewSummarySampleExcel(f)
  194. planSummaryExcel.Content = &SupplierPlanSummary{
  195. Plans: summaryPlans,
  196. SupplierId: supplierId,
  197. }
  198. // 绘制表格
  199. planSummaryExcel.Draws()
  200. c.Header("Content-Type", "application/octet-stream")
  201. c.Header("Content-Disposition", "attachment; filename="+"planSummary.xlsx")
  202. c.Header("Content-Transfer-Encoding", "binary")
  203. err := f.Write(c.Writer)
  204. if err != nil {
  205. return nil, err
  206. }
  207. return nil, nil
  208. }
  209. func GetPlanStatus(plan *model.ProductPlan, apictx *ApiSession) *PlanSummary {
  210. billStates := map[string]string{}
  211. billSerialNumber := map[string]string{}
  212. billSendTo := map[string]string{}
  213. billIsSend := map[string]bool{}
  214. billReviewed := map[string]int32{}
  215. billIsAck := map[string]bool{}
  216. billCreateTimes := map[string]time.Time{}
  217. if plan.Pack != nil && plan.Pack.Components != nil {
  218. for _, comp := range plan.Pack.Components {
  219. if comp.Stages != nil {
  220. for _, stage := range comp.Stages {
  221. if len(stage.BillId) > 0 {
  222. collectName := ""
  223. // 材料
  224. if stage.BillType == 1 {
  225. collectName = repo.CollectionBillPurchase
  226. }
  227. // 工艺
  228. if stage.BillType == 2 {
  229. collectName = repo.CollectionBillProduce
  230. }
  231. // 成品
  232. if stage.BillType == 3 {
  233. collectName = repo.CollectionBillProduct
  234. }
  235. ok, state := repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  236. CollectName: collectName,
  237. Query: repo.Map{"_id": stage.BillId},
  238. Project: []string{"status", "isSend", "reviewed", "isAck", "serialNumber", "sendTo", "remark", "createTime"}})
  239. if ok {
  240. billStates[stage.BillId] = state["status"].(string)
  241. billSerialNumber[stage.BillId] = state["serialNumber"].(string)
  242. if v, ok := state["sendTo"]; ok {
  243. billSendTo[stage.BillId] = v.(string)
  244. }
  245. if v, ok := state["isSend"]; ok {
  246. billIsSend[stage.BillId] = v.(bool)
  247. } else {
  248. billIsSend[stage.BillId] = false
  249. }
  250. if v, ok := state["reviewed"]; ok {
  251. billReviewed[stage.BillId] = v.(int32)
  252. } else {
  253. billReviewed[stage.BillId] = -1
  254. }
  255. if v, ok := state["isAck"]; ok {
  256. billIsAck[stage.BillId] = v.(bool)
  257. } else {
  258. billIsAck[stage.BillId] = false
  259. }
  260. if v, ok := state["createTime"]; ok {
  261. billCreateTimes[stage.BillId] = v.(primitive.DateTime).Time()
  262. }
  263. }
  264. }
  265. }
  266. }
  267. }
  268. }
  269. return &PlanSummary{
  270. Plan: plan,
  271. IsSend: billIsSend,
  272. IsAck: billIsAck,
  273. Reviewed: billReviewed,
  274. State: billStates,
  275. CreateTimes: billCreateTimes,
  276. SerialNumber: billSerialNumber,
  277. SendTo: billSendTo,
  278. }
  279. }