plan.go 42 KB

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