liwei 2 years ago
parent
commit
2b54dad65b

+ 250 - 0
boxcost/api/bill-produce-excel.go

@@ -0,0 +1,250 @@
+package api
+
+import (
+	"fmt"
+
+	"github.com/xuri/excelize/v2"
+)
+
+type ProduceBillExcel struct {
+	Offset int
+
+	Title string //标题
+
+	Excel *excelize.File
+
+	SheetName string
+
+	AlignCenterStyle int
+}
+
+func (b *ProduceBillExcel) drawTitle() error {
+	tileIndex := b.Offset + 1
+	startCell := fmt.Sprintf("A%d", tileIndex)
+	err := b.Excel.MergeCell(b.SheetName, startCell, fmt.Sprintf("I%d", tileIndex))
+	if err != nil {
+		return err
+	}
+
+	style, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
+		Font:      &excelize.Font{Bold: true, Size: 18}})
+	if err != nil {
+		return err
+	}
+	err = b.Excel.SetCellStyle(b.SheetName, startCell, startCell, style)
+	if err != nil {
+		return err
+	}
+	b.Excel.SetRowHeight(b.SheetName, tileIndex, 23)
+	b.Excel.SetCellValue(b.SheetName, startCell, b.Title)
+	return nil
+}
+
+func (b *ProduceBillExcel) drawSubTitles() error {
+
+	row := b.Offset + 2
+
+	styleLeft, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
+		Font:      &excelize.Font{Size: 11}})
+	if err != nil {
+		return err
+	}
+	styleRight, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "right", Vertical: "center"},
+		Font:      &excelize.Font{Size: 11}})
+	if err != nil {
+		return err
+	}
+
+	var drawLeft = func(rowIndex int, value string) error {
+		//左边1
+		left1Cell := fmt.Sprintf("A%d", rowIndex)
+		err = b.Excel.MergeCell(b.SheetName, left1Cell, fmt.Sprintf("E%d", rowIndex))
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, left1Cell, value)
+		return nil
+	}
+
+	var drawRight = func(rowIndex int, value string) error {
+		right1Cell := fmt.Sprintf("F%d", rowIndex)
+		err = b.Excel.MergeCell(b.SheetName, right1Cell, fmt.Sprintf("I%d", rowIndex))
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, right1Cell, right1Cell, styleRight)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, right1Cell, value)
+		return nil
+	}
+
+	//第一行
+	drawLeft(row, "类别:纸张类")
+	drawRight(row, "单号:ZZL-000003")
+	b.Excel.SetRowHeight(b.SheetName, row, 21)
+
+	//第二行
+	drawLeft(row+1, "供应商名称:正大文博")
+	drawRight(row+1, "下单时间:2022年12月07号 19:17:27")
+	b.Excel.SetRowHeight(b.SheetName, row+1, 21)
+
+	//第三行
+	drawLeft(row+2, "产品名称:测试3000盒-3333")
+	drawRight(row+2, "")
+	b.Excel.SetRowHeight(b.SheetName, row+2, 21)
+
+	return nil
+}
+
+func (b *ProduceBillExcel) drawTableTitle() error {
+	row := b.Offset + 5
+
+	//A加工项目 B规格(克) 尺寸C-D 数量E 单价F-G 交货时间H 备注I
+	var drawCol = func(prefix string, value string) error {
+		left1Cell := fmt.Sprintf("%s%d", prefix, row)
+		left2Cell := fmt.Sprintf("%s%d", prefix, row+1)
+
+		err := b.Excel.MergeCell(b.SheetName, left1Cell, left2Cell)
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left2Cell, b.AlignCenterStyle)
+		if err != nil {
+			return err
+		}
+
+		return b.Excel.SetCellValue(b.SheetName, left1Cell, value)
+	}
+
+	var drawCol2 = func(prefix string, value1 string, value2 string) error {
+
+		left1Cell := fmt.Sprintf("%s%d", prefix, row)
+		left2Cell := fmt.Sprintf("%s%d", prefix, row+1)
+		err := b.Excel.SetCellStyle(b.SheetName, left1Cell, left2Cell, b.AlignCenterStyle)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, left1Cell, value1)
+		b.Excel.SetCellValue(b.SheetName, left2Cell, value2)
+		return nil
+	}
+
+	drawCol("A", "加工项目")
+	drawCol("B", "规格")
+	drawCol("C", "纸张")
+	drawCol("D", "来纸尺寸")
+	drawCol("E", "印刷尺寸")
+	drawCol("F", "数量")
+	drawCol("H", "交货时间")
+	drawCol("I", "备注")
+	drawCol2("G", "单价", "元/张")
+	return nil
+}
+
+func (b *ProduceBillExcel) drawTableContent() error {
+	row := b.Offset + 7
+
+	var DrawRow = func(rowIndex int, values ...string) {
+		charas := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I"}
+		for i, c := range charas {
+			v := ""
+			if i < len(values) {
+				v = values[i]
+			}
+			b.Excel.SetCellValue(b.SheetName, fmt.Sprintf("%s%d", c, rowIndex), v)
+			val2Cel := fmt.Sprintf("%s%d", c, rowIndex)
+			b.Excel.SetCellStyle(b.SheetName, val2Cel, val2Cel, b.AlignCenterStyle)
+
+			b.Excel.SetRowHeight(b.SheetName, rowIndex, 21)
+		}
+	}
+	DrawRow(row, "单色印刷", "按文件要求", "太阳白卡", "0*0", "0*0", "3000", "400", "2022-12-07", "")
+	DrawRow(row + 1)
+	DrawRow(row + 2)
+
+	return nil
+}
+
+func (b *ProduceBillExcel) drawTableFooter() error {
+	row := b.Offset + 10
+
+	left1Cell := fmt.Sprintf("A%d", row)
+
+	border := []excelize.Border{
+		{Type: "top", Style: 1, Color: "000000"},
+		{Type: "left", Style: 1, Color: "000000"},
+		{Type: "right", Style: 1, Color: "000000"},
+		{Type: "bottom", Style: 1, Color: "000000"},
+	}
+
+	styleLeft, _ := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
+		Border:    border,
+	})
+
+	b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
+	b.Excel.SetCellValue(b.SheetName, left1Cell, "送货地址")
+
+	addCel := fmt.Sprintf("B%d", row)
+
+	b.Excel.MergeCell(b.SheetName, addCel, fmt.Sprintf("E%d", row))
+	b.Excel.SetCellStyle(b.SheetName, addCel, fmt.Sprintf("E%d", row), styleLeft)
+	b.Excel.SetCellValue(b.SheetName, addCel, "崇州泗潍路333号--联系电话13882239198")
+
+	sureCel := fmt.Sprintf("F%d", row)
+	b.Excel.MergeCell(b.SheetName, sureCel, fmt.Sprintf("I%d", row))
+	b.Excel.SetCellStyle(b.SheetName, sureCel, fmt.Sprintf("I%d", row), styleLeft)
+	b.Excel.SetCellValue(b.SheetName, sureCel, "供应商签字:")
+
+	b.Excel.SetRowHeight(b.SheetName, row, 21)
+
+	return nil
+}
+
+func (b *ProduceBillExcel) Draws() {
+	b.drawTitle()
+	b.drawSubTitles()
+	b.drawTableTitle()
+	b.drawTableContent()
+	b.drawTableFooter()
+}
+
+func NewProduceBill(f *excelize.File) *ProduceBillExcel {
+
+	border := []excelize.Border{
+		{Type: "top", Style: 1, Color: "000000"},
+		{Type: "left", Style: 1, Color: "000000"},
+		{Type: "right", Style: 1, Color: "000000"},
+		{Type: "bottom", Style: 1, Color: "000000"},
+	}
+
+	styleLeft, _ := f.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
+		Border:    border,
+	})
+
+	b := &ProduceBillExcel{
+		Title:            "中鱼互动加工单",
+		SheetName:        "Sheet1",
+		Excel:            f,
+		Offset:           0,
+		AlignCenterStyle: styleLeft,
+	}
+
+	f.SetColWidth(b.SheetName, "A", "A", 17)
+	f.SetColWidth(b.SheetName, "B", "B", 13)
+	f.SetColWidth(b.SheetName, "C", "G", 9.5)
+	f.SetColWidth(b.SheetName, "H", "I", 12)
+	f.SetPageMargins(b.SheetName, excelize.PageMarginTop(0), excelize.PageMarginLeft(0), excelize.PageMarginRight(0))
+
+	return b
+}

