package backend import ( "context" "fmt" "kpt-pasture/model" "kpt-pasture/util" "net/http" "time" "gorm.io/gorm" "gitee.com/xuyiping_admin/pkg/xerr" pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow" ) func (s *StoreEntry) DrugsList(ctx context.Context, req *pasturePb.SearchDrugsRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchDrugsResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } drugsList := make([]*model.Drugs, 0) var count int64 = 0 pref := s.DB.Model(new(model.Drugs)).Where("pasture_id = ?", userModel.AppPasture.Id) if req.Name != "" { pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%")) } if req.Usage > 0 { pref.Where("usage_method = ?", req.Usage) } if req.CategoryId > 0 { pref.Where("category_id = ?", req.CategoryId) } if err = pref.Order("id desc").Count(&count).Limit(int(pagination.PageSize)).Offset(int(pagination.PageOffset)). Find(&drugsList).Error; err != nil { return nil, xerr.WithStack(err) } return &pasturePb.SearchDrugsResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchDrugsData{ List: model.DrugsSlice(drugsList).ToPB(), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) DrugsCreateOrUpdate(ctx context.Context, req *pasturePb.SearchDrugsList) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } req.CategoryName = s.DrugCategoryMaps()[req.CategoryId] req.UnitName = s.UnitMap()[req.Unit] req.UsageName = s.DrugUsageMaps()[req.Usage] newDrugs := model.NewDrugs(userModel.AppPasture.Id, req, userModel.SystemUser) if req.Id <= 0 { if err = s.DB.Create(newDrugs).Error; err != nil { return xerr.WithStack(err) } } else { if err = s.DB.Where("id = ?", req.Id).Updates(newDrugs).Error; err != nil { return xerr.WithStack(err) } } return nil } func (s *StoreEntry) MedicalEquipmentList(ctx context.Context, req *pasturePb.SearchMedicalEquipmentRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchMedicalEquipmentResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } medicalEquipmentList := make([]*model.MedicalEquipment, 0) var count int64 = 0 pref := s.DB.Model(new(model.MedicalEquipment)).Where("pasture_id = ?", userModel.AppPasture.Id) if req.Name != "" { pref.Where("name like ?", fmt.Sprintf("%s%s%s", "%", req.Name, "%")) } if err = pref.Order("id desc").Count(&count).Limit(int(pagination.PageSize)).Offset(int(pagination.PageOffset)). Find(&medicalEquipmentList).Error; err != nil { return nil, xerr.WithStack(err) } unitMap := s.UnitMap() return &pasturePb.SearchMedicalEquipmentResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchMedicalEquipmentData{ List: model.MedicalEquipmentSlice(medicalEquipmentList).ToPB(unitMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) MedicalEquipmentCreateOrUpdate(ctx context.Context, req *pasturePb.SearchMedicalEquipmentList) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } newDrugs := model.NewMedicalEquipment(userModel.AppPasture.Id, req, userModel.SystemUser) if req.Id <= 0 { if err = s.DB.Create(newDrugs).Error; err != nil { return xerr.WithStack(err) } } else { if err = s.DB.Where("id = ?", req.Id).Updates(newDrugs).Error; err != nil { return xerr.WithStack(err) } } return nil } func (s *StoreEntry) NeckRingCreateOrUpdate(ctx context.Context, req *pasturePb.NeckRingCreateRequest) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } if req.Items == nil || len(req.Items) == 0 { return xerr.Custom("请选择要脖环数据") } if err = s.DB.Transaction(func(tx *gorm.DB) error { for _, item := range req.Items { number := "" cowInfo, err := s.GetCowInfoByCowId(ctx, userModel.AppPasture.Id, int64(item.CowId)) if err != nil { return xerr.Customf("该牛: %d 不存在", item.CowId) } newNeckRingLog := model.NewNeckRingBindLog(userModel.AppPasture.Id, item.Number, cowInfo, userModel.SystemUser) neckRing, ok, err := s.NeckRingIsExist(ctx, userModel.AppPasture.Id, item.Number) switch req.Status { case pasturePb.NeckRingOperationStatus_Bind: // 绑定 if err != nil { return xerr.WithStack(err) } if ok && neckRing.Status == pasturePb.NeckRingStatus_Bind { return xerr.Customf("该脖环: %s已经绑定牛只: %s", item.Number, neckRing.EarNumber) } newNeckRing := model.NewNeckRing(userModel.AppPasture.Id, item.Number, cowInfo, userModel.SystemUser) if err = tx.Create(newNeckRing).Error; err != nil { return xerr.WithStack(err) } number = item.Number newNeckRingLog.OperationStatusName = "绑定" // 解绑 case pasturePb.NeckRingOperationStatus_UnBind: if ok && neckRing.Status != pasturePb.NeckRingStatus_Bind { return xerr.Customf("该脖环: %s,未绑定牛只", item.Number) } if err = tx.Model(new(model.NeckRing)). Where("id = ?", neckRing.Id). Updates(map[string]interface{}{ "cow_id": 0, "ear_number": "", "wear_at": 0, "status": pasturePb.NeckRingStatus_Unbind, }).Error; err != nil { return xerr.WithStack(err) } newNeckRingLog.OperationStatusName = "解绑" // 编辑 case pasturePb.NeckRingOperationStatus_Edit: if err = tx.Model(new(model.NeckRing)). Where("neck_ring_number = ?", item.Number). Updates(map[string]interface{}{ "cow_id": cowInfo.Id, "ear_number": cowInfo.EarNumber, "wear_at": time.Now().Unix(), "status": pasturePb.NeckRingStatus_Bind, }).Error; err != nil { return xerr.WithStack(err) } number = item.Number newNeckRingLog.OperationStatusName = "编辑" default: continue } if err = tx.Create(newNeckRingLog).Error; err != nil { return xerr.WithStack(err) } if err = tx.Model(new(model.Cow)). Where("id = ?", item.CowId). Update("neck_ring_number", number). Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) NeckRingList(ctx context.Context, req *pasturePb.SearchNeckRingRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchNeckRingResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } neckRingLogList := make([]*model.NeckRing, 0) var count int64 = 0 pref := s.DB.Table(fmt.Sprintf("%s as a", new(model.NeckRing).TableName())). Select("a.*,COALESCE(b.pen_name, '') AS pen_name"). Joins("LEFT JOIN cow as b ON a.cow_id = b.id"). Where("a.status >= ?", pasturePb.NeckRingStatus_Unbind). Where("a.pasture_id = ?", userModel.AppPasture.Id). Where("a.neck_ring_number != ''") if req.Status > 0 { pref.Where("a.status = ?", req.Status) } if req.CowId > 0 { pref.Where("a.cow_id = ?", req.CowId) } if req.Number != "" { pref.Where("a.number like ?", fmt.Sprintf("%s%s%s", "%", req.Number, "%")) } if err = pref.Order("a.id desc"). Count(&count). Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&neckRingLogList).Error; err != nil { return nil, xerr.WithStack(err) } neckRingStatusMap := s.NeckRingStatusMap() return &pasturePb.SearchNeckRingResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchNeckRingData{ List: model.NeckRingSlice(neckRingLogList).ToPB(neckRingStatusMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) OutboundApply(ctx context.Context, req *pasturePb.OutboundApplyItem) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } if len(req.Goods) <= 0 { return xerr.Custom("请选择要出库商品") } var outbound *model.Outbound if req.Id > 0 { outbound, err = s.GetOutboundById(ctx, userModel.AppPasture.Id, int64(req.Id)) if err != nil || outbound == nil || outbound.Id <= 0 { return xerr.Customf("该出库单不存在") } if userModel.SystemUser.Id != int64(outbound.ApplicantId) { return xerr.Custom("非申请人,无权修改该出库单") } if outbound.AuditStatus != pasturePb.AuditStatus_Pending { return xerr.Custom("该出库单不能修改") } } else { // 创建出库申请 outbound = model.NewOutbound(userModel.AppPasture.Id, req, userModel.SystemUser) } goodsItems := make([]*pasturePb.OutboundApplyGoodsItem, 0) switch req.OutType { case pasturePb.OutType_Drugs: for _, v := range req.Goods { if v.Quantity <= 0 { return xerr.Custom("请填写商品数量") } if v.GoodsId <= 0 { return xerr.Custom("请选择要出库商品") } newDrugs := &model.Drugs{} if err = s.DB.Model(new(model.Drugs)). Where("id = ?", v.GoodsId). Where("inventory >= ?", v.Quantity). First(newDrugs).Error; err != nil { return xerr.WithStack(err) } goodsItems = append(goodsItems, &pasturePb.OutboundApplyGoodsItem{ GoodsId: v.GoodsId, Quantity: v.Quantity, Unit: v.Unit, GoodsName: newDrugs.Name, Specs: newDrugs.Specs, Producer: newDrugs.Producer, BatchNumber: newDrugs.BatchNumber, Price: float32(newDrugs.Price) / 100, }) } case pasturePb.OutType_Medical_Equipment: for _, v := range req.Goods { if v.Quantity <= 0 { return xerr.Custom("请填写商品数量") } if v.GoodsId <= 0 { return xerr.Custom("请选择要出库商品") } newMedicalEquipment := &model.MedicalEquipment{} if err = s.DB.Model(new(model.Drugs)). Where("id = ?", v.GoodsId). Where("inventory >= ?", v.Quantity). First(newMedicalEquipment).Error; err != nil { return xerr.WithStack(err) } goodsItems = append(goodsItems, &pasturePb.OutboundApplyGoodsItem{ GoodsId: v.GoodsId, Quantity: v.Quantity, Unit: v.Unit, GoodsName: newMedicalEquipment.Name, Specs: newMedicalEquipment.Specs, Producer: newMedicalEquipment.Producer, BatchNumber: newMedicalEquipment.BatchNumber, Price: float32(newMedicalEquipment.Price) / 100, }) } default: return xerr.Custom("未知的出库类型") } unitMap := s.UnitMap() if err = s.DB.Transaction(func(tx *gorm.DB) error { if req.Id > 0 { if err = tx.Model(new(model.Outbound)). Where("id = ?", req.Id). Update("applicant_remarks", req.ApplicantRemarks).Error; err != nil { return xerr.WithStack(err) } if err = tx.Model(new(model.OutboundDetail)). Where("outbound_id = ?", req.Id). Update("is_delete = ?", pasturePb.IsShow_No).Error; err != nil { return xerr.WithStack(err) } } else { if err = tx.Create(outbound).Error; err != nil { return xerr.WithStack(err) } } outboundLog := model.NewOutboundDetailList(outbound.Id, goodsItems, unitMap) if err = tx.Create(outboundLog).Error; err != nil { return xerr.WithStack(err) } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) OutboundList(ctx context.Context, req *pasturePb.SearchOutboundApplyRequest, pagination *pasturePb.PaginationModel) (*pasturePb.SearchOutboundApplyResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } startUnix := util.TimeParseLocalUnix(req.StartDayTime) endUnix := util.TimeParseLocalEndUnix(req.EndDayTime) var count int64 = 0 outboundList := make([]*model.Outbound, 0) pref := s.DB.Model(new(model.Outbound)).Where("pasture_id = ?", userModel.AppPasture.Id) if req.OutType > 0 { pref.Where("out_type = ?", req.OutType) } if startUnix > 0 && endUnix > 0 && startUnix <= endUnix { pref.Where("applicant_at BETWEEN ? AND ?", startUnix, endUnix) } if req.Number != "" { pref.Where("number like ?", fmt.Sprintf("%s%s%s", "%", req.Number, "%")) } if req.AuditStatus > 0 { pref.Where("audit_status = ?", req.AuditStatus) } if req.ApplicantId > 0 { pref.Where("applicant_id = ?", req.ApplicantId) } if req.ExamineId > 0 { pref.Where("examine_id = ?", req.ExamineId) } if err = pref.Order("id desc"). Count(&count). Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&outboundList).Error; err != nil { return nil, xerr.WithStack(err) } outTypeMap := s.OutTypeMap() auditStatusMap := s.AuditStatusMap() return &pasturePb.SearchOutboundApplyResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchOutboundApplyData{ List: model.OutboundSlice(outboundList).ToPB(outTypeMap, auditStatusMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) OutboundAudit(ctx context.Context, req *pasturePb.OutboundApplyAuditRequest) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } outbound, err := s.GetOutboundById(ctx, userModel.AppPasture.Id, int64(req.Id)) if err != nil { return xerr.WithStack(err) } if outbound == nil { return xerr.Custom("出库单不存在") } if req.AuditStatus != pasturePb.AuditStatus_Pass && req.AuditStatus != pasturePb.AuditStatus_Reject && req.AuditStatus != pasturePb.AuditStatus_Cancel { return xerr.Custom("审核状态异常") } if outbound.AuditStatus != pasturePb.AuditStatus_Pending { return xerr.Custom("异常出库单") } outboundDetails, err := s.GetOutboundDetailByOutboundId(ctx, outbound.Id) if err != nil { return xerr.WithStack(err) } if len(outboundDetails) <= 0 { return xerr.Custom("出库单商品不存在") } if err = s.DB.Transaction(func(tx *gorm.DB) error { if err = tx.Model(outbound). Where("id = ?", outbound.Id). Updates(map[string]interface{}{ "audit_status": req.AuditStatus, "examine_id": userModel.SystemUser.Id, "examine_name": userModel.SystemUser.Name, "examine_remarks": req.ExamineRemarks, "examine_at": time.Now().Unix(), }).Error; err != nil { return xerr.WithStack(err) } if req.AuditStatus != pasturePb.AuditStatus_Pass { return nil } tableName := "" switch outbound.OutType { case pasturePb.OutType_Drugs: tableName = new(model.Drugs).TableName() case pasturePb.OutType_Medical_Equipment: tableName = new(model.MedicalEquipment).TableName() default: return nil } for _, v := range outboundDetails { if err = tx.Table(tableName). Where("id = ?", v.GoodsId). Updates(map[string]interface{}{ "inventory": gorm.Expr("inventory - ?", v.Quantity), }).Error; err != nil { return xerr.WithStack(err) } } return nil }); err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) OutboundDetail(ctx context.Context, id int64) (*pasturePb.OutboundDetailResponse, error) { userModel, err := s.GetUserModel(ctx) if err != nil { return nil, xerr.WithStack(err) } outbound, err := s.GetOutboundById(ctx, userModel.AppPasture.Id, id) if err != nil { return nil, xerr.WithStack(err) } outboundLogs, err := s.GetOutboundDetailByOutboundId(ctx, id) if err != nil { return nil, xerr.WithStack(err) } outTypeMap := s.OutTypeMap() auditStatusMap := s.AuditStatusMap() applicantAtFormat, examineAtFormat := "", "" if outbound.ApplicantAt > 0 { applicantAtFormat = time.Unix(outbound.ApplicantAt, 0).Format(model.LayoutTime) } if outbound.ExamineAt > 0 { examineAtFormat = time.Unix(outbound.ExamineAt, 0).Format(model.LayoutTime) } return &pasturePb.OutboundDetailResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.OutboundApplyDetail{ Id: int32(outbound.Id), Number: outbound.Number, OutType: outbound.OutType, OutTypeName: outTypeMap[outbound.OutType], AuditStatus: outbound.AuditStatus, AuditStatusName: auditStatusMap[outbound.AuditStatus], ApplicantName: outbound.ApplicantName, ApplicantRemarks: outbound.ApplicantRemarks, ExamineName: outbound.ExamineName, ExamineRemarks: outbound.ExamineRemarks, ApplicantAtFormat: applicantAtFormat, ExamineAtFormat: examineAtFormat, GoodsItem: &pasturePb.OutboundApplyItem{ OutType: outbound.OutType, Goods: model.OutboundDetailSlice(outboundLogs).ToPB(), ApplicantRemarks: outbound.ApplicantRemarks, }, }, }, nil } func (s *StoreEntry) OutboundDelete(ctx context.Context, id int64) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } outbound, err := s.GetOutboundById(ctx, userModel.AppPasture.Id, id) if err != nil { return xerr.WithStack(err) } if outbound == nil { return xerr.Custom("出库单不存在") } if !(outbound.AuditStatus == pasturePb.AuditStatus_Pending || outbound.AuditStatus == pasturePb.AuditStatus_Cancel) { return xerr.Custom("出库单无法删除") } if userModel.SystemUser.Id != int64(outbound.ApplicantId) { return xerr.Custom("非申请人,无权删除出库单") } outbound.Delete() if err = s.DB.Model(new(model.Outbound)). Select("audit_status"). Updates(outbound).Error; err != nil { return xerr.WithStack(err) } return nil } func (s *StoreEntry) FrozenSemenList(ctx context.Context, req *pasturePb.FrozenSemenRequest, pagination *pasturePb.PaginationModel) (*pasturePb.FrozenSemenResponse, error) { frozenSemenList := make([]*model.FrozenSemen, 0) var count int64 = 0 pref := s.DB.Table(new(model.FrozenSemen).TableName()) if req.BullId != "" { pref.Where("bull_id = ?", req.BullId) } if req.Producer != "" { pref.Where("producer = ?", req.Producer) } if err := pref.Order("id desc"). Count(&count).Limit(int(pagination.PageSize)). Offset(int(pagination.PageOffset)). Find(&frozenSemenList).Error; err != nil { return nil, xerr.WithStack(err) } frozenSemenTypeMap := s.FrozenSemenTypeMap() unitMap := s.UnitMap() return &pasturePb.FrozenSemenResponse{ Code: http.StatusOK, Msg: "ok", Data: &pasturePb.SearchFrozenSemenData{ List: model.FrozenSemenSlice(frozenSemenList).ToPB(frozenSemenTypeMap, unitMap), Total: int32(count), PageSize: pagination.PageSize, Page: pagination.Page, }, }, nil } func (s *StoreEntry) FrozenSemenCreate(ctx context.Context, req *pasturePb.SearchFrozenSemenList) error { userModel, err := s.GetUserModel(ctx) if err != nil { return xerr.WithStack(err) } req.CowKindName = s.CowKindMap()[req.CowKind] newFrozenSemen := model.NewFrozenSemen(userModel.AppPasture.Id, req, userModel.SystemUser) if err := s.DB.Create(newFrozenSemen).Error; err != nil { return xerr.WithStack(err) } return nil }