animeic 1 жил өмнө
parent
commit
b991c1835a

+ 271 - 0
boxcost/api/report-excel.go

@@ -0,0 +1,271 @@
+package api
+
+import (
+	"box-cost/db/model"
+	"box-cost/log"
+	"encoding/json"
+	"fmt"
+
+	"github.com/xuri/excelize/v2"
+)
+
+type ReportExcel struct {
+	Row              int
+	Title            string //标题
+	SupplierName     string //供应商名
+	TimeRange        []string
+	Excel            *excelize.File
+	SheetName        string
+	AlignCenterStyle int
+	Content          []map[string]interface{}
+}
+
+func (b *ReportExcel) drawTitle() error {
+	b.Row++
+	// 设置外边距
+	startCell := fmt.Sprintf("A%d", b.Row)
+	endCell := fmt.Sprintf("I%d", b.Row)
+
+	b.Excel.SetColWidth(b.SheetName, "A", "A", 10)
+	b.Excel.SetColWidth(b.SheetName, "B", "B", 16)
+	b.Excel.SetColWidth(b.SheetName, "C", "D", 20)
+	b.Excel.SetColWidth(b.SheetName, "E", "H", 18)
+	b.Excel.SetColWidth(b.SheetName, "I", "I", 35)
+
+	err := b.Excel.MergeCell(b.SheetName, startCell, endCell)
+	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, b.Row, 35)
+	b.Excel.SetCellValue(b.SheetName, startCell, b.Title)
+	return nil
+}
+
+func (b *ReportExcel) drawSubTitles() error {
+	b.Row++
+
+	styleLeft, err := b.Excel.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
+		Font:      &excelize.Font{Size: 11}})
+	if err != nil {
+		return err
+	}
+	var drawLeft = func(rowIndex int, value string) error {
+		left1Cell := fmt.Sprintf("A%d", rowIndex)
+		err = b.Excel.MergeCell(b.SheetName, left1Cell, fmt.Sprintf("I%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
+	}
+	timeString := ""
+	if len(b.TimeRange) == 2 {
+		timeString = fmt.Sprintf(" ( %s~%s ) ", b.TimeRange[0], b.TimeRange[1])
+	}
+
+	drawLeft(b.Row, "单位名称:"+b.SupplierName+timeString)
+	b.Excel.SetRowHeight(b.SheetName, b.Row, 35)
+	return nil
+}
+
+func (b *ReportExcel) drawTableTitle() error {
+	b.Row++
+	var drawCol = func(prefix string, value string) error {
+		left1Cell := fmt.Sprintf("%s%d", prefix, b.Row)
+		left2Cell := fmt.Sprintf("%s%d", prefix, b.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)
+	}
+	drawCol("A", "序号")
+	drawCol("B", "日期")
+	drawCol("C", "采购或加工项目")
+	drawCol("D", "规格")
+	drawCol("E", "尺寸")
+	drawCol("F", "数量")
+	drawCol("G", "单价")
+	drawCol("H", "金额")
+	drawCol("I", "产品名称")
+	// b.Excel.SetRowHeight(b.SheetName, b.Row, 35)
+
+	return nil
+}
+
+func (b *ReportExcel) drawTableContent() error {
+	b.Row += 2
+	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, 46)
+		}
+	}
+
+	lists := b.Content
+
+	if len(lists) > 0 {
+		index := 0
+		var totalPrice float64 = 0.00
+		var totalCount int = 0
+		for _, list := range lists {
+			data, err := json.Marshal(list)
+			if err != nil {
+				log.Error(err)
+				continue
+			}
+			if list["billType"] == "purchase" {
+				purchase := model.PurchaseBill{}
+				err = json.Unmarshal(data, &purchase)
+				if err != nil {
+					log.Error(err)
+					continue
+				}
+				for _, paper := range purchase.Paper {
+					index++
+					completeTime := purchase.CompleteTime.Local().Format("2006-01-02")
+					// 实际完成数
+					realCount := fmt.Sprintf("%d", paper.ConfirmCount)
+					b.FormatToEmpty(&realCount)
+
+					// 实际金额
+					realPrice := fmt.Sprintf("%.3f", paper.OrderPrice*float64(paper.ConfirmCount))
+					b.FormatToEmpty(&realPrice)
+					DrawRow(b.Row, fmt.Sprintf("%d", index), completeTime, paper.Name, paper.Norm, fmt.Sprintf("%s*%s", paper.Height, paper.Width), fmt.Sprintf("%d", paper.ConfirmCount), fmt.Sprintf("%.3f", paper.OrderPrice), realPrice, purchase.ProductName)
+					totalPrice += paper.OrderPrice * float64(paper.ConfirmCount)
+					totalCount += paper.ConfirmCount
+					b.Row++
+				}
+			}
+			if list["billType"] == "produce" {
+				produce := model.ProduceBill{}
+				err = json.Unmarshal(data, &produce)
+				if err != nil {
+					log.Error(err)
+					continue
+				}
+				for _, pproduce := range produce.Produces {
+					index++
+					completeTime := produce.CompleteTime.Local().Format("2006-01-02")
+					// 实际完成数
+					realCount := fmt.Sprintf("%d", pproduce.ConfirmCount)
+					b.FormatToEmpty(&realCount)
+
+					// 实际金额
+					realPrice := fmt.Sprintf("%.3f", pproduce.OrderPrice*float64(pproduce.ConfirmCount))
+					b.FormatToEmpty(&realPrice)
+					DrawRow(b.Row, fmt.Sprintf("%d", index), completeTime, pproduce.Name, pproduce.Norm, pproduce.PrintSize, fmt.Sprintf("%d", pproduce.ConfirmCount), fmt.Sprintf("%.3f", pproduce.OrderPrice), realPrice, produce.ProductName)
+					totalPrice += pproduce.OrderPrice * float64(pproduce.ConfirmCount)
+					totalCount += pproduce.ConfirmCount
+					b.Row++
+				}
+			}
+			if list["billType"] == "product" {
+				product := model.ProductBill{}
+				err = json.Unmarshal(data, &product)
+				if err != nil {
+					log.Error(err)
+					continue
+				}
+				for _, pproduct := range product.Products {
+					index++
+					completeTime := product.CompleteTime.Local().Format("2006-01-02")
+					// 实际完成数
+					realCount := fmt.Sprintf("%d", pproduct.ConfirmCount)
+					b.FormatToEmpty(&realCount)
+
+					// 实际金额
+					realPrice := fmt.Sprintf("%.3f", pproduct.OrderPrice*float64(pproduct.ConfirmCount))
+					b.FormatToEmpty(&realPrice)
+					DrawRow(b.Row, fmt.Sprintf("%d", index), completeTime, pproduct.Name, pproduct.Norm, "-", fmt.Sprintf("%d", pproduct.ConfirmCount), fmt.Sprintf("%.3f", pproduct.OrderPrice), realPrice, product.ProductName)
+					totalPrice += pproduct.OrderPrice * float64(pproduct.ConfirmCount)
+					totalCount += pproduct.ConfirmCount
+					b.Row++
+				}
+			}
+
+		}
+		DrawRow(b.Row, "", "", "", "", "", "", "", "", "")
+		startCell := fmt.Sprintf("%s%d", "A", b.Row)
+		endCell := fmt.Sprintf("%s%d", "B", b.Row)
+		FCell := fmt.Sprintf("%s%d", "F", b.Row)
+		HCell := fmt.Sprintf("%s%d", "H", b.Row)
+		b.Excel.MergeCell(b.SheetName, startCell, endCell)
+		b.Excel.SetCellValue(b.SheetName, startCell, "合计")
+		// 数量汇总
+		b.Excel.SetCellValue(b.SheetName, FCell, totalCount)
+		// 金额汇总
+		b.Excel.SetCellValue(b.SheetName, HCell, totalPrice)
+	}
+
+	return nil
+}
+
+func (b *ReportExcel) Draws() {
+	b.drawTitle()
+	b.drawSubTitles()
+	b.drawTableTitle()
+	b.drawTableContent()
+}
+
+func NewReportExcel(f *excelize.File) *ReportExcel {
+
+	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", WrapText: true},
+		Border:    border,
+	})
+
+	b := &ReportExcel{
+		Title:            "供应商统计报表",
+		SupplierName:     "",
+		SheetName:        "Sheet1",
+		Excel:            f,
+		AlignCenterStyle: styleLeft,
+	}
+	f.SetPageMargins(b.SheetName, excelize.PageMarginTop(0), excelize.PageMarginLeft(0), excelize.PageMarginRight(0))
+
+	return b
+}
+
+func (b *ReportExcel) FormatToEmpty(str *string) {
+	if *str == "0" || *str == "0.000" {
+		*str = ""
+	}
+}

