|
|
|
@@ -13,6 +13,7 @@ import (
|
|
|
|
|
sProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/services"
|
|
|
|
|
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
|
|
|
|
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
|
|
|
|
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
|
|
|
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/validations"
|
|
|
|
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
|
|
|
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
|
|
|
@@ -39,8 +40,8 @@ type RecordingService interface {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type RecordingFIFOIntegrationService interface {
|
|
|
|
|
ConsumeRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error
|
|
|
|
|
ReleaseRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error
|
|
|
|
|
ConsumeRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock, note string, actorID uint) error
|
|
|
|
|
ReleaseRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock, note string, actorID uint) error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var recordingStockUsableKey = fifo.UsableKeyRecordingStock
|
|
|
|
@@ -57,6 +58,7 @@ type recordingService struct {
|
|
|
|
|
ApprovalSvc commonSvc.ApprovalService
|
|
|
|
|
ProductionStandardSvc sProductionStandard.ProductionStandardService
|
|
|
|
|
FifoSvc commonSvc.FifoService
|
|
|
|
|
StockLogRepo rStockLogs.StockLogRepository
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewRecordingService(
|
|
|
|
@@ -67,6 +69,7 @@ func NewRecordingService(
|
|
|
|
|
approvalRepo commonRepo.ApprovalRepository,
|
|
|
|
|
approvalSvc commonSvc.ApprovalService,
|
|
|
|
|
fifoSvc commonSvc.FifoService,
|
|
|
|
|
stockLogRepo rStockLogs.StockLogRepository,
|
|
|
|
|
productionStandardSvc sProductionStandard.ProductionStandardService,
|
|
|
|
|
validate *validator.Validate,
|
|
|
|
|
) RecordingService {
|
|
|
|
@@ -81,6 +84,7 @@ func NewRecordingService(
|
|
|
|
|
ApprovalSvc: approvalSvc,
|
|
|
|
|
ProductionStandardSvc: productionStandardSvc,
|
|
|
|
|
FifoSvc: fifoSvc,
|
|
|
|
|
StockLogRepo: stockLogRepo,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -88,12 +92,14 @@ func NewRecordingFIFOIntegrationService(
|
|
|
|
|
repo repository.RecordingRepository,
|
|
|
|
|
productWarehouseRepo rProductWarehouse.ProductWarehouseRepository,
|
|
|
|
|
fifoSvc commonSvc.FifoService,
|
|
|
|
|
stockLogRepo rStockLogs.StockLogRepository,
|
|
|
|
|
) RecordingFIFOIntegrationService {
|
|
|
|
|
return &recordingService{
|
|
|
|
|
Log: utils.Log,
|
|
|
|
|
Repository: repo,
|
|
|
|
|
ProductWarehouseRepo: productWarehouseRepo,
|
|
|
|
|
FifoSvc: fifoSvc,
|
|
|
|
|
StockLogRepo: stockLogRepo,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -274,7 +280,8 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
applyStockDesiredQuantities(mappedStocks, stockDesired, s.FifoSvc != nil)
|
|
|
|
|
if err := s.consumeRecordingStocks(ctx, tx, mappedStocks); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Create#%d", createdRecording.Id)
|
|
|
|
|
if err := s.consumeRecordingStocks(ctx, tx, mappedStocks, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -293,7 +300,8 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.consumeRecordingDepletions(ctx, tx, mappedDepletions); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Create#%d", createdRecording.Id)
|
|
|
|
|
if err := s.consumeRecordingDepletions(ctx, tx, mappedDepletions, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -304,7 +312,8 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.replenishRecordingEggs(ctx, tx, mappedEggs); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Create#%d", createdRecording.Id)
|
|
|
|
|
if err := s.replenishRecordingEggs(ctx, tx, mappedEggs, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -346,6 +355,10 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx := c.Context()
|
|
|
|
|
actorID, err := m.ActorIDFromContext(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var recordingEntity *entity.Recording
|
|
|
|
|
var updatedRecording *entity.Recording
|
|
|
|
@@ -431,14 +444,16 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if hasStockChanges {
|
|
|
|
|
if err := s.syncRecordingStocks(ctx, tx, recordingEntity.Id, existingStocks, req.Stocks); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Edit#%d", recordingEntity.Id)
|
|
|
|
|
if err := s.syncRecordingStocks(ctx, tx, recordingEntity.Id, existingStocks, req.Stocks, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if hasDepletionChanges {
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.releaseRecordingDepletions(ctx, tx, existingDepletions); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Edit#%d", recordingEntity.Id)
|
|
|
|
|
if err := s.releaseRecordingDepletions(ctx, tx, existingDepletions, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -464,7 +479,8 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.consumeRecordingDepletions(ctx, tx, mappedDepletions); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Edit#%d", recordingEntity.Id)
|
|
|
|
|
if err := s.consumeRecordingDepletions(ctx, tx, mappedDepletions, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -480,6 +496,28 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|
|
|
|
if err := ensureRecordingEggsUnused(existingEggs); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if s.StockLogRepo != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Edit#%d", recordingEntity.Id)
|
|
|
|
|
logs := make([]*entity.StockLog, 0, len(existingEggs))
|
|
|
|
|
for _, egg := range existingEggs {
|
|
|
|
|
if egg.ProductWarehouseId == 0 || egg.Qty <= 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
logs = append(logs, &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: egg.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Decrease: float64(egg.Qty),
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: recordingEntity.Id,
|
|
|
|
|
Notes: note,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
if len(logs) > 0 {
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateMany(ctx, logs, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err := s.adjustProductWarehouseQuantities(ctx, tx, buildWarehouseDeltas(nil, nil, existingEggs, nil)); err != nil {
|
|
|
|
|
s.Log.Errorf("Failed to adjust product warehouses for eggs: %+v", err)
|
|
|
|
|
return err
|
|
|
|
@@ -498,7 +536,8 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.replenishRecordingEggs(ctx, tx, mappedEggs); err != nil {
|
|
|
|
|
note := fmt.Sprintf("Recording-Edit#%d", recordingEntity.Id)
|
|
|
|
|
if err := s.replenishRecordingEggs(ctx, tx, mappedEggs, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@@ -675,7 +714,7 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if s.FifoSvc != nil {
|
|
|
|
|
if err := s.releaseRecordingDepletions(ctx, tx, oldDepletions); err != nil {
|
|
|
|
|
if err := s.releaseRecordingDepletions(ctx, tx, oldDepletions, "", 0); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -697,7 +736,7 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := s.releaseRecordingStocks(ctx, tx, oldStocks); err != nil {
|
|
|
|
|
if err := s.releaseRecordingStocks(ctx, tx, oldStocks, "", 0); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -756,10 +795,19 @@ func (s *recordingService) ensureProductWarehousesExist(c *fiber.Ctx, stocks []v
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) consumeRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error {
|
|
|
|
|
func (s *recordingService) consumeRecordingStocks(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
stocks []entity.RecordingStock,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if len(stocks) == 0 || s.FifoSvc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if strings.TrimSpace(note) != "" && s.StockLogRepo == nil {
|
|
|
|
|
return errors.New("stock log repository is not available")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, stock := range stocks {
|
|
|
|
|
if stock.Id == 0 {
|
|
|
|
@@ -792,15 +840,42 @@ func (s *recordingService) consumeRecordingStocks(ctx context.Context, tx *gorm.
|
|
|
|
|
if err := s.Repository.UpdateStockUsage(tx, stock.Id, result.UsageQuantity, result.PendingQuantity); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logDecrease := result.UsageQuantity
|
|
|
|
|
if result.PendingQuantity > 0 {
|
|
|
|
|
logDecrease += result.PendingQuantity
|
|
|
|
|
}
|
|
|
|
|
if logDecrease > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: stock.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Decrease: logDecrease,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: stock.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) consumeRecordingDepletions(ctx context.Context, tx *gorm.DB, depletions []entity.RecordingDepletion) error {
|
|
|
|
|
func (s *recordingService) consumeRecordingDepletions(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
depletions []entity.RecordingDepletion,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if len(depletions) == 0 || s.FifoSvc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if strings.TrimSpace(note) != "" && s.StockLogRepo == nil {
|
|
|
|
|
return errors.New("stock log repository is not available")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, depletion := range depletions {
|
|
|
|
|
if depletion.Id == 0 {
|
|
|
|
@@ -832,19 +907,67 @@ func (s *recordingService) consumeRecordingDepletions(ctx context.Context, tx *g
|
|
|
|
|
if err := s.Repository.UpdateDepletionPending(tx, depletion.Id, result.PendingQuantity); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logDecrease := result.UsageQuantity
|
|
|
|
|
if result.PendingQuantity > 0 {
|
|
|
|
|
logDecrease += result.PendingQuantity
|
|
|
|
|
}
|
|
|
|
|
if logDecrease > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: sourceWarehouseID,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Decrease: logDecrease,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: depletion.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
destDelta := depletion.Qty + depletion.PendingQty
|
|
|
|
|
if depletion.ProductWarehouseId != 0 && destDelta > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: depletion.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Increase: destDelta,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: depletion.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) ConsumeRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error {
|
|
|
|
|
return s.consumeRecordingStocks(ctx, tx, stocks)
|
|
|
|
|
func (s *recordingService) ConsumeRecordingStocks(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
stocks []entity.RecordingStock,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
return s.consumeRecordingStocks(ctx, tx, stocks, note, actorID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) releaseRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error {
|
|
|
|
|
func (s *recordingService) releaseRecordingStocks(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
stocks []entity.RecordingStock,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if len(stocks) == 0 || s.FifoSvc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if strings.TrimSpace(note) != "" && s.StockLogRepo == nil {
|
|
|
|
|
return errors.New("stock log repository is not available")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, stock := range stocks {
|
|
|
|
|
if stock.Id == 0 {
|
|
|
|
@@ -863,15 +986,38 @@ func (s *recordingService) releaseRecordingStocks(ctx context.Context, tx *gorm.
|
|
|
|
|
if err := s.Repository.UpdateStockUsage(tx, stock.Id, 0, 0); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if stock.UsageQty != nil && *stock.UsageQty > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: stock.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Increase: *stock.UsageQty,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: stock.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) releaseRecordingDepletions(ctx context.Context, tx *gorm.DB, depletions []entity.RecordingDepletion) error {
|
|
|
|
|
func (s *recordingService) releaseRecordingDepletions(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
depletions []entity.RecordingDepletion,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if len(depletions) == 0 || s.FifoSvc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if strings.TrimSpace(note) != "" && s.StockLogRepo == nil {
|
|
|
|
|
return errors.New("stock log repository is not available")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, depletion := range depletions {
|
|
|
|
|
if depletion.Id == 0 {
|
|
|
|
@@ -898,13 +1044,52 @@ func (s *recordingService) releaseRecordingDepletions(ctx context.Context, tx *g
|
|
|
|
|
if err := s.Repository.UpdateDepletionPending(tx, depletion.Id, 0); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logIncrease := depletion.Qty
|
|
|
|
|
if depletion.PendingQty > 0 {
|
|
|
|
|
logIncrease += depletion.PendingQty
|
|
|
|
|
}
|
|
|
|
|
if logIncrease > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: sourceWarehouseID,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Increase: logIncrease,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: depletion.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
destDelta := depletion.Qty + depletion.PendingQty
|
|
|
|
|
if depletion.ProductWarehouseId != 0 && destDelta > 0 && strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: depletion.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Decrease: destDelta,
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: depletion.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) ReleaseRecordingStocks(ctx context.Context, tx *gorm.DB, stocks []entity.RecordingStock) error {
|
|
|
|
|
return s.releaseRecordingStocks(ctx, tx, stocks)
|
|
|
|
|
func (s *recordingService) ReleaseRecordingStocks(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
stocks []entity.RecordingStock,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
return s.releaseRecordingStocks(ctx, tx, stocks, note, actorID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) resolvePopulationWarehouseID(ctx context.Context, projectFlockKandangID uint) (uint, error) {
|
|
|
|
@@ -963,27 +1148,48 @@ func (s *recordingService) adjustProductWarehouseQuantities(ctx context.Context,
|
|
|
|
|
return s.ProductWarehouseRepo.AdjustQuantities(ctx, deltas, func(*gorm.DB) *gorm.DB { return tx })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *recordingService) replenishRecordingEggs(ctx context.Context, tx *gorm.DB, eggs []entity.RecordingEgg) error {
|
|
|
|
|
func (s *recordingService) replenishRecordingEggs(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
tx *gorm.DB,
|
|
|
|
|
eggs []entity.RecordingEgg,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if len(eggs) == 0 || s.FifoSvc == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if strings.TrimSpace(note) != "" && s.StockLogRepo == nil {
|
|
|
|
|
return errors.New("stock log repository is not available")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, egg := range eggs {
|
|
|
|
|
if egg.Id == 0 || egg.ProductWarehouseId == 0 || egg.Qty <= 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
note := fmt.Sprintf("Recording egg #%d", egg.Id)
|
|
|
|
|
if _, err := s.FifoSvc.Replenish(ctx, commonSvc.StockReplenishRequest{
|
|
|
|
|
StockableKey: fifo.StockableKeyRecordingEgg,
|
|
|
|
|
StockableID: egg.Id,
|
|
|
|
|
ProductWarehouseID: egg.ProductWarehouseId,
|
|
|
|
|
Quantity: float64(egg.Qty),
|
|
|
|
|
Note: ¬e,
|
|
|
|
|
Tx: tx,
|
|
|
|
|
}); err != nil {
|
|
|
|
|
s.Log.Errorf("Failed to replenish FIFO stock for recording egg %d: %+v", egg.Id, err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if strings.TrimSpace(note) != "" && actorID != 0 {
|
|
|
|
|
log := &entity.StockLog{
|
|
|
|
|
ProductWarehouseId: egg.ProductWarehouseId,
|
|
|
|
|
CreatedBy: actorID,
|
|
|
|
|
Increase: float64(egg.Qty),
|
|
|
|
|
LoggableType: string(utils.StockLogTypeRecording),
|
|
|
|
|
LoggableId: egg.RecordingId,
|
|
|
|
|
Notes: note,
|
|
|
|
|
}
|
|
|
|
|
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
@@ -1034,6 +1240,8 @@ func (s *recordingService) syncRecordingStocks(
|
|
|
|
|
recordingID uint,
|
|
|
|
|
existing []entity.RecordingStock,
|
|
|
|
|
incoming []validation.Stock,
|
|
|
|
|
note string,
|
|
|
|
|
actorID uint,
|
|
|
|
|
) error {
|
|
|
|
|
if s.FifoSvc == nil {
|
|
|
|
|
if err := s.Repository.DeleteStocks(tx, recordingID); err != nil {
|
|
|
|
@@ -1080,7 +1288,7 @@ func (s *recordingService) syncRecordingStocks(
|
|
|
|
|
leftovers = append(leftovers, list...)
|
|
|
|
|
}
|
|
|
|
|
if len(leftovers) > 0 {
|
|
|
|
|
if err := s.releaseRecordingStocks(ctx, tx, leftovers); err != nil {
|
|
|
|
|
if err := s.releaseRecordingStocks(ctx, tx, leftovers, note, actorID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
ids := make([]uint, 0, len(leftovers))
|
|
|
|
@@ -1099,7 +1307,7 @@ func (s *recordingService) syncRecordingStocks(
|
|
|
|
|
if len(stocksToConsume) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return s.consumeRecordingStocks(ctx, tx, stocksToConsume)
|
|
|
|
|
return s.consumeRecordingStocks(ctx, tx, stocksToConsume, note, actorID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type eggTotals struct {
|
|
|
|
|