+ 47 - 0
boxcost/api/bill-produce.go

@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/gin-gonic/gin"
+	"github.com/xuri/excelize/v2"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
@@ -30,6 +31,9 @@ func BillProduce(r *GinRouter) {
 
 	// 删除单据
 	r.POST("/bill/produce/delete/:id", DelProduceBill)
+
+	//下载单据
+	r.GET("/bill/produce/download", DownProduceBill)
 }
 
 // 创建生产加工单据
@@ -147,3 +151,46 @@ func DelProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 
 	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBillProduce, billId)
 }
+
+func DownProduceBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	billId := c.Query("id")
+	if len(billId) < 1 {
+		return nil, fmt.Errorf("id不能为空")
+	}
+
+	id, err := primitive.ObjectIDFromHex(billId)
+	if err != nil {
+		return nil, errors.New("非法id")
+	}
+	var bill model.ProduceBill
+	option := &repo.DocSearchOptions{
+		CollectName: repo.CollectionBillProduce,
+		Query:       repo.Map{"_id": id},
+	}
+	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &bill)
+	if !found || err != nil {
+		log.Info(err)
+		return nil, errors.New("数据未找到")
+	}
+
+	f := excelize.NewFile()
+	// Create a new sheet.
+	index := f.NewSheet("Sheet1")
+	f.SetActiveSheet(index)
+	f.SetDefaultFont("宋体")
+
+	billExcel := NewProduceBill(f)
+	//设置对应的数据
+	billExcel.Draws()
+
+	c.Header("Content-Type", "application/octet-stream")
+	c.Header("Content-Disposition", "attachment; filename="+"bill.xlsx")
+	c.Header("Content-Transfer-Encoding", "binary")
+
+	err = f.Write(c.Writer)
+	if err != nil {
+		return nil, err
+	}
+
+	return nil, nil
+}

