plan.go 42 KB

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