Browse Source

2023-12-28 扫码入库

zoie 1 year ago
parent
commit
e083b265d3

+ 3 - 3
common/model/model.go

@@ -6,9 +6,9 @@ import (
 )
 
 type ControlBy struct {
-	CreateBy int `json:"createBy" gorm:"index;comment:创建者"` // 创建者
-	UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` // 更新者
-	DeptId   int `json:"deptId" gorm:"index;comment:部门id"`  // 更新者
+	CreateBy int `json:"createBy" gorm:"comment:创建者"`      // 创建者
+	UpdateBy int `json:"updateBy" gorm:"comment:更新者"`      // 更新者
+	DeptId   int `json:"deptId" gorm:"index;comment:部门id"` // 更新者
 }
 
 // SetCreateBy 设置创建人id

+ 46 - 0
controllers/medicine_template.go

@@ -212,3 +212,49 @@ func (c MedicineTemplateController) ListForStockOut() {
 
 	c.PageOK(list, int(count), 0, 0, "查询成功")
 }
+
+// ListForStockInScanCode 获取扫码入库表单列表
+// @Summary 获取扫码入库表单列表
+// @Description 获取扫码入库表单列表
+// @Tags 药品信息模板
+// @Success 200 {object} response.Page{list=[]models.MedicineTemplate} "{"code": 200, "data": [...]}"
+// @Router /medicine-template/list-for-stock [post]
+// @Security Bearer
+func (c MedicineTemplateController) ListForStockInScanCode() {
+	s := services.MedicineTemplate{}
+
+	list := make([]dto.MedicineTemplateForStockRes, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c.Ctx)
+	err := s.ListForStockInScanCode(&list, &count, p)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+
+	c.PageOK(list, int(count), 0, 0, "查询成功")
+}
+
+// ListForStockOutScanCode 获取扫码出库表单列表
+// @Summary 获取扫码出库表单列表
+// @Description 获取扫码出库表单列表
+// @Tags 药品信息模板
+// @Success 200 {object} response.Page{list=[]models.MedicineTemplate} "{"code": 200, "data": [...]}"
+// @Router /medicine-template/list-for-stock [post]
+// @Security Bearer
+func (c MedicineTemplateController) ListForStockOutScanCode() {
+	s := services.MedicineTemplate{}
+
+	list := make([]dto.MedicineTemplateForStockRes, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c.Ctx)
+	err := s.ListForStockOutScanCode(&list, &count, p)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+
+	c.PageOK(list, int(count), 0, 0, "查询成功")
+}

+ 3 - 3
controllers/sales.go

@@ -342,7 +342,7 @@ func (c SalesController) SalesStockOutExcel(reqData dto.SalesStockOutExcelReq) {
 	f.SetCellValue("Sheet1", "C3", "规格")
 	f.SetCellValue("Sheet1", "D3", "生产企业")
 	f.SetCellValue("Sheet1", "E3", "批号")
-	f.SetCellValue("Sheet1", "F3", "效期")
+	f.SetCellValue("Sheet1", "F3", "期")
 	f.SetCellValue("Sheet1", "G3", "批准文号")
 	f.SetCellValue("Sheet1", "H3", "数量")
 	f.SetCellValue("Sheet1", "I3", "单位")
@@ -452,7 +452,7 @@ func (c SalesController) SalesStockOutPdf(reqData dto.SalesStockOutExcelReq) {
 	}
 	cols := []float64{22, 12, 22, 18, 20, 20, 20, 10, 10, 18, 18}
 
-	header := []string{"品种", "剂型", "规格", "生产企业", "批号", "效期", "批准文号", "数量", "单位", "销售单价", "销售金额"}
+	header := []string{"品种", "剂型", "规格", "生产企业", "批号", "期", "批准文号", "数量", "单位", "销售单价", "销售金额"}
 	rows := [][]string{}
 	money := 0.0
 	for _, row := range list {
@@ -462,7 +462,7 @@ func (c SalesController) SalesStockOutPdf(reqData dto.SalesStockOutExcelReq) {
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldSpecName]))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldEnterpriseName]))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldExpiryDate].(time.Time).Format("2006-01-02")))
+		temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldApprovalNumber]))
 		temp = append(temp, fmt.Sprintf("%d", utils.ToInt(row["quantity"])))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldUnitName]))

+ 69 - 17
controllers/stock_template.go

@@ -50,6 +50,32 @@ func (c StockTemplateController) StockTemplateIn() {
 	c.OK(reqData.GetId(), "入库成功")
 }
 
+// StockTemplateInScanCode 扫码入库
+// @Summary 扫码入库
+// @Description 扫码入库
+// @Tags 库存
+// @Param body body dto.StockTemplateInInsertReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /stock-template/in [post]
+// @Security Bearer
+func (c StockTemplateController) StockTemplateInScanCode() {
+	s := services.StockTemplate{}
+	reqData := dto.BatchStockTemplateInInsertReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+
+	reqData.SetCreateBy(beegouser.GetUserId(c.Ctx))
+	reqData.SetDeptId(beegouser.GetDeptId(c.Ctx))
+	err := s.StockTemplateInScanCode(&reqData)
+	if err != nil {
+		c.Error(500, err, err.Error())
+		return
+	}
+	c.OK(nil, "扫码入库成功")
+}
+
 // StockTemplateInEdit 修改入库
 // @Summary 修改入库
 // @Description 修改入库
@@ -154,6 +180,32 @@ func (c StockTemplateController) StockTemplateOut() {
 	c.OK(reqData.GetId(), "出库成功")
 }
 
+// StockTemplateOutScanCode 扫码出库
+// @Summary 扫码出库
+// @Description 扫码出库
+// @Tags 库存
+// @Param body body dto.StockTemplateOutInsertReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /stock-template/out [post]
+// @Security Bearer
+func (c StockTemplateController) StockTemplateOutScanCode() {
+	s := services.StockTemplate{}
+	reqData := dto.BatchStockTemplateOutInsertReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+
+	reqData.SetCreateBy(beegouser.GetUserId(c.Ctx))
+	reqData.SetDeptId(beegouser.GetDeptId(c.Ctx))
+	err := s.StockTemplateOutScanCode(&reqData)
+	if err != nil {
+		c.Error(500, err, err.Error())
+		return
+	}
+	c.OK(nil, "扫码出库成功")
+}
+
 // StockTemplateOutEdit 修改入库
 // @Summary 修改入库
 // @Description 修改入库
@@ -398,19 +450,19 @@ func (c StockTemplateController) StockTemplateInventoryExcel(reqData dto.StockTe
 	f.SetCellValue("Sheet1", "F4", "收入")
 	f.SetCellValue("Sheet1", "F5", "数量")
 	f.SetCellValue("Sheet1", "G5", "批号")
-	f.SetCellValue("Sheet1", "H5", "效期")
+	f.SetCellValue("Sheet1", "H5", "期")
 
 	f.MergeCell("Sheet1", "I4", "K4")
 	f.SetCellValue("Sheet1", "I4", "支出")
 	f.SetCellValue("Sheet1", "I5", "数量")
 	f.SetCellValue("Sheet1", "J5", "批号")
-	f.SetCellValue("Sheet1", "K5", "效期")
+	f.SetCellValue("Sheet1", "K5", "期")
 
 	f.MergeCell("Sheet1", "L4", "N4")
 	f.SetCellValue("Sheet1", "L4", "结余")
 	f.SetCellValue("Sheet1", "L5", "数量")
 	f.SetCellValue("Sheet1", "M5", "批号")
-	f.SetCellValue("Sheet1", "N5", "效期")
+	f.SetCellValue("Sheet1", "N5", "期")
 
 	f.MergeCell("Sheet1", "O4", "O5")
 	f.SetCellValue("Sheet1", "O4", "经办人签字")
@@ -439,17 +491,17 @@ func (c StockTemplateController) StockTemplateInventoryExcel(reqData dto.StockTe
 			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v["forwarding_unit"])
 			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), utils.ToInt(v["total_in"]))
 			f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), v[models.FieldApprovalNumber])
-			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v[models.FieldExpiryDate].(time.Time).Format("2006-01-02"))
+			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), utils.ToDate(v[models.FieldExpiryDate]))
 		}
 		if utils.ToInt(v["stock_out_id"]) > 0 {
 			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v["receiving_unit"])
 			f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), utils.ToInt(v["total_out"]))
 			f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v[models.FieldApprovalNumber])
-			f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v[models.FieldExpiryDate].(time.Time).Format("2006-01-02"))
+			f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), utils.ToDate(v[models.FieldExpiryDate]))
 		}
 		f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), utils.ToInt(v["balance"]))
 		f.SetCellValue("Sheet1", fmt.Sprintf("M%d", line), v[models.FieldApprovalNumber])
-		f.SetCellValue("Sheet1", fmt.Sprintf("N%d", line), v[models.FieldExpiryDate].(time.Time).Format("2006-01-02"))
+		f.SetCellValue("Sheet1", fmt.Sprintf("N%d", line), utils.ToDate(v[models.FieldExpiryDate]))
 
 		f.SetCellValue("Sheet1", fmt.Sprintf("O%d", line), v["operator"])
 
@@ -547,7 +599,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 		if utils.ToInt(row["stock_in_id"]) > 0 {
 			temp = append(temp, fmt.Sprintf("%d", row["total_in"]))
 			temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-			temp = append(temp, fmt.Sprintf("%s", row[models.FieldExpiryDate].(time.Time).Format("2006-01-02")))
+			temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
 		} else {
 			temp = append(temp, "")
 			temp = append(temp, "")
@@ -557,7 +609,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 		if utils.ToInt(row["stock_out_id"]) > 0 {
 			temp = append(temp, fmt.Sprintf("%d", row["total_out"]))
 			temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-			temp = append(temp, fmt.Sprintf("%s", row[models.FieldExpiryDate].(time.Time).Format("2006-01-02")))
+			temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
 		} else {
 			temp = append(temp, "")
 			temp = append(temp, "")
@@ -566,7 +618,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 
 		temp = append(temp, fmt.Sprintf("%d", row["balance"]))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldExpiryDate].(time.Time).Format("2006-01-02")))
+		temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
 		temp = append(temp, fmt.Sprintf("%s", row["operator"]))
 		rows = append(rows, temp)
 
@@ -621,7 +673,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 	curx += width
 	pdf.SetXY(curx, y+h/2)
 	width = cols[7]
-	pdf.CellFormat(width, h/2, "效期", "1", 0, "CM", false, 0, "")
+	pdf.CellFormat(width, h/2, "期", "1", 0, "CM", false, 0, "")
 
 	// ------支出
 	curx += width
@@ -641,7 +693,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 	curx += width
 	pdf.SetXY(curx, y+h/2)
 	width = cols[10]
-	pdf.CellFormat(width, h/2, "效期", "1", 0, "CM", false, 0, "")
+	pdf.CellFormat(width, h/2, "期", "1", 0, "CM", false, 0, "")
 
 	// ------结余
 	curx += width
@@ -661,7 +713,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 	curx += width
 	pdf.SetXY(curx, y+h/2)
 	width = cols[13]
-	pdf.CellFormat(width, h/2, "效期", "1", 0, "CM", false, 0, "")
+	pdf.CellFormat(width, h/2, "期", "1", 0, "CM", false, 0, "")
 
 	curx += width
 	width = cols[14]
@@ -931,7 +983,7 @@ func (c StockTemplateController) TransportRecordWord(reqData dto.TransportRecord
 	run = para.AddRun()
 	run.Properties().SetFontFamily("宋体")
 	run.Properties().SetSize(9)
-	run.AddText("效期")
+	run.AddText("期")
 
 	cell = row.AddCell()
 	cell.Properties().SetWidthPercent(6)
@@ -1039,7 +1091,7 @@ func (c StockTemplateController) TransportRecordWord(reqData dto.TransportRecord
 		run = para.AddRun()
 		run.Properties().SetFontFamily("宋体")
 		run.Properties().SetSize(8)
-		run.AddText(medicineInfo[models.FieldExpiryDate].(time.Time).Format("2006-01-02"))
+		run.AddText(utils.ToDate(medicineInfo[models.FieldExpiryDate]))
 
 		cell = row.AddCell()
 		cell.Properties().SetWidthPercent(6)
@@ -1689,7 +1741,7 @@ func (c StockTemplateController) TransportRecordPdf(reqData dto.TransportRecordW
 
 	cols := []float64{30, 22, 20, 27, 31, 22, 21, 11, 11}
 
-	header := []string{"品种", "生产企业", "批准文号", "批签发合格编号", "规格(剂/支或粒)", "批号", "效期", "数量", "单位"}
+	header := []string{"品种", "生产企业", "批准文号", "批签发合格编号", "规格(剂/支或粒)", "批号", "期", "数量", "单位"}
 	rows := [][]string{}
 	for _, row := range list {
 		temp := []string{}
@@ -1699,7 +1751,7 @@ func (c StockTemplateController) TransportRecordPdf(reqData dto.TransportRecordW
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldQualificationNumber]))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldSpecName]))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldExpiryDate].(time.Time).Format("2006-01-02")))
+		temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
 		temp = append(temp, fmt.Sprintf("%d", utils.ToInt(row["quantity"])))
 		temp = append(temp, fmt.Sprintf("%s", row[models.FieldUnitName]))
 		rows = append(rows, temp)
@@ -2063,7 +2115,7 @@ func (c StockTemplateController) StockInquiryExcel() {
 	f.SetCellValue("Sheet1", "G2", "购进单价")
 	f.SetCellValue("Sheet1", "H2", "销售单价")
 	f.SetCellValue("Sheet1", "I2", "批号")
-	f.SetCellValue("Sheet1", "J2", "效期")
+	f.SetCellValue("Sheet1", "J2", "期")
 	f.SetCellValue("Sheet1", "K2", "批准文号")
 	f.SetCellValue("Sheet1", "L2", "批签发编号")
 	// 设置列宽

+ 2 - 2
docs/docs.go

@@ -2198,7 +2198,7 @@ const docTemplate = `{
                     "type": "string"
                 },
                 "endDate": {
-                    "description": "效期结束时间",
+                    "description": "期结束时间",
                     "type": "string"
                 },
                 "enterpriseId": {
@@ -2220,7 +2220,7 @@ const docTemplate = `{
                     "type": "integer"
                 },
                 "startDate": {
-                    "description": "效期开始时间",
+                    "description": "期开始时间",
                     "type": "string"
                 }
             }

+ 2 - 2
docs/swagger.json

@@ -2194,7 +2194,7 @@
                     "type": "string"
                 },
                 "endDate": {
-                    "description": "效期结束时间",
+                    "description": "期结束时间",
                     "type": "string"
                 },
                 "enterpriseId": {
@@ -2216,7 +2216,7 @@
                     "type": "integer"
                 },
                 "startDate": {
-                    "description": "效期开始时间",
+                    "description": "期开始时间",
                     "type": "string"
                 }
             }

+ 2 - 2
docs/swagger.yaml

@@ -360,7 +360,7 @@ definitions:
         description: 批号
         type: string
       endDate:
-        description: 效期结束时间
+        description: 期结束时间
         type: string
       enterpriseId:
         description: 生产企业id
@@ -377,7 +377,7 @@ definitions:
         description: 药品名称id
         type: integer
       startDate:
-        description: 效期开始时间
+        description: 期开始时间
         type: string
     type: object
   dto.StockTemplateInDeleteReq:

+ 3 - 3
dto/stock.go

@@ -27,7 +27,7 @@ type StockInInsertReq struct {
 	ApprovalNumber      string `json:"approvalNumber"`      // 批准文号
 	QualificationNumber string `json:"qualificationNumber"` // 批签发合格编号
 	ProductionDate      string `json:"productionDate"`      // 生产日期
-	ExpiryDate          string `json:"expiryDate"`          // 效期
+	ExpiryDate          string `json:"expiryDate"`          // 
 	BatchNumber         string `json:"batchNumber"`         // 批号
 
 	Quantity       int     `json:"quantity"`       // 数量
@@ -56,7 +56,7 @@ type StockOutInsertReq struct {
 	ApprovalNumber      string `json:"approvalNumber"`      // 批准文号
 	QualificationNumber string `json:"qualificationNumber"` // 批签发合格编号
 	ProductionDate      string `json:"productionDate"`      // 生产日期
-	ExpiryDate          string `json:"expiryDate"`          // 效期
+	ExpiryDate          string `json:"expiryDate"`          // 
 	BatchNumber         string `json:"batchNumber"`         // 批号
 
 	Quantity      int     `json:"quantity"`      // 数量
@@ -78,7 +78,7 @@ type StockInPageReq struct {
 	dto.Pagination `search:"-"`
 	ProductID      int    `json:"productId"`    // 药品名称id
 	EnterpriseID   int    `json:"enterpriseId"` // 生产企业id
-	ExpiryDate     string `json:"expiryDate"`   // 效期
+	ExpiryDate     string `json:"expiryDate"`   // 
 	BatchNumber    string `json:"batchNumber"`  // 批号
 }
 

+ 2 - 2
dto/stock_template.go

@@ -196,8 +196,8 @@ type StockStatListReq struct {
 	dto.Pagination `search:"-"`
 	ProductID      int    `json:"productId"`    // 药品名称id
 	EnterpriseID   int    `json:"enterpriseId"` // 生产企业id
-	StartDate      string `json:"startDate"`    // 效期开始时间
-	EndDate        string `json:"endDate"`      // 效期结束时间
+	StartDate      string `json:"startDate"`    // 期开始时间
+	EndDate        string `json:"endDate"`      // 期结束时间
 	BatchNumber    string `json:"batchNumber"`  // 批号
 }
 

+ 1 - 1
models/medicine_Info.go

@@ -12,7 +12,7 @@ type MedicineInfo struct {
 	ApprovalNumber      string `json:"approvalNumber" gorm:"size:128;"`      // 批准文号
 	QualificationNumber string `json:"qualificationNumber" gorm:"size:128;"` // 批签发合格编号
 	ProductionDate      string `json:"productionDate" gorm:"size:128;"`      // 生产日期
-	ExpiryDate          string `json:"expiryDate" gorm:"size:128;"`          // 效期
+	ExpiryDate          string `json:"expiryDate" gorm:"size:128;"`          // 
 	BatchNumber         string `json:"batchNumber" gorm:"size:128;"`         // 批号
 	model2.ControlBy
 	model2.ModelTime

+ 10 - 10
models/medicine_inventory.go

@@ -7,16 +7,16 @@ import (
 // 药品出入库信息
 type MedicineInventory struct {
 	model2.Model
-	MedicineID     int    `json:"medicineId" gorm:"size:4;not null;comment:药品信息ID"` // 药品信息ID
-	TotalIn        int    `json:"totalIn" gorm:"size:11;"`                          // 入库数量
-	StockInID      int    `json:"stockInId" gorm:"size:11;"`                        // 入库ID
-	TotalOut       int    `json:"totalOut" gorm:"size:11;"`                         // 出库数量
-	StockOutID     int    `json:"stockOutId" gorm:"size:11;"`                       // 出库ID
-	Balance        int    `json:"balance" gorm:"size:11;"`                          // 结余数量
-	ForwardingUnit string `json:"forwardingUnit" gorm:"size:128;"`                  // 发货单位
-	ReceivingUnit  string `json:"receivingUnit" gorm:"size:128;"`                   // 收货单位
-	Operator       string `json:"operator" gorm:"size:128;"`                        // 经办人
-	Date           string `json:"date" gorm:"size:128;"`                            // 日期
+	MedicineID     int    `json:"medicineId" gorm:"size:4;index;not null;comment:药品信息ID"` // 药品信息ID
+	TotalIn        int    `json:"totalIn" gorm:"size:11;"`                                // 入库数量
+	StockInID      int    `json:"stockInId" gorm:"size:11;"`                              // 入库ID
+	TotalOut       int    `json:"totalOut" gorm:"size:11;"`                               // 出库数量
+	StockOutID     int    `json:"stockOutId" gorm:"size:11;"`                             // 出库ID
+	Balance        int    `json:"balance" gorm:"size:11;"`                                // 结余数量
+	ForwardingUnit string `json:"forwardingUnit" gorm:"size:128;"`                        // 发货单位
+	ReceivingUnit  string `json:"receivingUnit" gorm:"size:128;"`                         // 收货单位
+	Operator       string `json:"operator" gorm:"size:128;"`                              // 经办人
+	Date           string `json:"date" gorm:"size:128;"`                                  // 日期
 
 	model2.ControlBy
 	model2.ModelTime

+ 6 - 3
models/medicine_template.go

@@ -13,7 +13,8 @@ const (
 	FieldUnitID              = "unit_id"              // 单位id
 	FieldDosageFormID        = "dosage_form_id"       //  剂型id
 	FieldBatchNumber         = "batch_number"         // 批号
-	FieldExpiryDate          = "expiry_date"          // 过期时间
+	FieldExpiryDate          = "expiry_date"          // 失效日期
+	FieldProducedDate        = "produced_date"        // 生产日期
 	FieldApprovalNumber      = "approval_number"      // 批准文号
 	FieldQualificationNumber = "qualification_number" // 批签发合格编号
 
@@ -52,7 +53,8 @@ func GetInitMedicineTemplateInfo(deptId, CreateBy int) []MedicineTemplate {
 		{Type: 2, Name: "生产企业", FieldName: FieldEnterpriseID, Show: 1, State: 1, Sort: -8, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
 		{Type: 3, Name: "规格", FieldName: FieldSpecID, Show: 1, State: 1, Sort: -7, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
 		{Type: 6, Name: "批号", FieldName: FieldBatchNumber, Show: 1, State: 1, Sort: -6, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
-		{Type: 9, Name: "效期", FieldName: FieldExpiryDate, Show: 1, State: 1, Sort: -5, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
+		{Type: 9, Name: "失效日期", FieldName: FieldExpiryDate, Show: 1, State: 1, Sort: -5, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
+		{Type: 9, Name: "生产日期", FieldName: FieldProducedDate, Show: 1, State: 1, Sort: -5, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
 		{Type: 6, Name: "批准文号", FieldName: FieldApprovalNumber, Show: 1, State: 1, Sort: -4, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
 		{Type: 5, Name: "剂型", FieldName: FieldDosageFormID, Show: 1, State: 1, Sort: -3, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
 		{Type: 4, Name: "单位", FieldName: FieldUnitID, Show: 1, State: 1, Sort: -2, ControlBy: model2.ControlBy{CreateBy: CreateBy, DeptId: deptId}},
@@ -70,7 +72,8 @@ func GetInitMedicineTemplateSql(deptId int) string {
 		unit_id INT comment '单位ID',
 		dosage_form_id INT comment '剂型ID',
         batch_number VARCHAR(256) comment '批号',
-        expiry_date DATE comment '效期',
+        expiry_date DATE comment '失效日期',
+        produced_date DATE comment '生产日期',
         approval_number VARCHAR(256) comment '批准文号',
         qualification_number VARCHAR(256) comment '批签发编号',
         purchase_unit_price DECIMAL(10,2) comment '购进单价',

+ 2 - 0
routers/medicine_template.go

@@ -15,6 +15,8 @@ func init() {
 		beego.NSRouter("/columns", &controllers.MedicineTemplateController{}, "*:Columns"),
 		beego.NSRouter("/list-for-stock", &controllers.MedicineTemplateController{}, "*:ListForStock"),
 		beego.NSRouter("/list-for-stock-out", &controllers.MedicineTemplateController{}, "*:ListForStockOut"),
+		beego.NSRouter("/scan-code/stock-in-list", &controllers.MedicineTemplateController{}, "*:ListForStockInScanCode"),   // 扫码入库列表
+		beego.NSRouter("/scan-code/stock-out-list", &controllers.MedicineTemplateController{}, "*:ListForStockOutScanCode"), // 扫码出库列表
 	)
 
 	//注册 namespace

+ 2 - 0
routers/stock.go

@@ -22,6 +22,8 @@ func init() {
 		beego.NSRouter("/inventory/export", &controllers.StockTemplateController{}, "*:StockTemplateInventoryExport"), // 库存 - excel
 		beego.NSRouter("/inventory/pdf", &controllers.StockTemplateController{}, "*:InventoryPdf"),
 		beego.NSRouter("/transport-record/export", &controllers.StockTemplateController{}, "*:TransportRecordExport"),
+		beego.NSRouter("/scan-code-in", &controllers.StockTemplateController{}, "*:StockTemplateInScanCode"),   // 扫码入库
+		beego.NSRouter("/scan-code-out", &controllers.StockTemplateController{}, "*:StockTemplateOutScanCode"), // 扫码出库
 	)
 	stock := beego.NewNamespace("/api/stock",
 		beego.NSRouter("/unit/list", &controllers.StockTemplateController{}, "*:StockUnitList"),         // 收/发货单位列表

+ 77 - 2
services/medicine_template.go

@@ -101,6 +101,44 @@ func (e *MedicineTemplate) ListForStock(list *[]dto.MedicineTemplateForStockRes,
 
 	return nil
 }
+func (e *MedicineTemplate) ListForStockInScanCode(list *[]dto.MedicineTemplateForStockRes, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data models.MedicineTemplate
+
+	err = db.DB.Model(&data).
+		Scopes(
+			actions.Permission(data.TableName(), p),
+		).
+		Order("sort").
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		logs.Error("db error: %s ", err)
+		return global.GetFailedErr
+	}
+	for i := 0; i < len(*list); i++ {
+		switch (*list)[i].Type {
+		case 1:
+			(*list)[i].Type = 6
+			(*list)[i].FieldName = models.FieldProductName
+		case 2:
+			(*list)[i].Type = 6
+			(*list)[i].FieldName = models.FieldEnterpriseName
+		case 3:
+			(*list)[i].Type = 6
+			(*list)[i].FieldName = models.FieldSpecName
+		case 4:
+			(*list)[i].Type = 6
+			(*list)[i].FieldName = models.FieldDosageFormName
+		case 5:
+			(*list)[i].Type = 6
+			(*list)[i].FieldName = models.FieldUnitName
+		}
+
+	}
+
+	return nil
+}
 func (e *MedicineTemplate) ListForStockOut(res *[]dto.MedicineTemplateForStockRes, count *int64, p *actions.DataPermission) error {
 	var err error
 	var data models.MedicineTemplate
@@ -145,8 +183,45 @@ func (e *MedicineTemplate) ListForStockOut(res *[]dto.MedicineTemplateForStockRe
 		if list[i].FieldName != models.FieldProductID &&
 			list[i].FieldName != models.FieldEnterpriseID &&
 			list[i].FieldName != models.FieldSpecID &&
-			list[i].FieldName != models.FieldBatchNumber &&
-			list[i].FieldName != models.FieldExpiryDate {
+			list[i].FieldName != models.FieldBatchNumber {
+			continue
+		}
+		*res = append(*res, v)
+	}
+	*count = int64(len(*res))
+	return nil
+}
+func (e *MedicineTemplate) ListForStockOutScanCode(res *[]dto.MedicineTemplateForStockRes, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data models.MedicineTemplate
+	var list []dto.MedicineTemplateForStockRes
+	err = db.DB.Model(&data).
+		Scopes(actions.Permission(data.TableName(), p)).
+		Order("sort").
+		Find(&list).Error
+	if err != nil {
+		logs.Error("db error: %s ", err)
+		return global.GetFailedErr
+	}
+	for i := 0; i < len(list); i++ {
+		switch list[i].Type {
+		case 1:
+			list[i].Type = 6
+			list[i].FieldName = models.FieldProductName
+		case 2:
+			list[i].Type = 6
+			list[i].FieldName = models.FieldEnterpriseName
+		case 3:
+			list[i].Type = 6
+			list[i].FieldName = models.FieldSpecName
+		}
+	}
+
+	for i, v := range list {
+		if list[i].FieldName != models.FieldProductName &&
+			list[i].FieldName != models.FieldEnterpriseName &&
+			list[i].FieldName != models.FieldSpecName &&
+			list[i].FieldName != models.FieldBatchNumber {
 			continue
 		}
 		*res = append(*res, v)

+ 2 - 0
services/sales.go

@@ -184,6 +184,8 @@ func (e *Sales) SalesOrderList(c *dto.SalesOrderPageReq, deptId int) (list []map
 		if id, ok := list[i][models.FieldDosageFormID]; ok {
 			list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id))
 		}
+
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
 	}
 	return list, count, nil
 }

+ 336 - 27
services/stock_template.go

@@ -12,9 +12,9 @@ import (
 	"fmt"
 	"github.com/beego/beego/v2/core/logs"
 	"gorm.io/gorm"
+	"sort"
 	"strconv"
 	"strings"
-	"time"
 )
 
 type StockTemplate struct {
@@ -32,6 +32,88 @@ func (e *StockTemplate) GetMedicineInfo(deptId int, medicine map[string]interfac
 	return
 }
 
+// FirstOrCreateMedicineInfo 查询或创建 品名、生产企业、规格、单位、剂型
+func (e *StockTemplate) FirstOrCreateMedicineInfo(deptId, createBy int, medicine *map[string]interface{}) (err error) {
+	// 查询或创建品名
+	product := models.Product{}
+	if productName, ok := (*medicine)[models.FieldProductName].(string); ok && len(productName) > 0 {
+		err = db.DB.Attrs(map[string]interface{}{"create_by": createBy}).FirstOrCreate(&product, map[string]interface{}{
+			"name":    productName,
+			"dept_id": deptId,
+		}).Error
+
+		if err != nil {
+			return errors.New("获取品名失败")
+		}
+		delete(*medicine, models.FieldProductName)
+	} else {
+		return errors.New("品名不能为空")
+	}
+	// 查询或创建生产企业
+	enterprise := models.Enterprise{}
+	if enterpriseName, ok := (*medicine)[models.FieldEnterpriseName].(string); ok && len(enterpriseName) > 0 {
+		err = db.DB.Attrs(map[string]interface{}{"create_by": createBy}).FirstOrCreate(&enterprise, map[string]interface{}{
+			"name":    enterpriseName,
+			"dept_id": deptId,
+		}).Error
+		if err != nil {
+			return errors.New("获取生产企业失败")
+		}
+		delete(*medicine, models.FieldEnterpriseName)
+	} else {
+		return errors.New("生产企业不能为空")
+	}
+
+	// 查询或创建规格
+	spec := models.Spec{}
+	if specName, ok := (*medicine)[models.FieldSpecName].(string); ok && len(specName) > 0 {
+		err = db.DB.Attrs(map[string]interface{}{"create_by": createBy}).FirstOrCreate(&spec, map[string]interface{}{
+			"name":    specName,
+			"dept_id": deptId,
+		}).Error
+		if err != nil {
+			return errors.New("获取规格失败")
+		}
+		delete(*medicine, models.FieldSpecName)
+	} else {
+		return errors.New("规格不能为空")
+	}
+
+	// 查询或创建单位
+	unit := models.Unit{}
+	if unitName, ok := (*medicine)[models.FieldUnitName].(string); ok && len(unitName) > 0 {
+		err = db.DB.Attrs(map[string]interface{}{"create_by": createBy}).FirstOrCreate(&unit, map[string]interface{}{
+			"name":    unitName,
+			"dept_id": deptId,
+		}).Error
+		if err != nil {
+			return errors.New("获取单位失败")
+		}
+	}
+
+	// 查询或创建剂型
+	dosageForm := models.DosageForm{}
+	if dosageFormName, ok := (*medicine)[models.FieldDosageFormName].(string); ok && len(dosageFormName) > 0 {
+		err = db.DB.Attrs(map[string]interface{}{"create_by": createBy}).FirstOrCreate(&dosageForm, map[string]interface{}{
+			"name":    dosageFormName,
+			"dept_id": deptId,
+		}).Error
+		if err != nil {
+			return errors.New("获取剂型失败")
+		}
+	}
+	delete(*medicine, models.FieldUnitName)
+	delete(*medicine, models.FieldDosageFormName)
+
+	(*medicine)[models.FieldProductID] = product.Id
+	(*medicine)[models.FieldEnterpriseID] = enterprise.Id
+	(*medicine)[models.FieldSpecID] = spec.Id
+	(*medicine)[models.FieldUnitID] = unit.Id
+	(*medicine)[models.FieldDosageFormID] = dosageForm.Id
+
+	return
+}
+
 // BatchStockTemplateIn 批量入库
 func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsertReq) error {
 	//var err error
@@ -135,6 +217,118 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 	return nil
 }
 
+// BatchStockTemplateIn 扫码入库
+func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInInsertReq) error {
+	//var err error
+	tx := db.DB.Begin()
+
+	for _, c := range req.StockInList {
+
+		// 检查药品信息是否已存在
+		err := e.FirstOrCreateMedicineInfo(req.DeptId, req.CreateBy, &c.MedicineInfo)
+		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+			tx.Rollback()
+			logs.Error("【扫码入库】初始化药品信息失败:%s", err)
+			return err
+		}
+
+		// 检查药品信息是否已存在
+		medicineInfo, err := e.GetMedicineInfo(req.DeptId, c.MedicineInfo)
+		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		var medicineInfoId int
+
+		// 如果药品信息不存在,则创建新的药品信息
+		if medicineInfo == nil {
+			sql := "INSERT INTO " + models.GetMedicineInfoTableName(req.DeptId) + " SET "
+			for k, v := range c.MedicineInfo {
+				sql += fmt.Sprintf("`%s`='%v',", k, v)
+			}
+			sql += fmt.Sprintf("`%s`='%v',", "purchase_unit_price", c.UnitPrice)
+
+			sql = sql[:len(sql)-1]
+			err = tx.Exec(sql).Error
+			if err != nil {
+				tx.Rollback()
+				logs.Error("db error: %s", err)
+				return global.CreateFailedErr
+			}
+			err = tx.Raw("SELECT LAST_INSERT_ID()").Scan(&medicineInfoId).Error
+			if err != nil {
+				tx.Rollback()
+				logs.Error("db error: %s", err)
+				return global.CreateFailedErr
+			}
+		} else {
+			medicineInfoId = utils.ToInt(medicineInfo["id"])
+			err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("purchase_unit_price", c.UnitPrice).Error
+			if err != nil {
+				tx.Rollback()
+				logs.Error("db error: %s", err)
+				return global.CreateFailedErr
+			}
+		}
+
+		// 进行入库操作
+		stockInRecord := models.StockIn{
+			MedicineID:     medicineInfoId,
+			Quantity:       c.Quantity,
+			UnitPrice:      c.UnitPrice,
+			Operator:       c.Operator,
+			ForwardingUnit: c.ForwardingUnit,
+			Date:           c.Date,
+			ControlBy: model2.ControlBy{
+				DeptId:   req.DeptId,
+				CreateBy: req.CreateBy,
+			},
+		}
+		err = tx.Create(&stockInRecord).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		c.Id = stockInRecord.Id
+
+		var inventory models.MedicineInventory
+		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+
+		// 添加库存记录
+		data := models.MedicineInventory{
+			MedicineID:     medicineInfoId,
+			TotalIn:        c.Quantity,
+			StockInID:      stockInRecord.Id,
+			TotalOut:       0,
+			StockOutID:     0,
+			Balance:        inventory.Balance + c.Quantity,
+			ForwardingUnit: c.ForwardingUnit,
+			Operator:       c.Operator,
+			Date:           c.Date,
+			ControlBy: model2.ControlBy{
+				DeptId:   req.DeptId,
+				CreateBy: req.CreateBy,
+			},
+		}
+		err = tx.Create(&data).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+	}
+
+	tx.Commit()
+	return nil
+}
+
 // StockTemplateIn 入库
 func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 	var err error
@@ -231,7 +425,8 @@ func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 	}
 	tx.Commit()
 	return nil
-} // StockTemplateIn 入库
+}
+
 func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error {
 	var err error
 	// 检查药品信息是否已存在
@@ -920,6 +1115,108 @@ func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInse
 	return nil
 }
 
+// StockTemplateOutScanCode 扫码出库
+func (e *StockTemplate) StockTemplateOutScanCode(req *dto.BatchStockTemplateOutInsertReq) error {
+	tx := db.DB.Begin()
+	for _, c := range req.StockOutList {
+		// 初始化药品信息
+		err := e.FirstOrCreateMedicineInfo(req.DeptId, req.CreateBy, &c.MedicineInfo)
+		if err != nil {
+			tx.Rollback()
+			logs.Error("【扫码出库】初始化药品信息失败: %s", err)
+			return err
+		}
+		// 检查药品信息是否已存在
+		medicineInfo, err := e.GetMedicineInfo(req.DeptId, c.MedicineInfo)
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		// 如果药品信息不存在,则不能出库
+		if medicineInfo == nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return errors.New("药品信息不存在,禁止出库")
+		}
+		medicineInfoId := utils.ToInt(medicineInfo["id"])
+
+		// 查询库查询信息
+		var mi models.MedicineInventory
+		err = tx.Model(mi).Where("medicine_id = ? AND dept_id = ?", medicineInfoId, req.DeptId).Last(&mi).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		if mi.Balance < c.Quantity {
+			tx.Rollback()
+			return errors.New(fmt.Sprintf("【%s】库存量【%d】小于出库库存量【%d】,出库失败", c.MedicineInfo[models.FieldProductName], mi.Balance, c.Quantity))
+		}
+
+		err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("sales_unit_price", c.UnitPrice).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		// 进行出库操作
+		stockOutRecord := models.StockOut{
+			MedicineID:    medicineInfoId,
+			Quantity:      c.Quantity,
+			UnitPrice:     c.UnitPrice,
+			Operator:      c.Operator,
+			ReceivingUnit: c.ReceivingUnit,
+			Date:          c.Date,
+			ControlBy: model2.ControlBy{
+				DeptId:   req.DeptId,
+				CreateBy: req.CreateBy,
+			},
+		}
+		err = tx.Create(&stockOutRecord).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+		c.Id = stockOutRecord.Id
+
+		var inventory models.MedicineInventory
+		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+
+		// 添加库存记录
+		data := models.MedicineInventory{
+			MedicineID:    medicineInfoId,
+			TotalIn:       0,
+			StockInID:     0,
+			TotalOut:      c.Quantity,
+			StockOutID:    stockOutRecord.Id,
+			Balance:       inventory.Balance - c.Quantity,
+			ReceivingUnit: c.ReceivingUnit,
+			Operator:      c.Operator,
+			Date:          c.Date,
+			ControlBy: model2.ControlBy{
+				DeptId:   req.DeptId,
+				CreateBy: req.CreateBy,
+			},
+		}
+		err = tx.Create(&data).Error
+		if err != nil {
+			tx.Rollback()
+			logs.Error("db error: %s", err)
+			return global.CreateFailedErr
+		}
+	}
+
+	tx.Commit()
+	return nil
+}
+
 // StockTemplateInList 出库列表
 func (e *StockTemplate) StockTemplateInList(c *dto.StockTemplateInPageReq, deptId int) (list []map[string]interface{}, count int64, err error) {
 
@@ -981,9 +1278,8 @@ func (e *StockTemplate) StockTemplateInList(c *dto.StockTemplateInPageReq, deptI
 				list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id))
 			}
 		}
-		if date, ok := list[i][models.FieldExpiryDate]; ok && date != nil {
-			list[i][models.FieldExpiryDate] = date.(time.Time).Format("2006-01-02")
-		}
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
+		list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate])
 	}
 	return list, count, nil
 }
@@ -1050,9 +1346,7 @@ func (e *StockTemplate) StockTemplateOutList(c *dto.StockTemplateOutPageReq, dep
 			}
 		}
 
-		if date, ok := list[i][models.FieldExpiryDate]; ok && date != nil {
-			list[i][models.FieldExpiryDate] = date.(time.Time).Format("2006-01-02")
-		}
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
 	}
 	return list, count, nil
 }
@@ -1110,9 +1404,7 @@ func (e *StockTemplate) StockTemplateInventoryList(c *dto.StockTemplateInventory
 		if id, ok := list[i][models.FieldDosageFormID]; ok {
 			list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id))
 		}
-		if date, ok := list[i][models.FieldExpiryDate]; ok && date != nil {
-			list[i][models.FieldExpiryDate] = date.(time.Time).Format("2006-01-02")
-		}
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
 	}
 	return list, count, nil
 }
@@ -1308,9 +1600,7 @@ func (e *StockTemplate) StockInquiryList(c *dto.StockStatListReq, deptId int) (l
 		if id, ok := list[i][models.FieldDosageFormID]; ok {
 			list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id))
 		}
-		if date, ok := list[i][models.FieldExpiryDate]; ok && date != nil {
-			list[i][models.FieldExpiryDate] = date.(time.Time).Format("2006-01-02")
-		}
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
 	}
 	return list, count, nil
 
@@ -1364,9 +1654,7 @@ func (e *StockTemplate) StockInquiryExcel(c *dto.StockStatListReq, deptId int) (
 		if id, ok := list[i][models.FieldDosageFormID]; ok {
 			list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id))
 		}
-		if date, ok := list[i][models.FieldExpiryDate]; ok && date != nil {
-			list[i][models.FieldExpiryDate] = date.(time.Time).Format("2006-01-02")
-		}
+		list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate])
 	}
 	return list, nil
 
@@ -1385,15 +1673,6 @@ func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[s
 	sql := "SELECT mi.balance,m_info.product_id,m_info.spec_id,m_info.unit_id FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
 		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql
-	//sqlWhereCount := "SELECT COUNT(1) FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory GROUP BY medicine_id) AS mi_latest " +
-	//	"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
-	//	"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql
-
-	//err = db.DB.Raw(sqlWhereCount).Scan(&count).Error
-	//if err != nil {
-	//	logs.Error("db error: %s ", err)
-	//	return list, count, global.GetFailedErr
-	//}
 
 	err = db.DB.Raw(sql).Scan(&result).Error
 	if err != nil {
@@ -1403,6 +1682,7 @@ func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[s
 
 	models.InitBasicData(deptId)
 	statMap := map[string]int{}
+	unitMap := map[string]string{}
 	for i := 0; i < len(result); i++ {
 
 		key := fmt.Sprintf("%v-%v", result[i][models.FieldProductID], result[i][models.FieldSpecID])
@@ -1412,20 +1692,49 @@ func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[s
 		} else {
 			statMap[key] = utils.ToInt(result[i]["balance"])
 		}
+
+		if result[i][models.FieldUnitID] != nil && utils.ToInt(result[i][models.FieldUnitID]) != 0 {
+			if v, ok := unitMap[key]; ok {
+				id := fmt.Sprintf("|%v|", result[i][models.FieldUnitID])
+				if strings.Contains(v, id) {
+					unitMap[key] = v + id
+				}
+
+			} else {
+				unitMap[key] = fmt.Sprintf("|%v|", result[i][models.FieldUnitID])
+			}
+		}
 	}
 	models.InitBasicData(deptId)
 	for key, num := range statMap {
 		product_id := utils.ToInt(strings.Split(key, "-")[0])
 		spec_id := utils.ToInt(strings.Split(key, "-")[1])
+		unit_ids := []string{}
+		if len(unitMap[key]) > 0 {
+			unit_ids = strings.Split(strings.Trim(unitMap[key], "|"), "|")
+		}
+		unit_name := ""
+		unit_ids_int := []int{}
+		for _, id := range unit_ids {
+
+			unit_name += models.Read_Unit_Get(utils.ToInt(id))
+			unit_name += "/"
+			unit_ids_int = append(unit_ids_int, utils.ToInt(id))
+		}
+		unit_name = strings.Trim(unit_name, "/")
 		list = append(list, map[string]interface{}{
 			"product_id":   product_id,
 			"product_name": models.Read_Product_Get(product_id),
 			"spec_id":      spec_id,
 			"spec_name":    models.Read_Spec_Get(spec_id),
 			"balance":      num,
+			"unit_name":    unit_name,
+			"unit_ids":     unit_ids_int,
 		})
 	}
-
+	sort.Slice(list, func(i, j int) bool {
+		return utils.ToInt(list[i]["product_id"]) < utils.ToInt(list[j]["product_id"])
+	})
 	return list, count, nil
 
 }

+ 16 - 0
utils/comm.go

@@ -16,6 +16,7 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"time"
 	"unicode"
 )
 
@@ -237,6 +238,21 @@ func ToFloat64(value interface{}) float64 {
 	return key_float64
 }
 
+func ToDate(value interface{}) string {
+	var key string
+	if value == nil {
+		return key
+	}
+	switch value.(type) {
+	case time.Time:
+		key = value.(time.Time).Format("2006-01-02")
+	default:
+		newValue, _ := json.Marshal(value)
+		key = string(newValue)
+	}
+	return key
+}
+
 // IsChineseOnly 判断字符串是否只包含中文字符
 func IsChineseOnly(s string) bool {
 	chineseRegexp := regexp.MustCompile("^[\\p{Han}]+$")