plan.go 39 KB

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