package services import ( cDto "Medical_ERP/common/dto" "Medical_ERP/common/global" db "Medical_ERP/common/initialize" model2 "Medical_ERP/common/model" "Medical_ERP/dto" "Medical_ERP/models" "Medical_ERP/utils" "errors" "fmt" "github.com/beego/beego/v2/core/logs" "gorm.io/gorm" "math/rand" "sort" "strconv" "strings" "time" ) type StockTemplate struct { } func (e *StockTemplate) GetStockNumber(stock string) (number string, err error) { switch stock { case models.TypeStockIn: var stockIn models.StockIn for { rand.New(rand.NewSource(time.Now().UnixNano())) // 生成随机数后八位 randomSuffix := rand.Intn(99999999) // 格式化年月日 date := time.Now().Format("20060102") // 组合成16位随机数 randomNumber := fmt.Sprintf("%s%08d", date, randomSuffix) // 查询数据库,检查随机数是否存在 if err = db.DB.Where("number = ?", randomNumber).First(&stockIn).Error; err != nil { if err == gorm.ErrRecordNotFound { return "RK" + randomNumber, nil } else { logs.Error("db error: %s", err) return number, err } } } case models.TypeStockOut: var stockOut models.StockOut for { rand.New(rand.NewSource(time.Now().UnixNano())) // 生成随机数后八位 randomSuffix := rand.Intn(99999999) // 格式化年月日 date := time.Now().Format("20060102") // 组合成16位随机数 randomNumber := fmt.Sprintf("%s%08d", date, randomSuffix) // 查询数据库,检查随机数是否存在 if err = db.DB.Where("number = ?", randomNumber).First(&stockOut).Error; err != nil { if err == gorm.ErrRecordNotFound { return "CK" + randomNumber, nil } else { logs.Error("db error: %s", err) return number, err } } } } return number, errors.New("生成随机数失败") } // GetMedicineInfo 通过名称、生产企业、规格、批号查询药品信息 func (e *StockTemplate) GetMedicineInfo(deptId int, medicine map[string]interface{}) (medicineInfo map[string]interface{}, key string, err error) { productID := utils.ToInt(medicine[models.FieldProductID]) enterpriseID := utils.ToInt(medicine[models.FieldEnterpriseID]) specID := utils.ToInt(medicine[models.FieldSpecID]) batchNumber := medicine[models.FieldBatchNumber] sql := `SELECT * FROM ` + models.GetMedicineInfoTableName(deptId) + ` WHERE product_id = ? AND enterprise_id = ? AND spec_id = ? AND batch_number = ? ` err = db.DB.Raw(sql, productID, enterpriseID, specID, batchNumber).Scan(&medicineInfo).Error key = fmt.Sprintf("%d_%d_%d_%d_%s", deptId, productID, enterpriseID, specID, batchNumber) return } func (e *StockTemplate) GetMedicineInfoForImg(medicine map[string]interface{}) (medicineImg models.MedicineImg, err error) { productID := utils.ToInt(medicine[models.FieldProductID]) enterpriseID := utils.ToInt(medicine[models.FieldEnterpriseID]) specID := utils.ToInt(medicine[models.FieldSpecID]) unitID := utils.ToInt(medicine[models.FieldUnitID]) dosageFormID := utils.ToInt(medicine[models.FieldDosageFormID]) batchNumber := utils.ToString(medicine[models.FieldBatchNumber]) medicineImg.BatchNumber = batchNumber medicineImg.ApprovalNumber = utils.ToString(medicine[models.FieldApprovalNumber]) medicineImg.QualificationNumber = utils.ToString(medicine[models.FieldQualificationNumber]) medicineImg.ProductionDate = utils.ToString(medicine[models.FieldProducedDate]) medicineImg.ExpiryDate = utils.ToString(medicine[models.FieldExpiryDate]) product := models.Product{} if err = db.DB.Model(&product).First(&product, productID).Error; err != nil { medicineImg.Product = product.Name } enterprise := models.Enterprise{} if err = db.DB.Model(&enterprise).First(&enterprise, enterpriseID).Error; err != nil { medicineImg.Enterprise = enterprise.Name } spec := models.Spec{} if err = db.DB.Model(&spec).First(&spec, specID).Error; err != nil { medicineImg.Spec = spec.Name } unit := models.Unit{} if unitID > 0 { if err = db.DB.Model(&unit).First(&unit, unitID).Error; err != nil { medicineImg.Unit = unit.Name } } dosageForm := models.DosageForm{} if dosageFormID > 0 { if err = db.DB.Model(&dosageForm).First(&dosageForm, dosageFormID).Error; err != nil { medicineImg.DosageForm = dosageForm.Name } } return } func (e *StockTemplate) GetMedicineInfoScanCodeForImg(medicine map[string]interface{}) (medicineImg models.MedicineImg, err error) { medicineImg.Product = utils.ToString(medicine[models.FieldProductName]) medicineImg.Enterprise = utils.ToString(medicine[models.FieldEnterpriseName]) medicineImg.Spec = utils.ToString(medicine[models.FieldSpecName]) medicineImg.Unit = utils.ToString(medicine[models.FieldUnitName]) medicineImg.DosageForm = utils.ToString(medicine[models.FieldDosageFormName]) medicineImg.BatchNumber = utils.ToString(medicine[models.FieldBatchNumber]) medicineImg.ApprovalNumber = utils.ToString(medicine[models.FieldApprovalNumber]) medicineImg.QualificationNumber = utils.ToString(medicine[models.FieldQualificationNumber]) medicineImg.ProductionDate = utils.ToString(medicine[models.FieldProducedDate]) medicineImg.ExpiryDate = utils.ToString(medicine[models.FieldExpiryDate]) 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 { number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } var medicineInfoMap = make(map[string]int) //var err error tx := db.DB.Begin() for _, c := range req.StockInList { // 检查药品信息是否已存在 medicineInfo, key, 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 var ok bool // 药品已经存在,但因为事务未提交查询不到则直接获取药品信息ID medicineInfoId, ok = medicineInfoMap[key] if !ok { // 如果药品信息不存在,则创建新的药品信息 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',", "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 medicineInfoMap[key] = medicineInfoId if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.CreateFailedErr } // 添加药品图片信息 medicineImg, err := e.GetMedicineInfoForImg(c.MedicineInfo) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("获取药品图片信息失败: %s", err) return global.CreateFailedErr } medicineImg.DeptId = req.DeptId medicineImg.CreateBy = req.CreateBy err = tx.Where(models.MedicineImg{ Product: medicineImg.Product, Enterprise: medicineImg.Enterprise, Spec: medicineImg.Spec, BatchNumber: medicineImg.BatchNumber, ControlBy: model2.ControlBy{ DeptId: req.DeptId, }}). Assign(medicineImg).FirstOrCreate(&medicineImg).Error if err != nil { tx.Rollback() logs.Error("添加药品图片信息失败: %s", err) return global.CreateFailedErr } } else { medicineInfoId = utils.ToInt(medicineInfo["id"]) err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("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, Number: number, State: req.State, 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 = ? and dept_id = ?", medicineInfoId, req.DeptId).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 } func (e *StockTemplate) CheckStockForQrcode(Qrcode string, stock string) error { var err error if !strings.HasPrefix(Qrcode, "9") { return nil } switch stock { case models.TypeStockIn: var stockIn models.StockIn err = db.DB.Where("qrcode = ?", Qrcode).First(&stockIn).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil } return errors.New("通过条码信息查询入库记录失败") } return errors.New(fmt.Sprintf("条码[%s]已入库,禁止重复入库", Qrcode)) case models.TypeStockOut: var stockOut models.StockOut err = db.DB.Where("qrcode = ?", Qrcode).First(&stockOut).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil } return errors.New("通过条码信息查询入库记录失败") } return errors.New(fmt.Sprintf("条码[%s]已出库,禁止重复出库", Qrcode)) } return nil } // BatchStockTemplateIn 扫码入库 func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInInsertReq) error { number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } for _, s := range req.StockInList { err := e.CheckStockForQrcode(s.Qrcode, models.TypeStockIn) if err != nil { return err } } var medicineInfoMap = make(map[string]int) //var err error tx := db.DB.Begin() for i, c := range req.StockInList { mi := make(map[string]interface{}) for k, v := range c.MedicineInfo { mi[k] = v } if qrcode, ok := c.MedicineInfo["qrcode"].(string); ok && len(qrcode) > 0 && len(req.StockInList[i].Qrcode) == 0 { c.Qrcode = qrcode } // 检查药品信息是否已存在 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, key, 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 var ok bool // 药品已经存在,但因为事务未提交查询不到则直接获取药品信息ID medicineInfoId, ok = medicineInfoMap[key] if !ok { // 如果药品信息不存在,则创建新的药品信息 if medicineInfo == nil { sql := "INSERT INTO " + models.GetMedicineInfoTableName(req.DeptId) + " SET " for k, v := range c.MedicineInfo { // 不是系统初始化字段 if !models.GetMedicineInfoFieldIsSysInit(k) { continue } if v == nil { continue } sql += fmt.Sprintf("`%s`='%v',", k, v) } sql += fmt.Sprintf("`%s`='%v',", "unit_price", c.UnitPrice) sql += fmt.Sprintf("`%s`='%v',", "qrcode", c.Qrcode) 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 } medicineInfoMap[key] = medicineInfoId // 添加药品图片信息 medicineImg, err := e.GetMedicineInfoScanCodeForImg(mi) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("获取药品图片信息失败: %s", err) return global.CreateFailedErr } medicineImg.Qrcode = c.Qrcode medicineImg.DeptId = req.DeptId medicineImg.CreateBy = req.CreateBy err = tx.Where(models.MedicineImg{ Product: medicineImg.Product, Enterprise: medicineImg.Enterprise, Spec: medicineImg.Spec, BatchNumber: medicineImg.BatchNumber, ControlBy: model2.ControlBy{ DeptId: req.DeptId, }}). Assign(medicineImg).FirstOrCreate(&medicineImg).Error if err != nil { tx.Rollback() logs.Error("添加药品图片信息失败: %s", err) return global.CreateFailedErr } } else { medicineInfoId = utils.ToInt(medicineInfo["id"]) err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("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, Qrcode: c.Qrcode, Number: number, State: req.State, 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 = ? and dept_id = ?", medicineInfoId, req.DeptId).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 number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } // 检查药品信息是否已存在 medicineInfo, _, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { logs.Error("db error: %s", err) return global.CreateFailedErr } var medicineInfoId int tx := db.DB.Begin() // 如果药品信息不存在,则创建新的药品信息 if medicineInfo == nil { sql := "INSERT INTO " + models.GetMedicineInfoTableName(c.DeptId) + " SET " for k, v := range c.MedicineInfo { sql += fmt.Sprintf("`%s`='%v',", k, v) } sql += fmt.Sprintf("`%s`='%v',", "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 } // 添加药品图片信息 medicineImg, err := e.GetMedicineInfoForImg(c.MedicineInfo) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("获取药品图片信息失败: %s", err) return global.CreateFailedErr } medicineImg.DeptId = c.DeptId medicineImg.CreateBy = c.CreateBy err = tx.Where(models.MedicineImg{ Product: medicineImg.Product, Enterprise: medicineImg.Enterprise, Spec: medicineImg.Spec, BatchNumber: medicineImg.BatchNumber, ControlBy: model2.ControlBy{ DeptId: c.DeptId, }}). Assign(medicineImg).FirstOrCreate(&medicineImg).Error if err != nil { tx.Rollback() logs.Error("添加药品图片信息失败: %s", err) return global.CreateFailedErr } } else { medicineInfoId = utils.ToInt(medicineInfo["id"]) err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Update("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, Number: number, State: c.State, ControlBy: model2.ControlBy{ DeptId: c.DeptId, CreateBy: c.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 = ? and dept_id = ?", medicineInfoId, c.DeptId).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: c.DeptId, CreateBy: c.CreateBy, }, } err = tx.Create(&data).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.CreateFailedErr } tx.Commit() return nil } func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error { var err error // 检查药品信息是否已存在 medicineInfo, _, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { logs.Error("db error: %s", err) return global.UpdateFailedErr } var medicineInfoId int tx := db.DB.Begin() // 如果药品信息不存在,则创建新的药品信息 if medicineInfo == nil { sql := "INSERT INTO " + models.GetMedicineInfoTableName(c.DeptId) + " SET " for k, v := range c.MedicineInfo { sql += fmt.Sprintf("`%s`='%v',", k, v) } sql += fmt.Sprintf("`%s`='%v',", "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.UpdateFailedErr } 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"]) c.MedicineInfo["unit_price"] = c.UnitPrice err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Updates(c.MedicineInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } } var StockInInfo models.StockIn // 查询入库信息 err = tx.Model(StockInInfo).Where("id = ? AND dept_id = ?", c.Id, c.DeptId).Find(&StockInInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 修改入库信息 //stockInRecord := models.StockIn{ // MedicineID: medicineInfoId, // Quantity: c.Quantity, // UnitPrice: c.UnitPrice, // Operator: c.Operator, // ForwardingUnit: c.ForwardingUnit, // Date: c.Date, // ControlBy: model2.ControlBy{ // UpdateBy: c.UpdateBy, // }, //} stockInRecordMap := map[string]interface{}{ "medicine_id": medicineInfoId, "quantity": c.Quantity, "unit_price": c.UnitPrice, "operator": c.Operator, "forwarding_unit": c.ForwardingUnit, "date": c.Date, "update_by": c.UpdateBy, } err = tx.Model(models.StockIn{}).Where("id = ?", c.Id).Updates(stockInRecordMap).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 1 查询收发记录 medicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("stock_in_id = ?", c.Id).First(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 修改为同一药品id if StockInInfo.MedicineID == medicineInfoId { // 数量相等 只更改入库信息 (购入单价、经办人、发货单位、入库日期) if StockInInfo.Quantity != c.Quantity { // 数量不相等 修改收发记录 // 2 修改数量 err = tx.Model(models.MedicineInventory{}).Where("id = ?", medicineInventory.Id).Updates( map[string]interface{}{ "total_in": c.Quantity, "update_by": c.UpdateBy, }).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 3、修改的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity-medicineInventory.TotalIn)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } } } else { // 2 查询收发记录 newMedicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&newMedicineInventory).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 2 修改入库数量、药品id、结余数量 err = tx.Model(models.MedicineInventory{}).Where("id = ?", medicineInventory.Id).Updates( map[string]interface{}{ "medicine_id": medicineInfoId, "total_in": c.Quantity, "balance": newMedicineInventory.Balance + c.Quantity, "update_by": c.UpdateBy, }).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 查询原药品id当前收发记录结余最小值 var balance *int err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)"). Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, StockInInfo.MedicineID, c.DeptId).Scan(&balance).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if balance != nil && *balance-c.Quantity < 0 { tx.Rollback() return errors.New("修改后将导致库存记录数据为负数,禁止修改") } // 3、修改原药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 4、修改新药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } } tx.Commit() return nil } func (e *StockTemplate) StockTemplateInDelete(c *dto.StockTemplateInDeleteReq) error { var err error var StockInInfo models.StockIn tx := db.DB.Begin() // 1 查询入库信息 err = tx.Model(StockInInfo).Where("id = ? AND dept_id = ?", c.Id, c.DeptId).Find(&StockInInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 2 查询收发记录 medicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("stock_in_id = ?", c.Id).First(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 3 查询当前收发记录结余最小值 var balance *int err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)"). Where("id > ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, StockInInfo.MedicineID, c.DeptId).Scan(&balance).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if balance != nil && *balance-medicineInventory.Balance < 0 { tx.Rollback() return errors.New("删除后将导致库存为负数,禁止删除") } // 4 删除收发记录 err = tx.Model(models.MedicineInventory{}).Where("stock_in_id = ?", c.Id).Delete(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 5 删除入库记录 err = tx.Where("id = ?", c.Id).Delete(&StockInInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 6 修改原药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance - ?", medicineInventory.TotalIn)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } tx.Commit() return nil } // StockTemplateOut 出库 func (e *StockTemplate) StockTemplateOut(c *dto.StockTemplateOutInsertReq) error { var err error number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } // 检查药品信息是否已存在 medicineInfo, _, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo) if err != nil { logs.Error("db error: %s", err) return global.CreateFailedErr } // 如果药品信息不存在,则不能出库 if medicineInfo == nil { logs.Error("db error: %s", err) return errors.New("药品信息不存在,禁止出库") } medicineInfoId := utils.ToInt(medicineInfo["id"]) // 查询库查询信息 var mi models.MedicineInventory err = db.DB.Model(mi).Where("medicine_id = ? AND dept_id = ?", medicineInfoId, c.DeptId).Last(&mi).Error if err != nil { logs.Error("db error: %s", err) return global.CreateFailedErr } if mi.Balance < c.Quantity { return errors.New(fmt.Sprintf("库存量【%d】小于出库库存量【%d】,出库失败", mi.Balance, c.Quantity)) } tx := db.DB.Begin() //err = tx.Table(models.GetMedicineInfoTableName(c.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, Number: number, State: c.State, ControlBy: model2.ControlBy{ DeptId: c.DeptId, CreateBy: c.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 = ? and dept_id = ?", medicineInfoId, c.DeptId).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: c.DeptId, CreateBy: c.CreateBy, }, } err = tx.Create(&data).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.CreateFailedErr } tx.Commit() return nil } // StockTemplateOutEdit 修改出库 func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) error { var err error // 检查药品信息是否已存在 medicineInfo, _, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo) if err != nil { logs.Error("db error: %s", err) if errors.Is(err, gorm.ErrRecordNotFound) { return errors.New("药品信息不存在,禁止出库") } else { return global.UpdateFailedErr } } var medicineInfoId int tx := db.DB.Begin() medicineInfoId = utils.ToInt(medicineInfo["id"]) //c.MedicineInfo["sales_unit_price"] = c.UnitPrice err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Updates(c.MedicineInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } var StockOutInfo models.StockOut // 查询出库信息 err = tx.Model(StockOutInfo).Where("id = ? AND dept_id = ?", c.Id, c.DeptId).Find(&StockOutInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } stockOutRecordMap := map[string]interface{}{ "medicine_id": medicineInfoId, "quantity": c.Quantity, //"unit_price": c.UnitPrice, "operator": c.Operator, "receiving_unit": c.ReceivingUnit, "date": c.Date, "update_by": c.UpdateBy, } err = tx.Model(models.StockOut{}).Where("id = ?", c.Id).Updates(stockOutRecordMap).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 1 查询收发记录 medicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("stock_out_id = ?", c.Id).First(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 修改为同一药品id if medicineInventory.MedicineID == medicineInfoId { // 数量相等 只更改入库信息 (购入单价、经办人、发货单位、入库日期) if StockOutInfo.Quantity != c.Quantity { // 查询收发记录 lastMedicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&lastMedicineInventory).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if lastMedicineInventory.Balance < c.Quantity { tx.Rollback() return errors.New("修改后将导致库存记录数据为负数,禁止修改") } // 查询新药品id当前收发记录结余最小值 var balance *int err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)"). Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Scan(&balance).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if balance != nil && *balance-c.Quantity+medicineInventory.TotalOut < 0 { tx.Rollback() return errors.New("修改后将导致库存记录数据为负数,禁止修改") } // 2 修改数量 err = tx.Model(models.MedicineInventory{}).Where("id = ?", medicineInventory.Id).Updates( map[string]interface{}{ "total_out": c.Quantity, "update_by": c.UpdateBy, }).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 3、修改的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity-medicineInventory.TotalOut)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } } } else { // 2 查询收发记录 newMedicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&newMedicineInventory).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if newMedicineInventory.Balance < c.Quantity { tx.Rollback() return errors.New("修改后将导致库存记录数据为负数,禁止修改") } // 3 查询新药品id当前收发记录结余最小值 var balance *int err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)"). Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Scan(&balance).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } if balance != nil && *balance-c.Quantity < 0 { tx.Rollback() return errors.New("修改后将导致库存记录数据为负数,禁止修改") } // 2 修改出库数量、药品id、结余数量 err = tx.Model(models.MedicineInventory{}).Where("id = ?", medicineInventory.Id).Updates( map[string]interface{}{ "medicine_id": medicineInfoId, "total_out": c.Quantity, "balance": newMedicineInventory.Balance - c.Quantity, "update_by": c.UpdateBy, }).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 3、修改原药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } // 4、修改新药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.UpdateFailedErr } } tx.Commit() return nil } // 删除出库 func (e *StockTemplate) StockTemplateOutDelete(c *dto.StockTemplateOutDeleteReq) error { var err error var StockOutInfo models.StockOut tx := db.DB.Begin() // 1 查询入库信息 err = tx.Model(StockOutInfo).Where("id = ? AND dept_id = ?", c.Id, c.DeptId).Find(&StockOutInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 2 查询收发记录 medicineInventory := models.MedicineInventory{} err = tx.Model(models.MedicineInventory{}).Where("stock_out_id = ?", c.Id).First(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 4 删除收发记录 err = tx.Model(models.MedicineInventory{}).Where("stock_out_id = ?", c.Id).Delete(&medicineInventory).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 5 删除入库记录 err = tx.Where("id = ?", c.Id).Delete(&StockOutInfo).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } // 6 修改原药品id的数量差 err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId). UpdateColumn("balance", gorm.Expr("balance + ?", medicineInventory.TotalOut)).Error if err != nil { tx.Rollback() logs.Error("db error: %s", err) return global.DeleteFailedErr } tx.Commit() return nil } // BatchStockTemplateOut 批量出库 func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInsertReq) error { number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } tx := db.DB.Begin() for _, c := range req.StockOutList { // 检查药品信息是否已存在 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("库存量【%d】小于出库库存量【%d】,出库失败", 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, Number: number, State: req.State, 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 = ? and dept_id = ?", medicineInfoId, req.DeptId).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 } // StockTemplateOutScanCode 扫码出库 func (e *StockTemplate) StockTemplateOutScanCode(req *dto.BatchStockTemplateOutInsertReq) error { number, err := e.GetStockNumber(models.TypeStockIn) if err != nil { logs.Error("获取: %s", err) return err } for _, s := range req.StockOutList { err := e.CheckStockForQrcode(s.Qrcode, models.TypeStockOut) if err != nil { return err } } tx := db.DB.Begin() for _, c := range req.StockOutList { medicineName := c.MedicineInfo[models.FieldProductName] // 初始化药品信息 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】,出库失败", medicineName, 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, Qrcode: c.Qrcode, Number: number, State: req.State, 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 = ? and dept_id = ?", medicineInfoId, req.DeptId).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) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_in.dept_id = " + strconv.Itoa(deptId) + " AND state = 1 AND stock_in.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND stock_in.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND stock_in.date <= '" + c.EndDate + "'" } if len(c.ForwardingUnit) > 0 { whereSql += " AND stock_in.forwarding_unit like '%" + c.ForwardingUnit + "%'" } if len(c.Qrcode) > 0 { whereSql += " AND stock_in.qrcode like '%" + c.Qrcode + "%'" } err = db.DB.Table("stock_in"). Select(mtable + ".*,stock_in.*,stock_in.id AS id"). Scopes( cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), ). Joins("left join " + mtable + " on stock_in.medicine_id = " + mtable + ".id"). Where(whereSql). Order("stock_in.date desc,stock_in.id desc"). Scan(&list).Limit(-1).Offset(-1). Count(&count).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldUnitID] = nil } else { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } func (e *StockTemplate) StockTemplateRefundInList(c *dto.StockTemplateInPageReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_in.dept_id = " + strconv.Itoa(deptId) + " AND state = 2 AND stock_in.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND stock_in.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND stock_in.date <= '" + c.EndDate + "'" } if len(c.ForwardingUnit) > 0 { whereSql += " AND stock_in.forwarding_unit like '%" + c.ForwardingUnit + "%'" } if len(c.Qrcode) > 0 { whereSql += " AND stock_in.qrcode like '%" + c.Qrcode + "%'" } err = db.DB.Table("stock_in"). Select(mtable + ".*,stock_in.*,stock_in.id AS id"). Scopes( cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), ). Joins("left join " + mtable + " on stock_in.medicine_id = " + mtable + ".id"). Where(whereSql). Order("stock_in.date desc,stock_in.id desc"). Scan(&list).Limit(-1).Offset(-1). Count(&count).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldUnitID] = nil } else { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } // StockTemplateInList 出库列表 func (e *StockTemplate) StockTemplateOutList(c *dto.StockTemplateOutPageReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state = 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND stock_out.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND stock_out.date <= '" + c.EndDate + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.Qrcode) > 0 { whereSql += " AND stock_out.qrcode like '%" + c.Qrcode + "%'" } err = db.DB.Table("stock_out"). Select(mtable + ".*," + "stock_out.*,stock_out.id AS id," + mtable + ".unit_price as sales_unit_price"). Scopes( cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), ). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Where(whereSql). Order("stock_out.date desc,stock_out.id desc"). Scan(&list).Limit(-1).Offset(-1). Count(&count).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldUnitID] = nil } else { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } func (e *StockTemplate) StockTemplateRefundOutList(c *dto.StockTemplateOutPageReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state > 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND stock_out.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND stock_out.date <= '" + c.EndDate + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.Qrcode) > 0 { whereSql += " AND stock_out.qrcode like '%" + c.Qrcode + "%'" } if c.State > 0 { whereSql += " AND stock_out.state = " + strconv.Itoa(c.State) } err = db.DB.Table("stock_out"). Select(mtable + ".*," + "stock_out.*,stock_out.id AS id," + mtable + ".unit_price as sales_unit_price"). Scopes( cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), ). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Where(whereSql). Order("stock_out.date desc,stock_out.id desc"). Scan(&list).Limit(-1).Offset(-1). Count(&count).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldUnitID] = nil } else { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } // StockTemplateInventoryList 库存统计列表 func (e *StockTemplate) StockTemplateInventoryList(c *dto.StockTemplateInventoryPageReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "medicine_inventory.dept_id = " + strconv.Itoa(deptId) + " AND medicine_inventory.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND medicine_inventory.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND medicine_inventory.date <= '" + c.EndDate + "'" } if len(c.SendReceiveUnit) > 0 { whereSql += " AND (medicine_inventory.forwarding_unit like '%" + c.SendReceiveUnit + "%' OR medicine_inventory.receiving_unit like '%" + c.SendReceiveUnit + "%')" } err = db.DB.Table("medicine_inventory"). Select(mtable + ".*,medicine_inventory.*,medicine_inventory.id AS id"). Scopes( cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), ). Joins("left join " + mtable + " on medicine_inventory.medicine_id = " + mtable + ".id"). Where(whereSql). Scan(&list).Limit(-1).Offset(-1). Count(&count).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } // StockTemplateInventoryList 库存统计列表 func (e *StockTemplate) StockTemplateInventoryExcel(c *dto.StockTemplateInventoryExcelReq, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "medicine_inventory.dept_id = " + strconv.Itoa(deptId) + " AND medicine_inventory.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND " + mtable + ".enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND " + mtable + ".batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND medicine_inventory.date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND medicine_inventory.date <= '" + c.EndDate + "'" } err = db.DB.Table("medicine_inventory"). Joins("left join " + mtable + " on medicine_inventory.medicine_id = " + mtable + ".id"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, nil } // StockUnitList 发货单位,收货单位 去重列表 func (e *StockTemplate) StockUnitList(c *dto.StockUnitListReq, deptId int) (list []string, err error) { whereSql := "dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null" switch c.Type { case 1: if len(c.Name) > 0 { whereSql += " AND forwarding_unit like '%" + c.Name + "%'" } whereSql += " AND forwarding_unit is not null AND forwarding_unit != ''" err = db.DB.Table("stock_in"). Distinct("forwarding_unit"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } return case 2: if len(c.Name) > 0 { whereSql += " AND receiving_unit like '%" + c.Name + "%'" } whereSql += " AND receiving_unit is not null AND receiving_unit != ''" err = db.DB.Table("stock_out"). Distinct("receiving_unit"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } return default: if len(c.Name) > 0 { whereSql += " AND (forwarding_unit like '%" + c.Name + "%' OR receiving_unit like '%" + c.Name + "%')" } forwarding_unit, receiving_unit := []string{}, []string{} err = db.DB.Table("medicine_inventory"). Distinct("forwarding_unit"). Where(whereSql + " AND forwarding_unit is not null AND forwarding_unit != ''"). Scan(&forwarding_unit).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } err = db.DB.Table("medicine_inventory"). Distinct("receiving_unit"). Where(whereSql + " AND receiving_unit is not null AND receiving_unit != ''"). Scan(&receiving_unit).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } list = append(forwarding_unit, receiving_unit...) return } } func (e *StockTemplate) StockOperatorList(c *dto.StockOperatorListReq, deptId int) (list []string, err error) { whereSql := "dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null" if len(c.Name) > 0 { whereSql += " AND operator like '%" + c.Name + "%'" } err = db.DB.Table("medicine_inventory"). Distinct("operator"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } return list, nil } // 库存查询 func (e *StockTemplate) StockInquiryList(c *dto.StockStatListReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "" if c.ProductID > 0 { whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND m_info.enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND m_info.batch_number = '" + c.BatchNumber + "'" } if len(c.StartDate) > 0 { whereSql += " AND m_info.expiry_date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND m_info.expiry_date <= '" + c.EndDate + "'" } if len(whereSql) > 0 { whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ") } offset := (c.Page - 1) * c.PageSize sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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 + " order by m_info.expiry_date limit ? offset ?;" sqlWhereCount := "SELECT COUNT(1) FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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, err } err = db.DB.Raw(sql, c.PageSize, offset).Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, count, err } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, count, nil } func (e *StockTemplate) GetStockInquiry(c *dto.GetStockStatReq, deptId int) (res map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "" if c.ProductID > 0 { whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND m_info.enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if c.SpecID > 0 { whereSql += " AND m_info.spec_id = " + strconv.Itoa(c.SpecID) } if len(c.BatchNumber) > 0 { whereSql += " AND m_info.batch_number = '" + c.BatchNumber + "'" } if len(whereSql) > 0 { whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ") } sql := "SELECT mi.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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 + " order by m_info.expiry_date ;" err = db.DB.Raw(sql).Last(&res).Error if err != nil { logs.Error("db error: %s ", err) if errors.Is(err, gorm.ErrRecordNotFound) { //return res, errors.New("药品信息不存在,查询药品库存失败!") res = make(map[string]interface{}) res["balance"] = 0 return res, nil } return res, global.GetFailedErr } return res, nil } // 库存查询excel func (e *StockTemplate) StockInquiryExcel(c *dto.StockStatListReq, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "" if c.ProductID > 0 { whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID) } if c.EnterpriseID > 0 { whereSql += " AND m_info.enterprise_id = " + strconv.Itoa(c.EnterpriseID) } if len(c.BatchNumber) > 0 { whereSql += " AND m_info.batch_number = " + c.BatchNumber } if len(c.StartDate) > 0 { whereSql += " AND m_info.expiry_date >= '" + c.StartDate + "'" } if len(c.EndDate) > 0 { whereSql += " AND m_info.expiry_date <= '" + c.EndDate + "'" } if len(whereSql) > 0 { whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ") } sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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 + " order by m_info.expiry_date" err = db.DB.Raw(sql).Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, nil } func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "" if c.ProductID > 0 { whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID) } if c.SpecID > 0 { whereSql += " AND m_info.spec_id = " + strconv.Itoa(c.SpecID) } if len(whereSql) > 0 { whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ") } var result []map[string]interface{} 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 WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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(sql).Scan(&result).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } 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]) if num, ok := statMap[key]; ok { statMap[key] = num + utils.ToInt(result[i]["balance"]) } 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 } func (e *StockTemplate) StockHomeStat(deptId int) (list map[string]interface{}, count int64, err error) { mtable := models.GetMedicineInfoTableName(deptId) var result []map[string]interface{} sql := "SELECT mi.balance,m_info.unit_price FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null 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" err = db.DB.Raw(sql).Scan(&result).Error if err != nil { logs.Error("db error: %s ", err) return list, count, global.GetFailedErr } inventoryQuantity := 0 inventoryAmount := 0.0 for i := 0; i < len(result); i++ { unit_price := utils.ToFloat64(result[i]["unit_price"]) inventoryQuantity += utils.ToInt(result[i]["balance"]) inventoryAmount += utils.ToFloat64(inventoryQuantity) * unit_price } var totalOut, totalIn int var totalOutMoney, totalInMoney float64 err = db.DB.Model(models.StockIn{}).Select("COALESCE(SUM(quantity),0)").Where("dept_id = ?", deptId).Scan(&totalIn).Error if err != nil { logs.Error("db error: %s ", err) return list, count, err } err = db.DB.Table("stock_in"). Select("COALESCE(SUM(stock_in.quantity * "+mtable+".unit_price),0)"). Joins("join "+mtable+" on stock_in.medicine_id = "+mtable+".id"). Where("dept_id = ? ", deptId). Scan(&totalInMoney).Error if err != nil { logs.Error("db error: %s ", err) return list, count, err } err = db.DB.Model(models.StockOut{}).Select("COALESCE(SUM(quantity),0)").Where("dept_id = ?", deptId).Scan(&totalOut).Error if err != nil { logs.Error("db error: %s ", err) return list, count, err } err = db.DB.Table("stock_out"). Select("COALESCE(SUM(stock_out.quantity * "+mtable+".unit_price),0)"). Joins("join "+mtable+" on stock_out.medicine_id = "+mtable+".id"). Where("dept_id = ? ", deptId). Scan(&totalOutMoney).Error if err != nil { logs.Error("db error: %s ", err) return list, count, err } list = make(map[string]interface{}) list["inventoryQuantity"] = inventoryQuantity // 库存总量 list["inventoryAmount"] = inventoryAmount // 库存总额(成本金额) list["totalOut"] = totalOut // 出库 list["totalOutMoney"] = totalOutMoney // 出库总金额 list["totalIn"] = totalIn // 入库 list["totalInMoney"] = totalInMoney // 入库总金额 return list, count, nil } func (e *StockTemplate) StockTemplateTransportRecordWord2(c *models.TransportRecord, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state = 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if len(c.Date) > 0 { whereSql += " AND stock_out.date = '" + c.Date + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.StockOutIds) > 0 { whereSql += " AND stock_out.id in (" + strings.Join(utils.IntArrayToStringArray(c.StockOutIds), ",") + ")" } err = db.DB.Table("stock_out"). Select(mtable + ".*,stock_out.quantity as quantity,stock_out.id as stock_out_id," + mtable + ".id as medicine_id"). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } return list, nil } func (e *StockTemplate) StockTemplateTransportRecordWord(c *models.TransportRecord, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state = 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if len(c.Date) > 0 { whereSql += " AND stock_out.date = '" + c.Date + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.StockOutIds) > 0 { whereSql += " AND stock_out.id in (" + strings.Join(utils.IntArrayToStringArray(c.StockOutIds), ",") + ")" } err = db.DB.Table("stock_out"). Select("stock_out.*,stock_out.id as stock_out_id," + mtable + ".*," + mtable + ".id as medicine_id"). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Order("stock_out.date desc,stock_out.id desc"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { list[i]["unit_price"] = utils.ToFloat64(list[i]["unit_price"]) // 金额 list[i]["money"] = utils.ToFloat64(list[i]["unit_price"]) * utils.ToFloat64(list[i]["quantity"]) if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, nil } func (e *StockTemplate) StockRefundOutTransportRecordPdf(c *models.TransportRecord, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state > 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if len(c.Date) > 0 { whereSql += " AND stock_out.date = '" + c.Date + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.StockOutIds) > 0 { whereSql += " AND stock_out.id in (" + strings.Join(utils.IntArrayToStringArray(c.StockOutIds), ",") + ")" } err = db.DB.Table("stock_out"). Select(mtable + ".*," + "stock_out.*,stock_out.id as stock_out_id," + mtable + ".id as medicine_id"). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Order("stock_out.date desc,stock_out.id desc"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { list[i]["unit_price"] = utils.ToFloat64(list[i]["unit_price"]) // 金额 list[i]["money"] = utils.ToFloat64(list[i]["unit_price"]) * utils.ToFloat64(list[i]["quantity"]) if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, nil } func (e *StockTemplate) GetRefundOutBarCodeInfo(c *models.TransportRecord, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state > 1 AND stock_out.deleted_at is null" if c.ProductID > 0 { whereSql += " AND " + mtable + ".product_id = " + strconv.Itoa(c.ProductID) } if len(c.Date) > 0 { whereSql += " AND stock_out.date = '" + c.Date + "'" } if len(c.ReceivingUnit) > 0 { whereSql += " AND stock_out.receiving_unit like '%" + c.ReceivingUnit + "%'" } if len(c.StockOutIds) > 0 { whereSql += " AND stock_out.id in (" + strings.Join(utils.IntArrayToStringArray(c.StockOutIds), ",") + ")" } err = db.DB.Table("stock_out"). Select(mtable + ".*,stock_out.quantity as quantity,stock_out.id as stock_out_id," + mtable + ".id as medicine_id"). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } } return list, nil } func (e *StockTemplate) StockRefundOutPdf(c *dto.StockRefundOutExport, deptId int) (list []map[string]interface{}, err error) { mtable := models.GetMedicineInfoTableName(deptId) whereSql := "stock_out.dept_id = " + strconv.Itoa(deptId) + " AND state > 1 AND stock_out.deleted_at is null" if len(c.StockOutIds) > 0 { whereSql += " AND stock_out.id in (" + strings.Join(utils.IntArrayToStringArray(c.StockOutIds), ",") + ")" } err = db.DB.Table("stock_out"). Select("stock_out.*,stock_out.id as stock_out_id," + mtable + ".*," + mtable + ".id as medicine_id"). Joins("left join " + mtable + " on stock_out.medicine_id = " + mtable + ".id"). Where(whereSql). Scan(&list).Error if err != nil { logs.Error("db error: %s ", err) return list, global.GetFailedErr } models.InitBasicData(deptId) for i := 0; i < len(list); i++ { list[i]["unit_price"] = utils.ToFloat64(list[i]["unit_price"]) // 金额 list[i]["money"] = utils.ToFloat64(list[i]["unit_price"]) * utils.ToFloat64(list[i]["quantity"]) if id, ok := list[i][models.FieldProductID]; ok { list[i][models.FieldProductName] = models.Read_Product_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldEnterpriseID]; ok { list[i][models.FieldEnterpriseName] = models.Read_Enterprise_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldSpecID]; ok { list[i][models.FieldSpecName] = models.Read_Spec_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldUnitID]; ok { list[i][models.FieldUnitName] = models.Read_Unit_Get(utils.ToInt(id)) } if id, ok := list[i][models.FieldDosageFormID]; ok { if utils.ToInt(id) == 0 { list[i][models.FieldDosageFormID] = nil } else { list[i][models.FieldDosageFormName] = models.Read_DosageForm_Get(utils.ToInt(id)) } } list[i][models.FieldExpiryDate] = utils.ToDate(list[i][models.FieldExpiryDate]) list[i][models.FieldProducedDate] = utils.ToDate(list[i][models.FieldProducedDate]) } return list, nil }