创建批次时插入一条记录
This commit is contained in:
47
internal/app/controller/auth_utils.go
Normal file
47
internal/app/controller/auth_utils.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUserNotFoundInContext 表示在 gin.Context 中未找到用户信息。
|
||||
ErrUserNotFoundInContext = errors.New("context中未找到用户信息")
|
||||
// ErrInvalidUserType 表示从 gin.Context 中获取的用户信息类型不正确。
|
||||
ErrInvalidUserType = errors.New("context中用户信息类型不正确")
|
||||
)
|
||||
|
||||
// GetOperatorIDFromContext 从 gin.Context 中提取操作者ID。
|
||||
// 假设操作者ID是由 AuthMiddleware 存储到 context 中的 *models.User 对象的 ID 字段。
|
||||
func GetOperatorIDFromContext(c *gin.Context) (uint, error) {
|
||||
userVal, exists := c.Get(models.ContextUserKey.String())
|
||||
if !exists {
|
||||
return 0, ErrUserNotFoundInContext
|
||||
}
|
||||
|
||||
user, ok := userVal.(*models.User)
|
||||
if !ok {
|
||||
return 0, ErrInvalidUserType
|
||||
}
|
||||
|
||||
return user.ID, nil
|
||||
}
|
||||
|
||||
// GetOperatorFromContext 从 gin.Context 中提取操作者。
|
||||
// 假设操作者是由 AuthMiddleware 存储到 context 中的 *models.User 对象的 字段。
|
||||
func GetOperatorFromContext(c *gin.Context) (*models.User, error) {
|
||||
userVal, exists := c.Get(models.ContextUserKey.String())
|
||||
if !exists {
|
||||
return nil, ErrUserNotFoundInContext
|
||||
}
|
||||
|
||||
user, ok := userVal.(*models.User)
|
||||
if !ok {
|
||||
return nil, ErrInvalidUserType
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
@@ -45,7 +45,9 @@ func (c *PigBatchController) CreatePigBatch(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
respDTO, err := c.service.CreatePigBatch(&req)
|
||||
userID, err := controller.GetOperatorIDFromContext(ctx)
|
||||
|
||||
respDTO, err := c.service.CreatePigBatch(userID, &req)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪批次失败", action, "业务逻辑失败", req)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
// PigBatchService 接口定义保持不变,继续作为应用层对外的契约。
|
||||
type PigBatchService interface {
|
||||
CreatePigBatch(dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error)
|
||||
CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error)
|
||||
GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error)
|
||||
UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error)
|
||||
DeletePigBatch(id uint) error
|
||||
@@ -51,7 +51,7 @@ func (s *pigBatchService) toPigBatchResponseDTO(batch *models.PigBatch) *dto.Pig
|
||||
}
|
||||
|
||||
// CreatePigBatch 现在将请求委托给领域服务处理。
|
||||
func (s *pigBatchService) CreatePigBatch(dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) {
|
||||
func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) {
|
||||
// 1. DTO -> 领域模型
|
||||
batch := &models.PigBatch{
|
||||
BatchNumber: dto.BatchNumber,
|
||||
@@ -62,7 +62,7 @@ func (s *pigBatchService) CreatePigBatch(dto *dto.PigBatchCreateDTO) (*dto.PigBa
|
||||
}
|
||||
|
||||
// 2. 调用领域服务
|
||||
createdBatch, err := s.domainService.CreatePigBatch(batch)
|
||||
createdBatch, err := s.domainService.CreatePigBatch(operatorID, batch)
|
||||
if err != nil {
|
||||
s.logger.Errorf("应用层: 创建猪批次失败: %v", err)
|
||||
return nil, mapDomainError(err)
|
||||
|
||||
@@ -73,6 +73,7 @@ func NewApplication(configPath string) (*Application, error) {
|
||||
pendingCollectionRepo := repository.NewGormPendingCollectionRepository(storage.GetDB())
|
||||
userActionLogRepo := repository.NewGormUserActionLogRepository(storage.GetDB())
|
||||
pigBatchRepo := repository.NewGormPigBatchRepository(storage.GetDB())
|
||||
pigBatchLogRepo := repository.NewGormPigBatchLogRepository(storage.GetDB())
|
||||
pigFarmRepo := repository.NewGormPigFarmRepository(storage.GetDB())
|
||||
pigPenRepo := repository.NewGormPigPenRepository(storage.GetDB())
|
||||
|
||||
@@ -81,7 +82,7 @@ func NewApplication(configPath string) (*Application, error) {
|
||||
|
||||
// 初始化猪群管理领域
|
||||
penTransferManager := pig.NewPenTransferManager(pigPenRepo)
|
||||
pigBatchDomain := pig.NewPigBatchService(pigBatchRepo, unitOfWork, penTransferManager)
|
||||
pigBatchDomain := pig.NewPigBatchService(pigBatchRepo, pigBatchLogRepo, unitOfWork, penTransferManager)
|
||||
|
||||
// --- 业务逻辑处理器初始化 ---
|
||||
pigFarmService := service.NewPigFarmService(pigFarmRepo, pigPenRepo, pigBatchRepo, unitOfWork, logger)
|
||||
|
||||
@@ -37,7 +37,7 @@ type PigBatchService interface {
|
||||
TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint) error
|
||||
|
||||
// CreatePigBatch 创建一个新的猪批次。
|
||||
CreatePigBatch(batch *models.PigBatch) (*models.PigBatch, error)
|
||||
CreatePigBatch(operatorID uint, batch *models.PigBatch) (*models.PigBatch, error)
|
||||
|
||||
// GetPigBatch 根据ID获取单个猪批次的详细信息。
|
||||
GetPigBatch(id uint) (*models.PigBatch, error)
|
||||
|
||||
@@ -16,29 +16,67 @@ import (
|
||||
// pigBatchService 是 PigBatchService 接口的具体实现。
|
||||
// 它作为猪群领域的主服务,封装了所有业务逻辑。
|
||||
type pigBatchService struct {
|
||||
pigBatchRepo repository.PigBatchRepository // 猪批次仓库
|
||||
uow repository.UnitOfWork // 工作单元,用于管理事务
|
||||
transferSvc PenTransferManager // 调栏子服务
|
||||
pigBatchRepo repository.PigBatchRepository // 猪批次仓库
|
||||
pigBatchLogRepo repository.PigBatchLogRepository // 猪批次日志仓库
|
||||
uow repository.UnitOfWork // 工作单元,用于管理事务
|
||||
transferSvc PenTransferManager // 调栏子服务
|
||||
}
|
||||
|
||||
// NewPigBatchService 是 pigBatchService 的构造函数。
|
||||
// 它通过依赖注入的方式,创建并返回一个 PigBatchService 接口的实例。
|
||||
func NewPigBatchService(
|
||||
pigBatchRepo repository.PigBatchRepository,
|
||||
pigBatchLogRepo repository.PigBatchLogRepository,
|
||||
uow repository.UnitOfWork,
|
||||
transferSvc PenTransferManager,
|
||||
) PigBatchService {
|
||||
return &pigBatchService{
|
||||
pigBatchRepo: pigBatchRepo,
|
||||
uow: uow,
|
||||
transferSvc: transferSvc,
|
||||
pigBatchRepo: pigBatchRepo,
|
||||
pigBatchLogRepo: pigBatchLogRepo,
|
||||
uow: uow,
|
||||
transferSvc: transferSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePigBatch 实现了创建猪批次的逻辑。
|
||||
func (s *pigBatchService) CreatePigBatch(batch *models.PigBatch) (*models.PigBatch, error) {
|
||||
// CreatePigBatch 实现了创建猪批次的逻辑,并同时创建初始批次日志。
|
||||
func (s *pigBatchService) CreatePigBatch(operatorID uint, batch *models.PigBatch) (*models.PigBatch, error) {
|
||||
// 业务规则可以在这里添加,例如检查批次号是否唯一等
|
||||
return s.pigBatchRepo.CreatePigBatch(batch)
|
||||
|
||||
var createdBatch *models.PigBatch
|
||||
err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
|
||||
// 1. 创建猪批次
|
||||
// 注意: 此处依赖一个假设存在的 pigBatchRepo.CreatePigBatchTx 方法
|
||||
var err error
|
||||
createdBatch, err = s.pigBatchRepo.CreatePigBatchTx(tx, batch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建猪批次失败: %w", err)
|
||||
}
|
||||
|
||||
// 2. 创建初始批次日志
|
||||
initialLog := &models.PigBatchLog{
|
||||
PigBatchID: createdBatch.ID,
|
||||
HappenedAt: time.Now(),
|
||||
ChangeType: models.ChangeTypeCorrection, // 初始创建可视为一种校正
|
||||
ChangeCount: createdBatch.InitialCount,
|
||||
Reason: fmt.Sprintf("创建了新的猪批次 %s,初始数量 %d", createdBatch.BatchNumber, createdBatch.InitialCount),
|
||||
BeforeCount: 0, // 初始创建前数量为0
|
||||
AfterCount: int(createdBatch.InitialCount),
|
||||
OperatorID: 0, // 假设初始创建没有特定操作员ID,或需要从上下文传入
|
||||
}
|
||||
|
||||
// 3. 记录批次日志
|
||||
if err := s.pigBatchLogRepo.Create(tx, initialLog); err != nil {
|
||||
return fmt.Errorf("记录初始批次日志失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return createdBatch, nil
|
||||
}
|
||||
|
||||
// GetPigBatch 实现了获取单个猪批次的逻辑。
|
||||
|
||||
@@ -67,16 +67,14 @@ const (
|
||||
// PigBatchLog 记录了猪批次数量或状态的每一次变更
|
||||
type PigBatchLog struct {
|
||||
gorm.Model
|
||||
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
|
||||
ChangeType LogChangeType `gorm:"size:20;not null;comment:变更类型"`
|
||||
ChangeCount int `gorm:"not null;comment:数量变化,负数表示减少"`
|
||||
Reason string `gorm:"size:255;comment:变更原因描述"`
|
||||
BeforeCount int `gorm:"not null;comment:变更前总数"`
|
||||
AfterCount int `gorm:"not null;comment:变更后总数"`
|
||||
BeforeSickCount int `gorm:"not null;comment:变更前病猪数"`
|
||||
AfterSickCount int `gorm:"not null;comment:变更后病猪数"`
|
||||
OperatorID uint `gorm:"comment:操作员ID"`
|
||||
HappenedAt time.Time `gorm:"primaryKey;comment:事件发生时间"`
|
||||
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
|
||||
ChangeType LogChangeType `gorm:"size:20;not null;comment:变更类型"`
|
||||
ChangeCount int `gorm:"not null;comment:数量变化,负数表示减少"`
|
||||
Reason string `gorm:"size:255;comment:变更原因描述"`
|
||||
BeforeCount int `gorm:"not null;comment:变更前总数"`
|
||||
AfterCount int `gorm:"not null;comment:变更后总数"`
|
||||
OperatorID uint `gorm:"comment:操作员ID"`
|
||||
HappenedAt time.Time `gorm:"primaryKey;comment:事件发生时间"`
|
||||
}
|
||||
|
||||
func (PigBatchLog) TableName() string {
|
||||
|
||||
27
internal/infra/repository/pig_batch_log_repository.go
Normal file
27
internal/infra/repository/pig_batch_log_repository.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// PigBatchLogRepository 定义了与猪批次日志相关的数据库操作接口。
|
||||
type PigBatchLogRepository interface {
|
||||
// Create 在指定的事务中创建一条新的猪批次日志。
|
||||
Create(tx *gorm.DB, log *models.PigBatchLog) error
|
||||
}
|
||||
|
||||
// gormPigBatchLogRepository 是 PigBatchLogRepository 的 GORM 实现。
|
||||
type gormPigBatchLogRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewGormPigBatchLogRepository 创建一个新的 PigBatchLogRepository 实例。
|
||||
func NewGormPigBatchLogRepository(db *gorm.DB) PigBatchLogRepository {
|
||||
return &gormPigBatchLogRepository{db: db}
|
||||
}
|
||||
|
||||
// Create 实现了创建猪批次日志的逻辑。
|
||||
func (r *gormPigBatchLogRepository) Create(tx *gorm.DB, log *models.PigBatchLog) error {
|
||||
return tx.Create(log).Error
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
// PigBatchRepository 定义了与猪批次相关的数据库操作接口
|
||||
type PigBatchRepository interface {
|
||||
CreatePigBatch(batch *models.PigBatch) (*models.PigBatch, error)
|
||||
CreatePigBatchTx(tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error)
|
||||
GetPigBatchByID(id uint) (*models.PigBatch, error)
|
||||
GetPigBatchByIDTx(tx *gorm.DB, id uint) (*models.PigBatch, error)
|
||||
// UpdatePigBatch 更新一个猪批次,返回更新后的批次、受影响的行数和错误
|
||||
@@ -29,7 +30,12 @@ func NewGormPigBatchRepository(db *gorm.DB) PigBatchRepository {
|
||||
|
||||
// CreatePigBatch 创建一个新的猪批次
|
||||
func (r *gormPigBatchRepository) CreatePigBatch(batch *models.PigBatch) (*models.PigBatch, error) {
|
||||
if err := r.db.Create(batch).Error; err != nil {
|
||||
return r.CreatePigBatchTx(r.db, batch)
|
||||
}
|
||||
|
||||
// CreatePigBatchTx 在指定的事务中,创建一个新的猪批次
|
||||
func (r *gormPigBatchRepository) CreatePigBatchTx(tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error) {
|
||||
if err := tx.Create(batch).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return batch, nil
|
||||
|
||||
Reference in New Issue
Block a user