+ 265 - 0
boxcost/api/bill-purchase-excel.go

@@ -0,0 +1,265 @@
+package api
+
+import (
+	"fmt"
+
+	"github.com/xuri/excelize/v2"
+)
+
+type PurchaseBillExcel struct {
+	Offset int
+
+	Title string //标题
+
+	Excel *excelize.File
+
+	SheetName string
+
+	AlignCenterStyle int
+}
+
+func (b *PurchaseBillExcel) drawTitle() error {
+	tileIndex := b.Offset + 1
+	startCell := fmt.Sprintf("A%d", tileIndex)
+	err := b.Excel.MergeCell(b.SheetName, startCell, fmt.Sprintf("I%d", tileIndex))
+	if err != nil {
+		return err
+	}
+
+	style, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
+		Font:      &excelize.Font{Bold: true, Size: 18}})
+	if err != nil {
+		return err
+	}
+	err = b.Excel.SetCellStyle(b.SheetName, startCell, startCell, style)
+	if err != nil {
+		return err
+	}
+	b.Excel.SetRowHeight(b.SheetName, tileIndex, 23)
+	b.Excel.SetCellValue(b.SheetName, startCell, b.Title)
+	return nil
+}
+
+func (b *PurchaseBillExcel) drawSubTitles() error {
+
+	row := b.Offset + 2
+
+	styleLeft, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
+		Font:      &excelize.Font{Size: 11}})
+	if err != nil {
+		return err
+	}
+	styleRight, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "right", Vertical: "center"},
+		Font:      &excelize.Font{Size: 11}})
+	if err != nil {
+		return err
+	}
+
+	var drawLeft = func(rowIndex int, value string) error {
+		//左边1
+		left1Cell := fmt.Sprintf("A%d", rowIndex)
+		err = b.Excel.MergeCell(b.SheetName, left1Cell, fmt.Sprintf("E%d", rowIndex))
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, left1Cell, value)
+		return nil
+	}
+
+	var drawRight = func(rowIndex int, value string) error {
+		right1Cell := fmt.Sprintf("F%d", rowIndex)
+		err = b.Excel.MergeCell(b.SheetName, right1Cell, fmt.Sprintf("I%d", rowIndex))
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, right1Cell, right1Cell, styleRight)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, right1Cell, value)
+		return nil
+	}
+
+	//第一行
+	drawLeft(row, "类别:纸张类")
+	drawRight(row, "单号:ZZL-000003")
+	b.Excel.SetRowHeight(b.SheetName, row, 21)
+
+	//第二行
+	drawLeft(row+1, "供应商名称:正大文博")
+	drawRight(row+1, "下单时间:2022年12月07号 19:17:27")
+	b.Excel.SetRowHeight(b.SheetName, row+1, 21)
+
+	//第三行
+	drawLeft(row+2, "产品名称:测试3000盒-3333")
+	drawRight(row+2, "")
+	b.Excel.SetRowHeight(b.SheetName, row+2, 21)
+
+	return nil
+}
+
+func (b *PurchaseBillExcel) drawTableTitle() error {
+	row := b.Offset + 5
+
+	//A采购项目 B规格(克) 尺寸C-D 数量E 单价F-G 交货时间H 备注I
+	var drawCol = func(prefix string, value string) error {
+		left1Cell := fmt.Sprintf("%s%d", prefix, row)
+		left2Cell := fmt.Sprintf("%s%d", prefix, row+1)
+
+		err := b.Excel.MergeCell(b.SheetName, left1Cell, left2Cell)
+		if err != nil {
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left2Cell, b.AlignCenterStyle)
+		if err != nil {
+			return err
+		}
+
+		return b.Excel.SetCellValue(b.SheetName, left1Cell, value)
+	}
+
+	var drawCol2 = func(prefix1 string, prefix2 string, value1 string, value2 string, value3 string) error {
+		left1Cell := fmt.Sprintf("%s%d", prefix1, row)
+		left2Cell := fmt.Sprintf("%s%d", prefix2, row)
+		err := b.Excel.MergeCell(b.SheetName, left1Cell, left2Cell)
+		if err != nil {
+			return err
+		}
+		if err != nil {
+			fmt.Println(err)
+			return err
+		}
+		err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left2Cell, b.AlignCenterStyle)
+		if err != nil {
+			return err
+		}
+		b.Excel.SetCellValue(b.SheetName, left1Cell, value1)
+
+		val2Cel := fmt.Sprintf("%s%d", prefix1, row+1)
+		b.Excel.SetCellStyle(b.SheetName, val2Cel, val2Cel, b.AlignCenterStyle)
+		b.Excel.SetCellValue(b.SheetName, val2Cel, value2)
+
+		val3Cel := fmt.Sprintf("%s%d", prefix2, row+1)
+		b.Excel.SetCellStyle(b.SheetName, val3Cel, val3Cel, b.AlignCenterStyle)
+		b.Excel.SetCellValue(b.SheetName, val3Cel, value3)
+		return nil
+	}
+
+	drawCol("A", "采购项目")
+	drawCol("B", "规格(克)")
+	drawCol("H", "交货时间")
+	drawCol("I", " 备注")
+	drawCol("E", " 数量")
+
+	drawCol2("C", "D", "尺寸(mm)", "长", "宽")
+	drawCol2("C", "D", "尺寸(mm)", "长", "宽")
+	drawCol2("F", "G", "单价", "元/张", "元/吨")
+
+	return nil
+}
+
+func (b *PurchaseBillExcel) drawTableContent() error {
+	row := b.Offset + 7
+
+	var DrawRow = func(rowIndex int, values ...string) {
+		charas := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I"}
+		for i, c := range charas {
+			v := ""
+			if i < len(values) {
+				v = values[i]
+			}
+			b.Excel.SetCellValue(b.SheetName, fmt.Sprintf("%s%d", c, rowIndex), v)
+			val2Cel := fmt.Sprintf("%s%d", c, rowIndex)
+			b.Excel.SetCellStyle(b.SheetName, val2Cel, val2Cel, b.AlignCenterStyle)
+
+			b.Excel.SetRowHeight(b.SheetName, rowIndex, 21)
+		}
+	}
+	DrawRow(row, "太阳白卡", "250g", "800", "800", "3000", "0.864", "5400", "2022-12-07", "")
+	DrawRow(row + 1)
+	DrawRow(row + 2)
+
+	return nil
+}
+
+func (b *PurchaseBillExcel) drawTableFooter() error {
+	row := b.Offset + 10
+
+	left1Cell := fmt.Sprintf("A%d", row)
+
+	border := []excelize.Border{
+		{Type: "top", Style: 1, Color: "000000"},
+		{Type: "left", Style: 1, Color: "000000"},
+		{Type: "right", Style: 1, Color: "000000"},
+		{Type: "bottom", Style: 1, Color: "000000"},
+	}
+
+	styleLeft, _ := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
+		Border:    border,
+	})
+
+	b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
+	b.Excel.SetCellValue(b.SheetName, left1Cell, "送货地址")
+
+	addCel := fmt.Sprintf("B%d", row)
+
+	b.Excel.MergeCell(b.SheetName, addCel, fmt.Sprintf("E%d", row))
+	b.Excel.SetCellStyle(b.SheetName, addCel, fmt.Sprintf("E%d", row), styleLeft)
+	b.Excel.SetCellValue(b.SheetName, addCel, "崇州泗潍路333号--联系电话13882239198")
+
+	sureCel := fmt.Sprintf("F%d", row)
+	b.Excel.MergeCell(b.SheetName, sureCel, fmt.Sprintf("I%d", row))
+	b.Excel.SetCellStyle(b.SheetName, sureCel, fmt.Sprintf("I%d", row), styleLeft)
+	b.Excel.SetCellValue(b.SheetName, sureCel, "供应商签字:")
+
+	b.Excel.SetRowHeight(b.SheetName, row, 21)
+
+	return nil
+}
+
+func (b *PurchaseBillExcel) Draws() {
+	b.drawTitle()
+	b.drawSubTitles()
+	b.drawTableTitle()
+	b.drawTableContent()
+	b.drawTableFooter()
+}
+
+func NewPurchaseBill(f *excelize.File) *PurchaseBillExcel {
+
+	border := []excelize.Border{
+		{Type: "top", Style: 1, Color: "000000"},
+		{Type: "left", Style: 1, Color: "000000"},
+		{Type: "right", Style: 1, Color: "000000"},
+		{Type: "bottom", Style: 1, Color: "000000"},
+	}
+
+	styleLeft, _ := f.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
+		Border:    border,
+		Font:      &excelize.Font{Size: 10},
+	})
+
+	b := &PurchaseBillExcel{
+		Title:            "原材料采购单",
+		SheetName:        "Sheet1",
+		Excel:            f,
+		Offset:           0,
+		AlignCenterStyle: styleLeft,
+	}
+
+	f.SetColWidth(b.SheetName, "A", "A", 17)
+	f.SetColWidth(b.SheetName, "B", "B", 13)
+	f.SetColWidth(b.SheetName, "C", "G", 9.5)
+	f.SetColWidth(b.SheetName, "H", "I", 12)
+	f.SetPageMargins(b.SheetName, excelize.PageMarginTop(0), excelize.PageMarginLeft(0), excelize.PageMarginRight(0))
+	return b
+}

