155 lines
5.2 KiB
Go
155 lines
5.2 KiB
Go
package pig
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// SellPigs 处理批量销售猪的业务逻辑。
|
|
func (s *pigBatchService) SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
|
|
return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
|
|
if quantity <= 0 {
|
|
return errors.New("销售数量必须大于0")
|
|
}
|
|
|
|
// 1. 校验猪栏信息
|
|
pen, err := s.transferSvc.GetPenByID(tx, penID)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrPenNotFound
|
|
}
|
|
return fmt.Errorf("获取猪栏 %d 信息失败: %w", penID, err)
|
|
}
|
|
|
|
// 校验猪栏是否属于该批次
|
|
if pen.PigBatchID == nil || *pen.PigBatchID != batchID {
|
|
return ErrPenNotAssociatedWithBatch
|
|
}
|
|
|
|
// 2. 业务校验:检查销售数量是否超过猪栏当前猪只数
|
|
currentPigsInPen, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
|
|
if err != nil {
|
|
return fmt.Errorf("获取猪栏 %d 当前猪只数失败: %w", penID, err)
|
|
}
|
|
|
|
if quantity > currentPigsInPen {
|
|
return fmt.Errorf("销售数量 %d 超过猪栏 %d 当前猪只数 %d", quantity, penID, currentPigsInPen)
|
|
}
|
|
|
|
// 3. 记录销售交易 (财务)
|
|
sale := &models.PigSale{
|
|
PigBatchID: batchID,
|
|
SaleDate: tradeDate,
|
|
Buyer: traderName,
|
|
Quantity: quantity,
|
|
UnitPrice: unitPrice,
|
|
TotalPrice: tatalPrice, // 总价不一定是单价x数量, 所以要传进来
|
|
Remarks: remarks,
|
|
OperatorID: operatorID,
|
|
}
|
|
if err := s.tradeSvc.SellPig(tx, sale); err != nil {
|
|
return fmt.Errorf("记录销售交易失败: %w", err)
|
|
}
|
|
|
|
// 4. 创建猪只转移日志 (物理)
|
|
transferLog := &models.PigTransferLog{
|
|
TransferTime: tradeDate,
|
|
PigBatchID: batchID,
|
|
PenID: penID,
|
|
Quantity: -quantity, // 销售导致数量减少
|
|
Type: models.PigTransferTypeSale,
|
|
OperatorID: operatorID,
|
|
Remarks: fmt.Sprintf("销售给 %s", traderName),
|
|
}
|
|
if err := s.transferSvc.LogTransfer(tx, transferLog); err != nil {
|
|
return fmt.Errorf("创建猪只转移日志失败: %w", err)
|
|
}
|
|
|
|
// 5. 记录批次数量变更日志 (逻辑)
|
|
if err := s.updatePigBatchQuantityTx(tx, operatorID, batchID, models.ChangeTypeSale, -quantity,
|
|
fmt.Sprintf("猪批次 %d 从猪栏 %d 销售 %d 头猪给 %s", batchID, penID, quantity, traderName),
|
|
tradeDate); err != nil {
|
|
return fmt.Errorf("更新猪批次数量失败: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// BuyPigs 处理批量购买猪的业务逻辑。
|
|
func (s *pigBatchService) BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, totalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
|
|
return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
|
|
if quantity <= 0 {
|
|
return errors.New("采购数量必须大于0")
|
|
}
|
|
|
|
// 1. 校验猪栏信息
|
|
pen, err := s.transferSvc.GetPenByID(tx, penID)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return ErrPenNotFound
|
|
}
|
|
return fmt.Errorf("获取猪栏 %d 信息失败: %w", penID, err)
|
|
}
|
|
|
|
// 校验猪栏是否属于该批次
|
|
if pen.PigBatchID == nil || *pen.PigBatchID != batchID {
|
|
return ErrPenNotAssociatedWithBatch
|
|
}
|
|
|
|
// 2. 业务校验:检查猪栏容量,如果超出,在备注中记录警告
|
|
currentPigsInPen, err := s.transferSvc.GetCurrentPigsInPen(tx, penID)
|
|
if err != nil {
|
|
return fmt.Errorf("获取猪栏 %d 当前猪只数失败: %w", penID, err)
|
|
}
|
|
|
|
transferRemarks := fmt.Sprintf("从 %s 采购", traderName)
|
|
if currentPigsInPen+quantity > pen.Capacity {
|
|
warning := fmt.Sprintf("[警告]猪栏容量超出: 当前 %d, 采购 %d, 容量 %d.", currentPigsInPen, quantity, pen.Capacity)
|
|
transferRemarks = fmt.Sprintf("%s %s", transferRemarks, warning)
|
|
}
|
|
|
|
// 3. 记录采购交易 (财务)
|
|
purchase := &models.PigPurchase{
|
|
PigBatchID: batchID,
|
|
PurchaseDate: tradeDate,
|
|
Supplier: traderName,
|
|
Quantity: quantity,
|
|
UnitPrice: unitPrice,
|
|
TotalPrice: totalPrice, // 总价不一定是单价x数量, 所以要传进来
|
|
Remarks: remarks, // 用户传入的备注
|
|
OperatorID: operatorID,
|
|
}
|
|
if err := s.tradeSvc.BuyPig(tx, purchase); err != nil {
|
|
return fmt.Errorf("记录采购交易失败: %w", err)
|
|
}
|
|
|
|
// 4. 创建猪只转移日志 (物理)
|
|
transferLog := &models.PigTransferLog{
|
|
TransferTime: tradeDate,
|
|
PigBatchID: batchID,
|
|
PenID: penID,
|
|
Quantity: quantity, // 采购导致数量增加
|
|
Type: models.PigTransferTypePurchase,
|
|
OperatorID: operatorID,
|
|
Remarks: transferRemarks, // 包含系统生成的备注和潜在的警告
|
|
}
|
|
if err := s.transferSvc.LogTransfer(tx, transferLog); err != nil {
|
|
return fmt.Errorf("创建猪只转移日志失败: %w", err)
|
|
}
|
|
|
|
// 5. 记录批次数量变更日志 (逻辑)
|
|
if err := s.updatePigBatchQuantityTx(tx, operatorID, batchID, models.ChangeTypeBuy, quantity,
|
|
fmt.Sprintf("猪批次 %d 在猪栏 %d 采购 %d 头猪从 %s", batchID, penID, quantity, traderName),
|
|
tradeDate); err != nil {
|
|
return fmt.Errorf("更新猪批次数量失败: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|