plan.go 42 KB

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