+ 157 - 3
boxcost/api/report.go

@@ -25,14 +25,169 @@ func Report(r *GinRouter) {
 	r.GET("/report/purchase/download", ReportPurchaseDownload)
 	r.GET("/report/product/download", ReportProductDownload)
 	r.GETJWT("/report/list", ReportList)
+	r.GETJWT("/report/download", ReportListDownload)
+}
+
+// 加工单
+func ReportListDownload(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	// start, stop := CreatePageRange(page, size)
+	supplierId := primitive.NilObjectID
+	if _supplierId, ok := query["supplierId"]; ok {
+		supplierId, _ = primitive.ObjectIDFromHex(_supplierId.(string))
+	}
+
+	timeRange := []interface{}{}
+	if _timeRange, ok := query["timeRange"]; ok {
+		timeRange, _ = _timeRange.([]interface{})
+	}
+	filtter := handleReportQuery(query)
+
+	purchases := []*model.PurchaseBill{}
+	produces := []*model.ProduceBill{}
+	products := []*model.ProductBill{}
+
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillPurchase,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &purchases)
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillProduce,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &produces)
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillProduct,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &products)
+
+	// 加入redis有序集合中
+	redisCli := apictx.Svc.Redis
+
+	reportBillKey := "report-bill-list:" + apictx.User.Parent
+
+	isExist := redisCli.Exists(apictx.CreateRepoCtx().Ctx, reportBillKey).Val()
+	// 不存在这个key时
+	if isExist < 1 {
+		if len(purchases) > 0 {
+			for _, purchase := range purchases {
+				member := "purchase_" + purchase.Id.Hex()
+				score := purchase.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		if len(produces) > 0 {
+			for _, produce := range produces {
+				member := "produce_" + produce.Id.Hex()
+				score := produce.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		if len(products) > 0 {
+			for _, product := range products {
+				member := "product_" + product.Id.Hex()
+				score := product.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		// 设置过期时间
+		redisCli.Expire(apictx.CreateRepoCtx().Ctx, reportBillKey, 20*time.Second)
+
+	}
+
+	total, err := redisCli.ZCard(apictx.CreateRepoCtx().Ctx, reportBillKey).Uint64()
+	fmt.Println(total)
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+
+	reports, err := redisCli.ZRevRange(apictx.CreateRepoCtx().Ctx, reportBillKey, 0, -1).Result()
+	if err != nil {
+		return nil, err
+	}
+
+	if len(reports) < 1 {
+		return repo.PageResult{
+			Page:  page,
+			Size:  size,
+			Total: 0,
+		}, nil
+	}
+	lists := []map[string]interface{}{}
+	for _, report := range reports {
+		billArray := strings.Split(report, "_")
+		billType := billArray[0]
+		_billId := billArray[1]
+		billId, _ := primitive.ObjectIDFromHex(_billId)
+		billData := map[string]interface{}{}
+
+		found := false
+		if billType == "purchase" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillPurchase,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if billType == "produce" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillProduce,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if billType == "product" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillProduct,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if found {
+			billData["billType"] = billType
+			lists = append(lists, billData)
+		}
+	}
+	f := excelize.NewFile()
+	index := f.NewSheet("Sheet1")
+	f.SetActiveSheet(index)
+	f.SetDefaultFont("宋体")
+	report := NewReportExcel(f)
+	supplier := model.Supplier{}
+	supplierName := "【所有供应商】"
+	if !supplierId.IsZero() {
+		repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+			CollectName: repo.CollectionSupplier,
+			Query:       repo.Map{"supplierId": supplierId},
+			Project:     []string{"name"},
+		}, &supplier)
+		supplierName = supplier.Name
+
+	}
+	report.SupplierName = supplierName
+	if len(timeRange) == 2 {
+		report.TimeRange = append(report.TimeRange, timeRange[0].(string), timeRange[1].(string))
+	}
+	report.Content = lists
+	report.Draws()
+
+	c.Header("Content-Type", "application/octet-stream")
+	c.Header("Content-Disposition", "attachment; filename="+"report.xlsx")
+	c.Header("Content-Transfer-Encoding", "binary")
+	err = f.Write(c.Writer)
+	if err != nil {
+		return nil, err
+	}
+	return nil, nil
 }
 
 // 加工单
 func ReportList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	page, size, query := UtilQueryPageSize(c)
 	start, stop := CreatePageRange(page, size)
-	fmt.Println(start, stop)
-
 	filtter := handleReportQuery(query)
 
 	purchases := []*model.PurchaseBill{}
@@ -148,7 +303,6 @@ func ReportList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		Page:  page,
 		Size:  size,
 	}, nil
-
 }
 
 func CreatePageRange(page, size int64) (int64, int64) {

+ 0 - 1
boxcost/api/utils.go

@@ -187,7 +187,6 @@ func handleReportQuery(query map[string]interface{}) map[string]interface{} {
 	query["status"] = "complete"
 	if _supplierId, ok := query["supplierId"]; ok {
 		delete(query, "supplierId")
-		fmt.Printf("id::::%#v\n", _supplierId)
 		supplierId, _ := primitive.ObjectIDFromHex(_supplierId.(string))
 		if !supplierId.IsZero() {
 			query["supplierId"] = supplierId