plan.go 43 KB

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