猪群相关接口增加当前总量和当前总存栏量

This commit is contained in:
2025-10-23 11:29:48 +08:00
parent c1f71050e9
commit 324a533c94
7 changed files with 158 additions and 86 deletions

View File

@@ -4906,6 +4906,14 @@ const docTemplate = `{
"description": "创建时间", "description": "创建时间",
"type": "string" "type": "string"
}, },
"currentTotalPigsInPens": {
"description": "当前存栏总数",
"type": "integer"
},
"currentTotalQuantity": {
"description": "当前总数",
"type": "integer"
},
"end_date": { "end_date": {
"description": "批次结束日期", "description": "批次结束日期",
"type": "string" "type": "string"

View File

@@ -4898,6 +4898,14 @@
"description": "创建时间", "description": "创建时间",
"type": "string" "type": "string"
}, },
"currentTotalPigsInPens": {
"description": "当前存栏总数",
"type": "integer"
},
"currentTotalQuantity": {
"description": "当前总数",
"type": "integer"
},
"end_date": { "end_date": {
"description": "批次结束日期", "description": "批次结束日期",
"type": "string" "type": "string"

View File

@@ -662,6 +662,12 @@ definitions:
create_time: create_time:
description: 创建时间 description: 创建时间
type: string type: string
currentTotalPigsInPens:
description: 当前存栏总数
type: integer
currentTotalQuantity:
description: 当前总数
type: integer
end_date: end_date:
description: 批次结束日期 description: 批次结束日期
type: string type: string

View File

@@ -32,16 +32,18 @@ type PigBatchQueryDTO struct {
// PigBatchResponseDTO 定义了猪批次信息的响应结构 // PigBatchResponseDTO 定义了猪批次信息的响应结构
type PigBatchResponseDTO struct { type PigBatchResponseDTO struct {
ID uint `json:"id"` // 批次ID ID uint `json:"id"` // 批次ID
BatchNumber string `json:"batch_number"` // 批次编号 BatchNumber string `json:"batch_number"` // 批次编号
OriginType models.PigBatchOriginType `json:"origin_type"` // 批次来源 OriginType models.PigBatchOriginType `json:"origin_type"` // 批次来源
StartDate time.Time `json:"start_date"` // 批次开始日期 StartDate time.Time `json:"start_date"` // 批次开始日期
EndDate time.Time `json:"end_date"` // 批次结束日期 EndDate time.Time `json:"end_date"` // 批次结束日期
InitialCount int `json:"initial_count"` // 初始数量 InitialCount int `json:"initial_count"` // 初始数量
Status models.PigBatchStatus `json:"status"` // 批次状态 Status models.PigBatchStatus `json:"status"` // 批次状态
IsActive bool `json:"is_active"` // 是否活跃 IsActive bool `json:"is_active"` // 是否活跃
CreateTime time.Time `json:"create_time"` // 创建时间 CurrentTotalQuantity int `json:"currentTotalQuantity"` // 当前总数
UpdateTime time.Time `json:"update_time"` // 更新时间 CurrentTotalPigsInPens int `json:"currentTotalPigsInPens"` // 当前存栏总数
CreateTime time.Time `json:"create_time"` // 创建时间
UpdateTime time.Time `json:"update_time"` // 更新时间
} }
// AssignEmptyPensToBatchRequest 用于为猪批次分配空栏的请求体 // AssignEmptyPensToBatchRequest 用于为猪批次分配空栏的请求体

View File

@@ -57,21 +57,23 @@ func NewPigBatchService(domainService domain_pig.PigBatchService, logger *logs.L
} }
// toPigBatchResponseDTO 负责将领域模型转换为应用层DTO这个职责保留在应用层。 // toPigBatchResponseDTO 负责将领域模型转换为应用层DTO这个职责保留在应用层。
func (s *pigBatchService) toPigBatchResponseDTO(batch *models.PigBatch) *dto.PigBatchResponseDTO { func (s *pigBatchService) toPigBatchResponseDTO(batch *models.PigBatch, currentTotalQuantity, currentTotalPigsInPens int) *dto.PigBatchResponseDTO {
if batch == nil { if batch == nil {
return nil return nil
} }
return &dto.PigBatchResponseDTO{ return &dto.PigBatchResponseDTO{
ID: batch.ID, ID: batch.ID,
BatchNumber: batch.BatchNumber, BatchNumber: batch.BatchNumber,
OriginType: batch.OriginType, OriginType: batch.OriginType,
StartDate: batch.StartDate, StartDate: batch.StartDate,
EndDate: batch.EndDate, EndDate: batch.EndDate,
InitialCount: batch.InitialCount, InitialCount: batch.InitialCount,
Status: batch.Status, Status: batch.Status,
IsActive: batch.IsActive(), IsActive: batch.IsActive(),
CreateTime: batch.CreatedAt, CurrentTotalQuantity: currentTotalQuantity,
UpdateTime: batch.UpdatedAt, CurrentTotalPigsInPens: currentTotalPigsInPens,
CreateTime: batch.CreatedAt,
UpdateTime: batch.UpdatedAt,
} }
} }
@@ -94,7 +96,7 @@ func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreat
} }
// 3. 领域模型 -> DTO // 3. 领域模型 -> DTO
return s.toPigBatchResponseDTO(createdBatch), nil return s.toPigBatchResponseDTO(createdBatch, dto.InitialCount, 0), nil
} }
// GetPigBatch 从领域服务获取数据并转换为DTO同时处理错误转换。 // GetPigBatch 从领域服务获取数据并转换为DTO同时处理错误转换。
@@ -104,8 +106,17 @@ func (s *pigBatchService) GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error)
s.logger.Warnf("应用层: 获取猪批次失败, ID: %d, 错误: %v", id, err) s.logger.Warnf("应用层: 获取猪批次失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err) return nil, MapDomainError(err)
} }
currentTotalQuantity, err := s.domainService.GetCurrentPigsInPen(id)
return s.toPigBatchResponseDTO(batch), nil if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetCurrentPigsInPen(id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
return s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens), nil
} }
// UpdatePigBatch 协调获取、更新和保存的流程,并处理错误转换。 // UpdatePigBatch 协调获取、更新和保存的流程,并处理错误转换。
@@ -144,8 +155,20 @@ func (s *pigBatchService) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*
return nil, MapDomainError(err) return nil, MapDomainError(err)
} }
// 4. 转换并返回结果 // 4. 填充猪群信息
return s.toPigBatchResponseDTO(updatedBatch), nil currentTotalQuantity, err := s.domainService.GetCurrentPigsInPen(id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetCurrentPigsInPen(id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
// 5. 转换并返回结果
return s.toPigBatchResponseDTO(updatedBatch, currentTotalQuantity, currentTotalPigsInPens), nil
} }
// DeletePigBatch 将删除操作委托给领域服务,并转换领域错误为应用层错误。 // DeletePigBatch 将删除操作委托给领域服务,并转换领域错误为应用层错误。
@@ -168,7 +191,17 @@ func (s *pigBatchService) ListPigBatches(isActive *bool) ([]*dto.PigBatchRespons
var responseDTOs []*dto.PigBatchResponseDTO var responseDTOs []*dto.PigBatchResponseDTO
for _, batch := range batches { for _, batch := range batches {
responseDTOs = append(responseDTOs, s.toPigBatchResponseDTO(batch)) currentTotalQuantity, err := s.domainService.GetCurrentPigsInPen(batch.ID)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", batch.ID, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetCurrentPigsInPen(batch.ID)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", batch.ID, err)
return nil, MapDomainError(err)
}
responseDTOs = append(responseDTOs, s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens))
} }
return responseDTOs, nil return responseDTOs, nil

View File

@@ -6,7 +6,6 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" "git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"gorm.io/gorm"
) )
// --- 业务错误定义 --- // --- 业务错误定义 ---
@@ -60,6 +59,8 @@ type PigBatchService interface {
GetCurrentPigQuantity(batchID uint) (int, error) GetCurrentPigQuantity(batchID uint) (int, error)
// GetCurrentPigsInPen 获取指定猪栏的当前存栏量。 // GetCurrentPigsInPen 获取指定猪栏的当前存栏量。
GetCurrentPigsInPen(penID uint) (int, error) GetCurrentPigsInPen(penID uint) (int, error)
// GetTotalPigsInPensForBatch 获取指定猪群下所有猪栏的当前总存栏数
GetTotalPigsInPensForBatch(batchID uint) (int, error)
UpdatePigBatchQuantity(operatorID uint, batchID uint, changeType models.LogChangeType, changeAmount int, changeReason string, happenedAt time.Time) error UpdatePigBatchQuantity(operatorID uint, batchID uint, changeType models.LogChangeType, changeAmount int, changeReason string, happenedAt time.Time) error
@@ -120,61 +121,3 @@ func NewPigBatchService(
sickSvc: sickSvc, sickSvc: sickSvc,
} }
} }
func (s *pigBatchService) RemoveEmptyPenFromBatch(batchID uint, penID uint) error {
return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
// 1. 检查猪批次是否存在且活跃
batch, err := s.pigBatchRepo.GetPigBatchByIDTx(tx, batchID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPigBatchNotFound
}
return err
}
if !batch.IsActive() {
return ErrPigBatchNotActive
}
// 2. 检查猪栏是否存在
pen, err := s.transferSvc.GetPenByID(tx, penID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPenNotFound
}
return err
}
// 3. 检查猪栏是否与当前批次关联
if pen.PigBatchID == nil || *pen.PigBatchID != batchID {
return ErrPenNotAssociatedWithBatch
}
// 4. 检查猪栏是否为空
pigsInPen, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
if err != nil {
return err
}
if pigsInPen > 0 {
return ErrPenNotEmpty
}
// 5. 释放猪栏 (将 pig_batch_id 设置为 nil状态设置为空闲)
if err := s.transferSvc.ReleasePen(tx, penID); err != nil {
return err
}
return nil
})
}
func (s *pigBatchService) GetCurrentPigsInPen(penID uint) (int, error) {
var currentPigs int
err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
pigs, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
if err != nil {
return err
}
currentPigs = pigs
return nil
})
return currentPigs, err
}

View File

@@ -381,3 +381,75 @@ func (s *pigBatchService) ReclassifyPenToNewBatch(fromBatchID uint, toBatchID ui
return nil return nil
}) })
} }
func (s *pigBatchService) RemoveEmptyPenFromBatch(batchID uint, penID uint) error {
return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
// 1. 检查猪批次是否存在且活跃
batch, err := s.pigBatchRepo.GetPigBatchByIDTx(tx, batchID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPigBatchNotFound
}
return err
}
if !batch.IsActive() {
return ErrPigBatchNotActive
}
// 2. 检查猪栏是否存在
pen, err := s.transferSvc.GetPenByID(tx, penID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPenNotFound
}
return err
}
// 3. 检查猪栏是否与当前批次关联
if pen.PigBatchID == nil || *pen.PigBatchID != batchID {
return ErrPenNotAssociatedWithBatch
}
// 4. 检查猪栏是否为空
pigsInPen, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
if err != nil {
return err
}
if pigsInPen > 0 {
return ErrPenNotEmpty
}
// 5. 释放猪栏 (将 pig_batch_id 设置为 nil状态设置为空闲)
if err := s.transferSvc.ReleasePen(tx, penID); err != nil {
return err
}
return nil
})
}
func (s *pigBatchService) GetCurrentPigsInPen(penID uint) (int, error) {
var currentPigs int
err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
pigs, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
if err != nil {
return err
}
currentPigs = pigs
return nil
})
return currentPigs, err
}
// GetTotalPigsInPensForBatch 实现了获取指定猪群下所有猪栏的当前总存栏数的逻辑。
func (s *pigBatchService) GetTotalPigsInPensForBatch(batchID uint) (int, error) {
var totalPigs int
err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
pigs, err := s.transferSvc.GetTotalPigsInPensForBatchTx(tx, batchID)
if err != nil {
return err
}
totalPigs = pigs
return nil
})
return totalPigs, err
}