+ 47 - 0
boxcost/api/bill.go

@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/gin-gonic/gin"
+	"github.com/xuri/excelize/v2"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
@@ -25,6 +26,9 @@ func Bill(r *GinRouter) {
 	// 获取单据列表
 	r.GET("/bill/purchase/list", GetBills)
 
+	// 获取单据列表
+	r.GET("/bill/purchase/download", DownLoadBills)
+
 	// 更新单据
 	r.POST("/bill/purchase/update", UpdateBill)
 
@@ -116,6 +120,49 @@ func GetBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	return repo.RepoPageSearch(apictx.CreateRepoCtx(), option)
 }
 
+func DownLoadBills(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	billId := c.Query("id")
+	if len(billId) < 1 {
+		return nil, fmt.Errorf("id不能为空")
+	}
+
+	id, err := primitive.ObjectIDFromHex(billId)
+	if err != nil {
+		return nil, errors.New("非法id")
+	}
+	var bill model.PurchaseBill
+	option := &repo.DocSearchOptions{
+		CollectName: repo.CollectionBillPurchase,
+		Query:       repo.Map{"_id": id},
+	}
+	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), option, &bill)
+	if !found || err != nil {
+		log.Info(err)
+		return nil, errors.New("数据未找到")
+	}
+
+	f := excelize.NewFile()
+	// Create a new sheet.
+	index := f.NewSheet("Sheet1")
+	f.SetActiveSheet(index)
+	f.SetDefaultFont("宋体")
+
+	billExcel := NewPurchaseBill(f)
+	//设置对应的数据
+	billExcel.Draws()
+
+	c.Header("Content-Type", "application/octet-stream")
+	c.Header("Content-Disposition", "attachment; filename="+"bill.xlsx")
+	c.Header("Content-Transfer-Encoding", "binary")
+
+	err = f.Write(c.Writer)
+	if err != nil {
+		return nil, err
+	}
+
+	return nil, nil
+}
+
 // 更新单据
 func UpdateBill(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	var bill model.PurchaseBill

+ 33 - 1
boxcost/api/plan.go

@@ -78,7 +78,39 @@ func GetProductPlan(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return nil, errors.New("数据未找到")
 	}
 
-	return plan, nil
+	billStates := map[string]string{}
+
+	if plan.Pack != nil && plan.Pack.Components != nil {
+		for _, comp := range plan.Pack.Components {
+			if comp.Mats != nil {
+				for _, mat := range comp.Mats {
+
+					if len(mat.BillId) > 0 {
+						ok, state := repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{CollectName: repo.CollectionBillPurchase, Query: repo.Map{"_id": mat.BillId}, Project: []string{"status"}})
+						if ok {
+							billStates[mat.BillId] = state["status"].(string)
+						}
+					}
+
+					if mat.Crafts != nil {
+						for _, craft := range mat.Crafts {
+							if len(craft.BillId) > 0 {
+								ok, state := repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{CollectName: repo.CollectionBillProduce, Query: repo.Map{"_id": craft.BillId}, Project: []string{"status"}})
+								if ok {
+									billStates[craft.BillId] = state["status"].(string)
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return map[string]interface{}{
+		"plan":       plan,
+		"billStates": billStates,
+	}, nil
 }
 
 // 获取生产计划列表

+ 4 - 0
boxcost/boxcost.log

@@ -7,3 +7,7 @@
 {"level":"info","timestamp":"2022-11-14 10:17:17","message":"[<nil>]","service_name":"boxcost"}
 {"level":"info","timestamp":"2022-11-14 10:18:50","message":"[<nil>]","service_name":"boxcost"}
 {"level":"info","timestamp":"2022-11-14 10:22:22","message":"[<nil>]","service_name":"boxcost"}
+{"level":"info","timestamp":"2022-12-21 11:19:42","message":"[<nil>]","service_name":"boxcost"}
+{"level":"info","timestamp":"2022-12-21 11:20:02","message":"[<nil>]","service_name":"boxcost"}
+{"level":"info","timestamp":"2022-12-21 11:21:28","message":"[<nil>]","service_name":"boxcost"}
+{"level":"info","timestamp":"2022-12-21 11:24:46","message":"[<nil>]","service_name":"boxcost"}

+ 10 - 4
boxcost/go.mod

@@ -8,8 +8,10 @@ require (
 	github.com/gin-contrib/sessions v0.0.3
 	github.com/gin-gonic/gin v1.7.4
 	github.com/go-redis/redis/v8 v8.11.5
+	github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible
 	github.com/natefinch/lumberjack v2.0.0+incompatible
 	github.com/spf13/viper v1.9.0
+	github.com/xuri/excelize/v2 v2.6.1
 	go.mongodb.org/mongo-driver v1.9.1
 	go.uber.org/dig v1.12.0
 	go.uber.org/zap v1.17.0
@@ -33,7 +35,6 @@ require (
 	github.com/gorilla/securecookie v1.1.1 // indirect
 	github.com/gorilla/sessions v1.1.3 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
-	github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.14.4 // indirect
 	github.com/kr/text v0.2.0 // indirect
@@ -44,6 +45,7 @@ require (
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/nats-io/jwt/v2 v2.3.0 // indirect
 	github.com/nats-io/nats.go v1.13.1-0.20220308171302-2f2f6968e98d // indirect
 	github.com/nats-io/nkeys v0.3.0 // indirect
@@ -51,6 +53,8 @@ require (
 	github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
 	github.com/pelletier/go-toml v1.9.4 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
+	github.com/richardlehane/mscfb v1.0.4 // indirect
+	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/spf13/afero v1.6.0 // indirect
 	github.com/spf13/cast v1.4.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
@@ -60,13 +64,15 @@ require (
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.0.2 // indirect
 	github.com/xdg-go/stringprep v1.0.2 // indirect
+	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
+	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 	go.uber.org/atomic v1.7.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect
-	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
-	golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
+	golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect
+	golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
-	golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
+	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
 	google.golang.org/protobuf v1.28.0 // indirect

+ 27 - 8
boxcost/go.sum

@@ -286,6 +286,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
 github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
@@ -316,6 +318,11 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
 github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/quasoft/memstore v0.0.0-20180925164028-84a050167438/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg=
+github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
+github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
+github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
+github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
+github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@@ -338,8 +345,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/tidwall/gjson v1.9.4 h1:oNis7dk9Rs3dKJNNigXZT1MTOiJeBtpurn+IpCB75MY=
@@ -358,6 +366,12 @@ github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
 github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
 github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
 github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
+github.com/xuri/excelize/v2 v2.6.1 h1:ICBdtw803rmhLN3zfvyEGH3cwSmZv+kde7LhTDT659k=
+github.com/xuri/excelize/v2 v2.6.1/go.mod h1:tL+0m6DNwSXj/sILHbQTYsLi9IF4TW59H2EF3Yrx1AU=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -397,8 +411,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
-golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c=
+golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -411,6 +425,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE=
+golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -472,8 +488,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
+golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -558,10 +575,11 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -786,8 +804,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=