plan.go 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447
  1. package api
  2. import (
  3. "archive/zip"
  4. "box-cost/db/model"
  5. "box-cost/db/repo"
  6. "box-cost/log"
  7. "bytes"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "os"
  12. "path/filepath"
  13. "regexp"
  14. "strings"
  15. "sync"
  16. "time"
  17. "github.com/gin-gonic/gin"
  18. "github.com/xuri/excelize/v2"
  19. "go.mongodb.org/mongo-driver/bson"
  20. "go.mongodb.org/mongo-driver/bson/primitive"
  21. )
  22. // TODO 下载代码重复提取
  23. // 生产计划管理
  24. func ProductPlan(r *GinRouter) {
  25. // 创建生产计划
  26. r.POSTJWT("/plan/create", CreateProductPlan)
  27. // 获取生产计划详情
  28. r.GETJWT("/plan/detail/:id", GetProductPlan)
  29. // 获取生产计划列表
  30. r.GETJWT("/plan/list", GetProductPlans)
  31. // 更新生产计划
  32. r.POSTJWT("/plan/update", UpdateProductPlan)
  33. // 删除生产计划
  34. r.POSTJWT("/plan/delete/:id", DelProductPlan)
  35. // 下载部件单据
  36. // r.GET("/bill/plan/download", DownLoadCompBills)
  37. r.GETJWT("/bill/plan/download", DownLoadPlanBills)
  38. r.GETJWT("/bill/comp/download", DownLoadCompBills)
  39. r.GETJWT("/bill/comp/downloadPdf", DownLoadCompBillsPdf)
  40. r.GETJWT("/bill/plan/downloadPdf", DownLoadPlanBillsPdf)
  41. // 生产成本表
  42. r.GETJWT("/plan/cost/download", DownLoadPlanCost)
  43. // 单据批量分配给供应商
  44. r.GETJWT("/plan/alloc/batch", PlanAllocBatch)
  45. }
  46. // 把某个计划的订单批量分配给供应商
  47. // id 为计划id
  48. // /plan/alloc/batch?id=xxx
  49. func PlanAllocBatch(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  50. // ?验证当前账户是否可发送订单
  51. userId, _ := primitive.ObjectIDFromHex(apictx.User.Parent)
  52. user, err1 := getUserById(apictx, userId)
  53. if err1 != nil {
  54. return nil, errors.New("用户错误")
  55. }
  56. if !isSender(user.Roles) {
  57. return nil, errors.New("没有发送权限")
  58. }
  59. _planId := c.Query("id")
  60. planId, err := primitive.ObjectIDFromHex(_planId)
  61. if err != nil {
  62. return nil, errors.New("planId错误")
  63. }
  64. plan := model.ProductPlan{}
  65. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  66. CollectName: repo.CollectionProductPlan,
  67. Query: repo.Map{"_id": planId},
  68. }, &plan)
  69. if !found || err != nil {
  70. return nil, errors.New("数据未找到")
  71. }
  72. // 获取所有stages单据id
  73. billIds := make([]string, 0)
  74. for _, comp := range plan.Pack.Components {
  75. if comp.Id == "" || len(comp.Stages) == 0 {
  76. continue
  77. }
  78. for _, stage := range comp.Stages {
  79. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  80. if !billId.IsZero() {
  81. billIds = append(billIds, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  82. }
  83. }
  84. }
  85. // 去重单据号
  86. typeBillIds := removeDuplicationSort(billIds)
  87. if len(typeBillIds) < 1 {
  88. return nil, errors.New("未找到单据信息")
  89. }
  90. var wg sync.WaitGroup
  91. for _, tId := range typeBillIds {
  92. var err error
  93. billType := ""
  94. tidArr := strings.Split(tId, "_")
  95. // 采购
  96. billId, _ := primitive.ObjectIDFromHex(tidArr[1])
  97. if tidArr[0] == "1" {
  98. billType = PURCHASE_BILL_TYPE
  99. // _, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, billId.Hex(), &model.PurchaseBill{IsSend: true, SendTime: time.Now()})
  100. _, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, billId.Hex(), &model.PurchaseBill{IsSend: true, SendTime: time.Now()}, &repo.RecordLogReq{
  101. Path: c.Request.URL.Path,
  102. UserInfo: user,
  103. TargetId: billId.Hex(),
  104. Type: "send",
  105. })
  106. }
  107. // 工艺
  108. if tidArr[0] == "2" {
  109. billType = PRODUCE_BILL_TYPE
  110. // _, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId.Hex(), &model.ProduceBill{IsSend: true, SendTime: time.Now()})
  111. _, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId.Hex(), &model.ProduceBill{IsSend: true, SendTime: time.Now()}, &repo.RecordLogReq{
  112. Path: c.Request.URL.Path,
  113. UserInfo: user,
  114. TargetId: billId.Hex(),
  115. Type: "send",
  116. })
  117. }
  118. // 成品采购
  119. if tidArr[0] == "3" {
  120. billType = PRODUCT_BILL_TYPE
  121. // _, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduct, billId.Hex(), &model.ProductBill{IsSend: true, SendTime: time.Now()})
  122. _, err = repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionBillProduct, billId.Hex(), &model.ProductBill{IsSend: true, SendTime: time.Now()}, &repo.RecordLogReq{
  123. Path: c.Request.URL.Path,
  124. UserInfo: user,
  125. TargetId: billId.Hex(),
  126. Type: "send",
  127. })
  128. }
  129. if err == nil {
  130. // 给供应商发送通知短信
  131. smsInfo, err := genSupplierSmsTemp(billId, billType, apictx)
  132. fmt.Println(smsInfo)
  133. if err == nil {
  134. wg.Add(1)
  135. go SendSmsNotify(smsInfo.Phone, &SupplierSmsReq{smsInfo.Product, smsInfo.SerialNumber}, &wg)
  136. // err = SendSmsNotify1(smsInfo.Phone, &SupplierSmsReq{smsInfo.Product, smsInfo.SerialNumber})
  137. // fmt.Println(err)
  138. }
  139. }
  140. }
  141. wg.Wait()
  142. return true, nil
  143. }
  144. // 更新供应商确定数量与plan中stage项的同步
  145. func updateStageCount(c *gin.Context, planId primitive.ObjectID, idCounts map[string]int, apictx *ApiSession) (interface{}, error) {
  146. if len(idCounts) == 0 {
  147. return true, nil
  148. }
  149. plan := model.ProductPlan{}
  150. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  151. CollectName: repo.CollectionProductPlan,
  152. Query: repo.Map{"_id": planId},
  153. }, &plan)
  154. if !found || err != nil {
  155. return nil, errors.New("数据未找到")
  156. }
  157. for _, comp := range plan.Pack.Components {
  158. if comp.Id == "" || len(comp.Stages) == 0 {
  159. continue
  160. }
  161. for _, stage := range comp.Stages {
  162. if v, ok := idCounts[stage.Id]; ok {
  163. stage.ConfirmCount = v
  164. }
  165. }
  166. }
  167. plan.UpdateTime = time.Now()
  168. userId, _ := primitive.ObjectIDFromHex(apictx.User.ID)
  169. user, _ := getUserById(apictx, userId)
  170. // return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionProductPlan, planId.Hex(), &plan)
  171. return repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionProductPlan, planId.Hex(), &plan, &repo.RecordLogReq{
  172. Path: c.Request.URL.Path,
  173. UserInfo: user,
  174. TargetId: planId.Hex(),
  175. Type: "sync",
  176. })
  177. }
  178. type SupplierPlanCost struct {
  179. *model.ProductPlan
  180. SupplierId string
  181. }
  182. func DownLoadPlanCost(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  183. _planId := c.Query("id")
  184. _supplierId := c.Query("supplierId")
  185. supplierId, _ := primitive.ObjectIDFromHex(_supplierId)
  186. planId, _ := primitive.ObjectIDFromHex(_planId)
  187. if planId.IsZero() {
  188. return nil, errors.New("planId错误")
  189. }
  190. plan := model.ProductPlan{}
  191. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  192. CollectName: repo.CollectionProductPlan,
  193. Query: repo.Map{"_id": planId},
  194. }, &plan)
  195. if !found || err != nil {
  196. return nil, errors.New("数据未找到")
  197. }
  198. summaryPlans := []*PlanSummary{}
  199. summaryPlan := GetPlanStatus(&plan, apictx)
  200. summaryPlans = append(summaryPlans, summaryPlan)
  201. if len(summaryPlans) < 1 {
  202. return nil, errors.New("数据不存在")
  203. }
  204. f := excelize.NewFile()
  205. index := f.NewSheet("Sheet1")
  206. f.SetActiveSheet(index)
  207. f.SetDefaultFont("宋体")
  208. planSummaryExcel := NewPlanCostExcel(f)
  209. planSummaryExcel.Content = &SupplierPlanSummary{
  210. Plans: summaryPlans,
  211. SupplierId: supplierId,
  212. }
  213. // 绘制表格
  214. planSummaryExcel.Title = fmt.Sprintf("生产成本表(%s)%d盒", plan.Name, plan.Total)
  215. planSummaryExcel.Draws()
  216. c.Header("Content-Type", "application/octet-stream")
  217. c.Header("Content-Disposition", "attachment; filename="+"planCost.xlsx")
  218. c.Header("Content-Transfer-Encoding", "binary")
  219. err = f.Write(c.Writer)
  220. if err != nil {
  221. return nil, err
  222. }
  223. return nil, nil
  224. }
  225. func DownLoadCompBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  226. _planId := c.Query("id")
  227. compId := c.Query("compId")
  228. planId, _ := primitive.ObjectIDFromHex(_planId)
  229. if planId.IsZero() {
  230. return nil, errors.New("planId错误")
  231. }
  232. if len(compId) < 1 {
  233. return nil, errors.New("planId错误")
  234. }
  235. plan := model.ProductPlan{}
  236. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  237. CollectName: repo.CollectionProductPlan,
  238. Query: repo.Map{"_id": planId},
  239. }, &plan)
  240. if !found || err != nil {
  241. return nil, errors.New("数据未找到")
  242. }
  243. compBills := make([]string, 0)
  244. compNameId := ""
  245. for _, comp := range plan.Pack.Components {
  246. if comp.Id == "" || len(comp.Stages) == 0 {
  247. continue
  248. }
  249. if compId == comp.Id {
  250. compNameId = fmt.Sprintf("%s_%s", comp.Name, compId)
  251. for _, stage := range comp.Stages {
  252. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  253. if !billId.IsZero() {
  254. compBills = append(compBills, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  255. }
  256. }
  257. }
  258. }
  259. if len(compBills) < 1 {
  260. return nil, errors.New("数据未找到")
  261. }
  262. companyName := getCompanyName(apictx)
  263. typeBillIds := removeDuplicationSort(compBills)
  264. if len(typeBillIds) < 1 {
  265. return nil, errors.New("未找到单据信息")
  266. }
  267. f := excelize.NewFile()
  268. f.SetDefaultFont("宋体")
  269. flagIndex := -1
  270. // 采购 加工 加工-印刷 加工-覆膜 成品采购
  271. typeRows := []int{0, 0, 0, 0, 0}
  272. for _, tId := range typeBillIds {
  273. tidArr := strings.Split(tId, "_")
  274. var billExcel IExcel
  275. // 采购
  276. billId, _ := primitive.ObjectIDFromHex(tidArr[1])
  277. if tidArr[0] == "1" {
  278. purchase := model.PurchaseBill{}
  279. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  280. CollectName: repo.CollectionBillPurchase,
  281. Query: repo.Map{"_id": billId},
  282. }, &purchase)
  283. if !found {
  284. continue
  285. }
  286. sheetName := "采购单"
  287. index := f.NewSheet(sheetName)
  288. if flagIndex < 0 {
  289. flagIndex = index
  290. }
  291. // index := f.NewSheet("采购单")
  292. // f.SetActiveSheet(index)
  293. billExcel = NewPurchaseBill(f)
  294. billExcel.SetSheetName(sheetName)
  295. if purchase.Reviewed == 1 {
  296. if len(purchase.SignUsers) > 0 {
  297. signs := []*model.Signature{}
  298. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  299. CollectName: repo.CollectionSignature,
  300. Query: repo.Map{"_id": bson.M{"$in": purchase.SignUsers}},
  301. Sort: bson.M{"sort": 1},
  302. }, &signs)
  303. billExcel.SetSignatures(signs)
  304. }
  305. }
  306. billExcel.SetContent(&purchase)
  307. billExcel.SetTitle(fmt.Sprintf("%s原材料采购单", companyName))
  308. billExcel.SetRow(typeRows[0])
  309. billExcel.Draws()
  310. typeRows[0] = billExcel.GetRow() + 5
  311. }
  312. // 工艺
  313. if tidArr[0] == "2" {
  314. produce := model.ProduceBill{}
  315. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  316. CollectName: repo.CollectionBillProduce,
  317. Query: repo.Map{"_id": billId},
  318. }, &produce)
  319. if !found {
  320. continue
  321. }
  322. sheetName := "加工单"
  323. if produce.IsPrint {
  324. sheetName = "加工单-印刷"
  325. } else if produce.IsLam {
  326. sheetName = "加工单-覆膜"
  327. }
  328. index := f.NewSheet(sheetName)
  329. if flagIndex < 0 {
  330. flagIndex = index
  331. }
  332. billExcel = NewProduceBill(f)
  333. billExcel.SetSheetName(sheetName)
  334. if produce.Reviewed == 1 {
  335. if len(produce.SignUsers) > 0 {
  336. signs := []*model.Signature{}
  337. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  338. CollectName: repo.CollectionSignature,
  339. Query: repo.Map{"_id": bson.M{"$in": produce.SignUsers}},
  340. Sort: bson.M{"sort": 1},
  341. }, &signs)
  342. billExcel.SetSignatures(signs)
  343. }
  344. }
  345. billExcel.SetContent(&produce)
  346. billExcel.SetTitle(fmt.Sprintf("%s加工单", companyName))
  347. if produce.IsPrint {
  348. billExcel.SetRow(typeRows[2])
  349. billExcel.Draws()
  350. typeRows[2] = billExcel.GetRow() + 5
  351. } else if produce.IsLam {
  352. billExcel.SetRow(typeRows[3])
  353. billExcel.Draws()
  354. typeRows[3] = billExcel.GetRow() + 5
  355. } else {
  356. billExcel.SetRow(typeRows[1])
  357. billExcel.Draws()
  358. typeRows[1] = billExcel.GetRow() + 5
  359. }
  360. }
  361. // 成品采购
  362. if tidArr[0] == "3" {
  363. product := model.ProductBill{}
  364. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  365. CollectName: repo.CollectionBillProduct,
  366. Query: repo.Map{"_id": billId},
  367. }, &product)
  368. if !found {
  369. continue
  370. }
  371. sheetName := "成品采购单"
  372. index := f.NewSheet(sheetName)
  373. if flagIndex < 0 {
  374. flagIndex = index
  375. }
  376. billExcel = NewProductBill(f)
  377. billExcel.SetSheetName(sheetName)
  378. if product.Reviewed == 1 {
  379. if len(product.SignUsers) > 0 {
  380. signs := []*model.Signature{}
  381. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  382. CollectName: repo.CollectionSignature,
  383. Query: repo.Map{"_id": bson.M{"$in": product.SignUsers}},
  384. Sort: bson.M{"sort": 1},
  385. }, &signs)
  386. billExcel.SetSignatures(signs)
  387. }
  388. }
  389. billExcel.SetContent(&product)
  390. billExcel.SetTitle(companyName)
  391. billExcel.SetRow(typeRows[4])
  392. billExcel.Draws()
  393. typeRows[4] = billExcel.GetRow() + 5
  394. }
  395. }
  396. // 设置活跃sheet
  397. f.SetActiveSheet(flagIndex)
  398. // 删除默认Sheet1
  399. f.DeleteSheet("Sheet1")
  400. c.Header("Content-Type", "application/octet-stream")
  401. c.Header("Content-Disposition", "attachment; filename="+fmt.Sprintf("%s.xlsx", compNameId))
  402. c.Header("Content-Transfer-Encoding", "binary")
  403. f.Write(c.Writer)
  404. return nil, nil
  405. }
  406. func DownLoadPlanBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  407. _planId := c.Query("id")
  408. planId, err := primitive.ObjectIDFromHex(_planId)
  409. if err != nil {
  410. return nil, errors.New("planId错误")
  411. }
  412. plan := model.ProductPlan{}
  413. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  414. CollectName: repo.CollectionProductPlan,
  415. Query: repo.Map{"_id": planId},
  416. }, &plan)
  417. if !found || err != nil {
  418. return nil, errors.New("数据未找到")
  419. }
  420. // 获取组件中的单据并分工序排列
  421. // 获取所有stages单据id
  422. // billIds := make([]string, 0)
  423. type billIds []string
  424. compBillsMap := make(map[string]billIds, 0)
  425. for _, comp := range plan.Pack.Components {
  426. if comp.Id == "" || len(comp.Stages) == 0 {
  427. continue
  428. }
  429. // 唯一组价名,拼上id是因为防止可能有多个相同组件名
  430. compNameId := fmt.Sprintf("%s_%s", comp.Name, comp.Id)
  431. for _, stage := range comp.Stages {
  432. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  433. if !billId.IsZero() {
  434. compBillsMap[compNameId] = append(compBillsMap[compNameId], fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  435. // billIds = append(billIds, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  436. }
  437. }
  438. }
  439. if len(compBillsMap) < 1 {
  440. return nil, errors.New("数据未找到")
  441. }
  442. companyName := getCompanyName(apictx)
  443. _planName := plan.Name
  444. r := regexp.MustCompile(`/`)
  445. planName := r.ReplaceAllString(_planName, `&`)
  446. // fmt.Println(planName)
  447. // 打包pdf的缓存目录
  448. saveTmpDir := fmt.Sprintf("tmp1/excel/%s", planName)
  449. if isExistDir(saveTmpDir) {
  450. os.RemoveAll(saveTmpDir)
  451. }
  452. for compNameId, billIds := range compBillsMap {
  453. // 去重单据号
  454. typeBillIds := removeDuplicationSort(billIds)
  455. if len(typeBillIds) < 1 {
  456. return nil, errors.New("未找到单据信息")
  457. }
  458. f := excelize.NewFile()
  459. f.SetDefaultFont("宋体")
  460. flagIndex := -1
  461. // 采购 加工 加工-印刷 加工-覆膜 成品采购
  462. typeRows := []int{0, 0, 0, 0, 0}
  463. for _, tId := range typeBillIds {
  464. tidArr := strings.Split(tId, "_")
  465. var billExcel IExcel
  466. // 采购
  467. billId, _ := primitive.ObjectIDFromHex(tidArr[1])
  468. if tidArr[0] == "1" {
  469. purchase := model.PurchaseBill{}
  470. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  471. CollectName: repo.CollectionBillPurchase,
  472. Query: repo.Map{"_id": billId},
  473. }, &purchase)
  474. if !found {
  475. continue
  476. }
  477. sheetName := "采购单"
  478. index := f.NewSheet(sheetName)
  479. if flagIndex < 0 {
  480. flagIndex = index
  481. }
  482. // index := f.NewSheet("采购单")
  483. // f.SetActiveSheet(index)
  484. billExcel = NewPurchaseBill(f)
  485. billExcel.SetSheetName(sheetName)
  486. if purchase.Reviewed == 1 {
  487. if len(purchase.SignUsers) > 0 {
  488. signs := []*model.Signature{}
  489. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  490. CollectName: repo.CollectionSignature,
  491. Query: repo.Map{"_id": bson.M{"$in": purchase.SignUsers}},
  492. Sort: bson.M{"sort": 1},
  493. }, &signs)
  494. billExcel.SetSignatures(signs)
  495. }
  496. }
  497. billExcel.SetContent(&purchase)
  498. billExcel.SetTitle(fmt.Sprintf("%s原材料采购单", companyName))
  499. billExcel.SetRow(typeRows[0])
  500. billExcel.Draws()
  501. typeRows[0] = billExcel.GetRow() + 5
  502. }
  503. // 工艺
  504. if tidArr[0] == "2" {
  505. produce := model.ProduceBill{}
  506. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  507. CollectName: repo.CollectionBillProduce,
  508. Query: repo.Map{"_id": billId},
  509. }, &produce)
  510. if !found {
  511. continue
  512. }
  513. sheetName := "加工单"
  514. if produce.IsPrint {
  515. sheetName = "加工单-印刷"
  516. } else if produce.IsLam {
  517. sheetName = "加工单-覆膜"
  518. }
  519. index := f.NewSheet(sheetName)
  520. if flagIndex < 0 {
  521. flagIndex = index
  522. }
  523. billExcel = NewProduceBill(f)
  524. billExcel.SetSheetName(sheetName)
  525. if produce.Reviewed == 1 {
  526. if len(produce.SignUsers) > 0 {
  527. signs := []*model.Signature{}
  528. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  529. CollectName: repo.CollectionSignature,
  530. Query: repo.Map{"_id": bson.M{"$in": produce.SignUsers}},
  531. Sort: bson.M{"sort": 1},
  532. }, &signs)
  533. billExcel.SetSignatures(signs)
  534. }
  535. }
  536. billExcel.SetContent(&produce)
  537. billExcel.SetTitle(fmt.Sprintf("%s加工单", companyName))
  538. if produce.IsPrint {
  539. billExcel.SetRow(typeRows[2])
  540. billExcel.Draws()
  541. typeRows[2] = billExcel.GetRow() + 5
  542. } else if produce.IsLam {
  543. billExcel.SetRow(typeRows[3])
  544. billExcel.Draws()
  545. typeRows[3] = billExcel.GetRow() + 5
  546. } else {
  547. billExcel.SetRow(typeRows[1])
  548. billExcel.Draws()
  549. typeRows[1] = billExcel.GetRow() + 5
  550. }
  551. }
  552. // 成品采购
  553. if tidArr[0] == "3" {
  554. product := model.ProductBill{}
  555. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  556. CollectName: repo.CollectionBillProduct,
  557. Query: repo.Map{"_id": billId},
  558. }, &product)
  559. if !found {
  560. continue
  561. }
  562. sheetName := "成品采购单"
  563. index := f.NewSheet(sheetName)
  564. if flagIndex < 0 {
  565. flagIndex = index
  566. }
  567. billExcel = NewProductBill(f)
  568. billExcel.SetSheetName(sheetName)
  569. if product.Reviewed == 1 {
  570. if len(product.SignUsers) > 0 {
  571. signs := []*model.Signature{}
  572. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  573. CollectName: repo.CollectionSignature,
  574. Query: repo.Map{"_id": bson.M{"$in": product.SignUsers}},
  575. Sort: bson.M{"sort": 1},
  576. }, &signs)
  577. billExcel.SetSignatures(signs)
  578. }
  579. }
  580. billExcel.SetContent(&product)
  581. billExcel.SetTitle(companyName)
  582. billExcel.SetRow(typeRows[4])
  583. billExcel.Draws()
  584. typeRows[4] = billExcel.GetRow() + 5
  585. }
  586. }
  587. // 设置活跃sheet
  588. f.SetActiveSheet(flagIndex)
  589. // 删除默认Sheet1
  590. f.DeleteSheet("Sheet1")
  591. buf, _ := f.WriteToBuffer()
  592. targeEXcelName := fmt.Sprintf("%s.xlsx", compNameId)
  593. err := savePdfToTmp(saveTmpDir, targeEXcelName, buf.Bytes())
  594. if err != nil {
  595. fmt.Println("保存文件失败!")
  596. return nil, err
  597. }
  598. }
  599. c.Header("Content-Type", "application/octet-stream")
  600. c.Header("Content-Disposition", "attachment; filename="+fmt.Sprintf("%s-execl.zip", planName))
  601. c.Header("Content-Transfer-Encoding", "binary")
  602. archive := zip.NewWriter(c.Writer)
  603. defer archive.Close()
  604. // 遍历路径信息
  605. filepath.Walk(saveTmpDir, func(path string, info os.FileInfo, _ error) error {
  606. // 如果是源路径,提前进行下一个遍历
  607. if path == saveTmpDir {
  608. return nil
  609. }
  610. // 获取:文件头信息
  611. header, _ := zip.FileInfoHeader(info)
  612. header.Name = strings.TrimPrefix(path, saveTmpDir+`/`)
  613. // 判断:文件是不是文件夹
  614. if info.IsDir() {
  615. header.Name += `/`
  616. } else {
  617. // 设置:zip的文件压缩算法
  618. header.Method = zip.Deflate
  619. }
  620. // 创建:压缩包头部信息
  621. writer, _ := archive.CreateHeader(header)
  622. if !info.IsDir() {
  623. file, _ := os.Open(path)
  624. defer file.Close()
  625. io.Copy(writer, file)
  626. }
  627. return nil
  628. })
  629. // 删除缓存目录
  630. os.RemoveAll(saveTmpDir)
  631. return nil, nil
  632. // http://127.0.0.1:8888/boxcost/bill/plan/download?id=652206412617b328da71655e
  633. // http://127.0.0.1:8888/boxcost/bill/comp/download?id=652206412617b328da71655e&compId=1677034398070
  634. // http://127.0.0.1:8888/boxcost/bill/comp/downloadPdf?id=652206412617b328da71655e&compId=1677034398070
  635. }
  636. func DownLoadPlanBillsPdf(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  637. _planId := c.Query("id")
  638. planId, err := primitive.ObjectIDFromHex(_planId)
  639. if err != nil {
  640. return nil, errors.New("planId错误")
  641. }
  642. plan := model.ProductPlan{}
  643. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  644. CollectName: repo.CollectionProductPlan,
  645. Query: repo.Map{"_id": planId},
  646. }, &plan)
  647. if !found || err != nil {
  648. return nil, errors.New("数据未找到")
  649. }
  650. // 获取所有stages单据id
  651. billIds := make([]string, 0)
  652. for _, comp := range plan.Pack.Components {
  653. if comp.Id == "" || len(comp.Stages) == 0 {
  654. continue
  655. }
  656. for _, stage := range comp.Stages {
  657. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  658. if !billId.IsZero() {
  659. billIds = append(billIds, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  660. }
  661. }
  662. }
  663. if len(billIds) < 1 {
  664. return nil, errors.New("数据未找到")
  665. }
  666. // 去重单据号
  667. typeBillIds := removeDuplicationSort(billIds)
  668. companyName := getCompanyName(apictx)
  669. _planName := plan.Name
  670. r := regexp.MustCompile(`/`)
  671. planName := r.ReplaceAllString(_planName, `&`)
  672. // fmt.Println(planName)
  673. // 打包pdf的缓存目录
  674. saveTmpDir := fmt.Sprintf("tmp1/%s", planName)
  675. if isExistDir(saveTmpDir) {
  676. os.RemoveAll(saveTmpDir)
  677. }
  678. // 记录文件数量
  679. var wg sync.WaitGroup
  680. c1 := make(chan int)
  681. for _, tId := range typeBillIds {
  682. productName := ""
  683. supplierName := ""
  684. serialNumber := ""
  685. f := excelize.NewFile()
  686. index := f.NewSheet("Sheet1")
  687. f.SetActiveSheet(index)
  688. f.SetDefaultFont("宋体")
  689. tidArr := strings.Split(tId, "_")
  690. var billExcel IExcel
  691. // 采购
  692. billId, _ := primitive.ObjectIDFromHex(tidArr[1])
  693. if tidArr[0] == "1" {
  694. purchase := model.PurchaseBill{}
  695. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  696. CollectName: repo.CollectionBillPurchase,
  697. Query: repo.Map{"_id": billId},
  698. }, &purchase)
  699. if !found {
  700. continue
  701. }
  702. billExcel = NewPurchaseBill(f)
  703. if purchase.Reviewed == 1 {
  704. if len(purchase.SignUsers) > 0 {
  705. signs := []*model.Signature{}
  706. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  707. CollectName: repo.CollectionSignature,
  708. Query: repo.Map{"_id": bson.M{"$in": purchase.SignUsers}},
  709. Sort: bson.M{"sort": 1},
  710. }, &signs)
  711. billExcel.SetSignatures(signs)
  712. }
  713. }
  714. productName = purchase.ProductName
  715. supplierName = purchase.Supplier
  716. serialNumber = purchase.SerialNumber
  717. billExcel.SetContent(&purchase)
  718. billExcel.SetTitle(fmt.Sprintf("%s原材料采购单", companyName))
  719. }
  720. // 工艺
  721. if tidArr[0] == "2" {
  722. produce := model.ProduceBill{}
  723. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  724. CollectName: repo.CollectionBillProduce,
  725. Query: repo.Map{"_id": billId},
  726. }, &produce)
  727. if !found {
  728. continue
  729. }
  730. billExcel = NewProduceBill(f)
  731. if produce.Reviewed == 1 {
  732. if len(produce.SignUsers) > 0 {
  733. signs := []*model.Signature{}
  734. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  735. CollectName: repo.CollectionSignature,
  736. Query: repo.Map{"_id": bson.M{"$in": produce.SignUsers}},
  737. Sort: bson.M{"sort": 1},
  738. }, &signs)
  739. billExcel.SetSignatures(signs)
  740. }
  741. }
  742. productName = produce.ProductName
  743. supplierName = produce.Supplier
  744. serialNumber = produce.SerialNumber
  745. billExcel.SetContent(&produce)
  746. billExcel.SetTitle(fmt.Sprintf("%s加工单", companyName))
  747. }
  748. // 成品采购
  749. if tidArr[0] == "3" {
  750. product := model.ProductBill{}
  751. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  752. CollectName: repo.CollectionBillProduct,
  753. Query: repo.Map{"_id": billId},
  754. }, &product)
  755. if !found {
  756. continue
  757. }
  758. billExcel = NewProductBill(f)
  759. if product.Reviewed == 1 {
  760. if len(product.SignUsers) > 0 {
  761. signs := []*model.Signature{}
  762. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  763. CollectName: repo.CollectionSignature,
  764. Query: repo.Map{"_id": bson.M{"$in": product.SignUsers}},
  765. Sort: bson.M{"sort": 1},
  766. }, &signs)
  767. billExcel.SetSignatures(signs)
  768. }
  769. }
  770. productName = product.ProductName
  771. supplierName = product.Supplier
  772. serialNumber = product.SerialNumber
  773. billExcel.SetContent(&product)
  774. billExcel.SetTitle(companyName)
  775. }
  776. billExcel.SetIsPdf("true")
  777. billExcel.Draws()
  778. buf, _ := f.WriteToBuffer()
  779. // r := regexp.MustCompile(`/`)
  780. _productName := r.ReplaceAllString(productName, `&`)
  781. _supplierName := r.ReplaceAllString(supplierName, `&`)
  782. targePdfName := fmt.Sprintf("%s-%s-%s.pdf", _supplierName, _productName, serialNumber)
  783. // fmt.Println(targePdfName)
  784. wg.Add(1)
  785. go toPdfAndSaveTask(buf, apictx.Svc.Conf.PdfApiAddr, saveTmpDir, targePdfName, c1, &wg)
  786. }
  787. go func() {
  788. // 等待所有goroutine
  789. wg.Wait()
  790. // 关闭channel
  791. close(c1)
  792. }()
  793. // channel关闭后结束后停止遍历接收channel中的值
  794. for n := range c1 {
  795. if n == -1 {
  796. return nil, errors.New("下载失败,请重试")
  797. }
  798. }
  799. c.Header("Content-Type", "application/octet-stream")
  800. c.Header("Content-Disposition", "attachment; filename="+planName+".zip")
  801. c.Header("Content-Transfer-Encoding", "binary")
  802. archive := zip.NewWriter(c.Writer)
  803. defer archive.Close()
  804. // 遍历路径信息
  805. filepath.Walk(saveTmpDir, func(path string, info os.FileInfo, _ error) error {
  806. // 如果是源路径,提前进行下一个遍历
  807. if path == saveTmpDir {
  808. return nil
  809. }
  810. // 获取:文件头信息
  811. header, _ := zip.FileInfoHeader(info)
  812. header.Name = strings.TrimPrefix(path, saveTmpDir+`/`)
  813. // 判断:文件是不是文件夹
  814. if info.IsDir() {
  815. header.Name += `/`
  816. } else {
  817. // 设置:zip的文件压缩算法
  818. header.Method = zip.Deflate
  819. }
  820. // 创建:压缩包头部信息
  821. writer, _ := archive.CreateHeader(header)
  822. if !info.IsDir() {
  823. file, _ := os.Open(path)
  824. defer file.Close()
  825. io.Copy(writer, file)
  826. }
  827. return nil
  828. })
  829. // 删除缓存目录
  830. os.RemoveAll(saveTmpDir)
  831. return nil, nil
  832. }
  833. type ToPdfResult struct {
  834. IsSucc bool
  835. Err error
  836. }
  837. func toPdfAndSaveTask(buf *bytes.Buffer, toPdfAddr, saveTmpDir, targetPdfName string, toPdfResult chan<- int, wg *sync.WaitGroup) {
  838. if buf.Len() < 1<<10 {
  839. fmt.Println("execl内容为空")
  840. log.Error("execl内容为空")
  841. toPdfResult <- -1
  842. wg.Done()
  843. return
  844. }
  845. res, err := excelToPdf(buf, toPdfAddr)
  846. if err != nil {
  847. fmt.Println(err)
  848. log.Error(err)
  849. // pdfRes := ToPdfResult{
  850. // IsSucc: false,
  851. // Err: err,
  852. // }
  853. // toPdfResult <- pdfRes
  854. toPdfResult <- -1
  855. wg.Done()
  856. return
  857. }
  858. byteData, err := io.ReadAll(res.Body)
  859. if err != nil {
  860. fmt.Println(err)
  861. // pdfRes := ToPdfResult{
  862. // IsSucc: false,
  863. // Err: err,
  864. // }
  865. // toPdfResult <- pdfRes
  866. toPdfResult <- -1
  867. wg.Done()
  868. return
  869. }
  870. if len(byteData) < 1 {
  871. fmt.Println("pdf内容为空")
  872. log.Error("pdf内容为空")
  873. toPdfResult <- -1
  874. wg.Done()
  875. return
  876. }
  877. defer res.Body.Close()
  878. err = savePdfToTmp(saveTmpDir, targetPdfName, byteData)
  879. if err != nil {
  880. // pdfRes := ToPdfResult{
  881. // IsSucc: false,
  882. // Err: err,
  883. // }
  884. // toPdfResult <- pdfRes
  885. toPdfResult <- -1
  886. wg.Done()
  887. return
  888. }
  889. // pdfRes := ToPdfResult{
  890. // IsSucc: true,
  891. // Err: err,
  892. // }
  893. // toPdfResult <- pdfRes
  894. toPdfResult <- 1
  895. wg.Done()
  896. }
  897. func DownLoadCompBillsPdf(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  898. _planId := c.Query("id")
  899. compId := c.Query("compId")
  900. planId, _ := primitive.ObjectIDFromHex(_planId)
  901. if planId.IsZero() {
  902. return nil, errors.New("planId错误")
  903. }
  904. if len(compId) < 1 {
  905. return nil, errors.New("compId错误")
  906. }
  907. plan := model.ProductPlan{}
  908. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  909. CollectName: repo.CollectionProductPlan,
  910. Query: repo.Map{"_id": planId},
  911. }, &plan)
  912. if !found || err != nil {
  913. return nil, errors.New("数据未找到")
  914. }
  915. // 获取所有stages单据id
  916. billIds := make([]string, 0)
  917. compNameId := ""
  918. for _, comp := range plan.Pack.Components {
  919. if comp.Id == "" || len(comp.Stages) == 0 {
  920. continue
  921. }
  922. if comp.Id == compId {
  923. compNameId = fmt.Sprintf("%s_%s", comp.Name, comp.Id)
  924. for _, stage := range comp.Stages {
  925. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  926. if !billId.IsZero() {
  927. billIds = append(billIds, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  928. }
  929. }
  930. }
  931. }
  932. if len(billIds) < 1 {
  933. return nil, errors.New("数据未找到")
  934. }
  935. // 去重单据号
  936. typeBillIds := removeDuplicationSort(billIds)
  937. companyName := getCompanyName(apictx)
  938. _planName := plan.Name
  939. r := regexp.MustCompile(`/`)
  940. planName := r.ReplaceAllString(_planName, `&`)
  941. // fmt.Println(planName)
  942. // 打包pdf的缓存目录
  943. saveTmpDir := fmt.Sprintf("tmp1/%s/%s", planName, compNameId)
  944. if isExistDir(saveTmpDir) {
  945. os.RemoveAll(saveTmpDir)
  946. }
  947. // 记录文件数量
  948. var wg sync.WaitGroup
  949. c1 := make(chan int)
  950. for _, tId := range typeBillIds {
  951. productName := ""
  952. supplierName := ""
  953. serialNumber := ""
  954. f := excelize.NewFile()
  955. index := f.NewSheet("Sheet1")
  956. f.SetActiveSheet(index)
  957. f.SetDefaultFont("宋体")
  958. tidArr := strings.Split(tId, "_")
  959. var billExcel IExcel
  960. // 采购
  961. billId, _ := primitive.ObjectIDFromHex(tidArr[1])
  962. if tidArr[0] == "1" {
  963. purchase := model.PurchaseBill{}
  964. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  965. CollectName: repo.CollectionBillPurchase,
  966. Query: repo.Map{"_id": billId},
  967. }, &purchase)
  968. if !found {
  969. continue
  970. }
  971. billExcel = NewPurchaseBill(f)
  972. if purchase.Reviewed == 1 {
  973. if len(purchase.SignUsers) > 0 {
  974. signs := []*model.Signature{}
  975. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  976. CollectName: repo.CollectionSignature,
  977. Query: repo.Map{"_id": bson.M{"$in": purchase.SignUsers}},
  978. Sort: bson.M{"sort": 1},
  979. }, &signs)
  980. billExcel.SetSignatures(signs)
  981. }
  982. }
  983. productName = purchase.ProductName
  984. supplierName = purchase.Supplier
  985. serialNumber = purchase.SerialNumber
  986. billExcel.SetContent(&purchase)
  987. billExcel.SetTitle(fmt.Sprintf("%s原材料采购单", companyName))
  988. }
  989. // 工艺
  990. if tidArr[0] == "2" {
  991. produce := model.ProduceBill{}
  992. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  993. CollectName: repo.CollectionBillProduce,
  994. Query: repo.Map{"_id": billId},
  995. }, &produce)
  996. if !found {
  997. continue
  998. }
  999. billExcel = NewProduceBill(f)
  1000. if produce.Reviewed == 1 {
  1001. if len(produce.SignUsers) > 0 {
  1002. signs := []*model.Signature{}
  1003. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  1004. CollectName: repo.CollectionSignature,
  1005. Query: repo.Map{"_id": bson.M{"$in": produce.SignUsers}},
  1006. Sort: bson.M{"sort": 1},
  1007. }, &signs)
  1008. billExcel.SetSignatures(signs)
  1009. }
  1010. }
  1011. productName = produce.ProductName
  1012. supplierName = produce.Supplier
  1013. serialNumber = produce.SerialNumber
  1014. billExcel.SetContent(&produce)
  1015. billExcel.SetTitle(fmt.Sprintf("%s加工单", companyName))
  1016. }
  1017. // 成品采购
  1018. if tidArr[0] == "3" {
  1019. product := model.ProductBill{}
  1020. found, _ := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  1021. CollectName: repo.CollectionBillProduct,
  1022. Query: repo.Map{"_id": billId},
  1023. }, &product)
  1024. if !found {
  1025. continue
  1026. }
  1027. billExcel = NewProductBill(f)
  1028. if product.Reviewed == 1 {
  1029. if len(product.SignUsers) > 0 {
  1030. signs := []*model.Signature{}
  1031. repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  1032. CollectName: repo.CollectionSignature,
  1033. Query: repo.Map{"_id": bson.M{"$in": product.SignUsers}},
  1034. Sort: bson.M{"sort": 1},
  1035. }, &signs)
  1036. billExcel.SetSignatures(signs)
  1037. }
  1038. }
  1039. productName = product.ProductName
  1040. supplierName = product.Supplier
  1041. serialNumber = product.SerialNumber
  1042. billExcel.SetContent(&product)
  1043. billExcel.SetTitle(companyName)
  1044. }
  1045. billExcel.SetIsPdf("true")
  1046. billExcel.Draws()
  1047. buf, _ := f.WriteToBuffer()
  1048. // r := regexp.MustCompile(`/`)
  1049. _productName := r.ReplaceAllString(productName, `&`)
  1050. _supplierName := r.ReplaceAllString(supplierName, `&`)
  1051. targePdfName := fmt.Sprintf("%s-%s-%s.pdf", _supplierName, _productName, serialNumber)
  1052. // fmt.Println(targePdfName)
  1053. wg.Add(1)
  1054. go toPdfAndSaveTask(buf, apictx.Svc.Conf.PdfApiAddr, saveTmpDir, targePdfName, c1, &wg)
  1055. }
  1056. go func() {
  1057. // 等待所有goroutine
  1058. wg.Wait()
  1059. // 关闭channel
  1060. close(c1)
  1061. }()
  1062. // channel关闭后结束后停止遍历接收channel中的值
  1063. for n := range c1 {
  1064. if n == -1 {
  1065. return nil, errors.New("下载失败,请重试")
  1066. }
  1067. }
  1068. c.Header("Content-Type", "application/octet-stream")
  1069. c.Header("Content-Disposition", "attachment; filename="+fmt.Sprintf("%s.zip", compNameId))
  1070. c.Header("Content-Transfer-Encoding", "binary")
  1071. archive := zip.NewWriter(c.Writer)
  1072. defer archive.Close()
  1073. // 遍历路径信息
  1074. filepath.Walk(saveTmpDir, func(path string, info os.FileInfo, _ error) error {
  1075. // 如果是源路径,提前进行下一个遍历
  1076. if path == saveTmpDir {
  1077. return nil
  1078. }
  1079. // 获取:文件头信息
  1080. header, _ := zip.FileInfoHeader(info)
  1081. header.Name = strings.TrimPrefix(path, saveTmpDir+`/`)
  1082. // 判断:文件是不是文件夹
  1083. if info.IsDir() {
  1084. header.Name += `/`
  1085. } else {
  1086. // 设置:zip的文件压缩算法
  1087. header.Method = zip.Deflate
  1088. }
  1089. // 创建:压缩包头部信息
  1090. writer, _ := archive.CreateHeader(header)
  1091. if !info.IsDir() {
  1092. file, _ := os.Open(path)
  1093. defer file.Close()
  1094. io.Copy(writer, file)
  1095. }
  1096. return nil
  1097. })
  1098. // 删除缓存目录
  1099. os.RemoveAll(saveTmpDir)
  1100. return nil, nil
  1101. }
  1102. // 创建生产计划
  1103. func CreateProductPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  1104. var plan model.ProductPlan
  1105. err := c.ShouldBindJSON(&plan)
  1106. if err != nil {
  1107. fmt.Println(err)
  1108. return nil, errors.New("参数错误!")
  1109. }
  1110. if plan.Name == "" {
  1111. return nil, errors.New("生产计划名为空")
  1112. }
  1113. if plan.Total == 0 {
  1114. return nil, errors.New("生产计划数应不为0")
  1115. }
  1116. if plan.TotalPrice == nil {
  1117. var zero float64 = 0
  1118. plan.TotalPrice = &zero
  1119. }
  1120. plan.Status = "process" // 进行中
  1121. plan.CreateTime = time.Now()
  1122. plan.UpdateTime = time.Now()
  1123. userId, _ := primitive.ObjectIDFromHex(apictx.User.ID)
  1124. userInfo, _ := getUserById(apictx, userId)
  1125. result, err := repo.RepoAddDoc1(apictx.CreateRepoCtx(), repo.CollectionProductPlan, &plan, &repo.RecordLogReq{
  1126. Path: c.Request.URL.Path,
  1127. UserInfo: userInfo,
  1128. TargetId: "",
  1129. Type: "created",
  1130. })
  1131. return result, err
  1132. }
  1133. // 获取生产计划信息
  1134. func GetProductPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  1135. planId := c.Param("id")
  1136. id, err := primitive.ObjectIDFromHex(planId)
  1137. if err != nil {
  1138. return nil, errors.New("非法id")
  1139. }
  1140. var plan model.ProductPlan
  1141. option := &repo.DocSearchOptions{
  1142. CollectName: repo.CollectionProductPlan,
  1143. Query: repo.Map{"_id": id},
  1144. }
  1145. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &plan)
  1146. if !found || err != nil {
  1147. log.Info(err)
  1148. return nil, errors.New("数据未找到")
  1149. }
  1150. billData := map[string]interface{}{}
  1151. if plan.Pack != nil && plan.Pack.Components != nil {
  1152. for _, comp := range plan.Pack.Components {
  1153. if comp.Stages != nil {
  1154. for _, stage := range comp.Stages {
  1155. if len(stage.BillId) > 0 {
  1156. collectName := ""
  1157. // 材料
  1158. if stage.BillType == 1 {
  1159. collectName = repo.CollectionBillPurchase
  1160. }
  1161. // 工艺
  1162. if stage.BillType == 2 {
  1163. collectName = repo.CollectionBillProduce
  1164. }
  1165. // 成品
  1166. if stage.BillType == 3 {
  1167. collectName = repo.CollectionBillProduct
  1168. }
  1169. ok, state := repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  1170. CollectName: collectName,
  1171. Query: repo.Map{"_id": stage.BillId},
  1172. // Project: []string{"status", "isSend", "reviewed", "isAck", "serialNumber", "sendTo", "remark"}
  1173. })
  1174. if ok {
  1175. billData[stage.BillId] = state
  1176. }
  1177. }
  1178. }
  1179. }
  1180. }
  1181. }
  1182. return map[string]interface{}{
  1183. "plan": plan,
  1184. "billData": billData,
  1185. }, nil
  1186. }
  1187. // 获取生产计划列表
  1188. func GetProductPlans(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  1189. page, size, query := UtilQueryPageSize(c)
  1190. if _packId, ok := query["packId"]; ok {
  1191. packId, _ := primitive.ObjectIDFromHex(_packId.(string))
  1192. query["pack._id"] = packId
  1193. delete(query, "packId")
  1194. }
  1195. if _name, ok := query["name"]; ok {
  1196. delete(query, "name")
  1197. query["name"] = bson.M{"$regex": _name.(string)}
  1198. }
  1199. option := &repo.PageSearchOptions{
  1200. CollectName: repo.CollectionProductPlan,
  1201. Query: query,
  1202. Page: page,
  1203. Size: size,
  1204. Sort: bson.M{"createTime": -1},
  1205. Project: []string{"_id", "thumbnail", "name", "updateTime", "createTime", "createUser", "total", "totalPrice", "status"},
  1206. }
  1207. return repo.RepoPageSearch(apictx.CreateRepoCtx(), option)
  1208. }
  1209. // 更新生产计划
  1210. func UpdateProductPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  1211. var plan model.ProductPlan
  1212. err := c.ShouldBindJSON(&plan)
  1213. if err != nil {
  1214. fmt.Println(err)
  1215. log.Error(err)
  1216. return nil, errors.New("参数错误")
  1217. }
  1218. if plan.Id.Hex() == "" {
  1219. return nil, errors.New("id的为空")
  1220. }
  1221. plan.UpdateTime = time.Now()
  1222. userId, _ := primitive.ObjectIDFromHex(apictx.User.ID)
  1223. user, _ := getUserById(apictx, userId)
  1224. // return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionProductPlan, plan.Id.Hex(), &plan)
  1225. return repo.RepoUpdateSetDoc1(apictx.CreateRepoCtx(), repo.CollectionProductPlan, plan.Id.Hex(), &plan, &repo.RecordLogReq{
  1226. Path: c.Request.URL.Path,
  1227. UserInfo: user,
  1228. TargetId: plan.Id.Hex(),
  1229. Type: "update",
  1230. })
  1231. }
  1232. // 删除生产计划
  1233. func DelProductPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  1234. userId, _ := primitive.ObjectIDFromHex(apictx.User.Parent)
  1235. if userId.IsZero() {
  1236. return nil, errors.New("用户错误,请重新登录")
  1237. }
  1238. _planId := c.Param("id")
  1239. planId, _ := primitive.ObjectIDFromHex(_planId)
  1240. if planId.IsZero() {
  1241. return nil, errors.New("计划id错误")
  1242. }
  1243. plan := model.ProductPlan{}
  1244. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  1245. CollectName: repo.CollectionProductPlan,
  1246. Query: repo.Map{"_id": planId},
  1247. }, &plan)
  1248. if !found || err != nil {
  1249. return nil, errors.New("计划数据未找到")
  1250. }
  1251. res, err := repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionProductPlan, _planId)
  1252. // 删除计划对应订单
  1253. if err == nil {
  1254. // 获取所有stages单据id
  1255. billIds := make([]string, 0)
  1256. for _, comp := range plan.Pack.Components {
  1257. if comp.Id == "" || len(comp.Stages) == 0 {
  1258. continue
  1259. }
  1260. for _, stage := range comp.Stages {
  1261. billId, _ := primitive.ObjectIDFromHex(stage.BillId)
  1262. if !billId.IsZero() {
  1263. billIds = append(billIds, fmt.Sprintf("%d_%s", stage.BillType, stage.BillId))
  1264. }
  1265. }
  1266. }
  1267. // 去重单据号
  1268. typeBillIds := removeDuplicationSort(billIds)
  1269. if len(typeBillIds) < 1 {
  1270. return res, err
  1271. }
  1272. for _, tId := range typeBillIds {
  1273. tidArr := strings.Split(tId, "_")
  1274. // 采购
  1275. if tidArr[0] == "1" {
  1276. repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillPurchase, tidArr[1])
  1277. }
  1278. // 工艺
  1279. if tidArr[0] == "2" {
  1280. repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, tidArr[1])
  1281. }
  1282. // 成品采购
  1283. if tidArr[0] == "3" {
  1284. repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduct, tidArr[1])
  1285. }
  1286. }
  1287. }
  1288. return res, err
  1289. }