plan.go 42 KB

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