mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat[BE-127]; creating correct logic update and delete transfer laying
This commit is contained in:
@@ -361,7 +361,9 @@ func (s transferLayingService) UpdateOne(c *fiber.Ctx, req *validation.Update, i
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err := s.Repository.GetByID(c.Context(), id, nil)
|
||||
existingTransfer, err := s.Repository.GetByID(c.Context(), id, func(db *gorm.DB) *gorm.DB {
|
||||
return db.Preload("Sources.ProductWarehouse").Preload("Targets")
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "TransferLaying not found")
|
||||
@@ -382,26 +384,140 @@ func (s transferLayingService) UpdateOne(c *fiber.Ctx, req *validation.Update, i
|
||||
}
|
||||
}
|
||||
|
||||
updateBody := make(map[string]any)
|
||||
|
||||
if req.TransferDate != nil {
|
||||
updateBody["transfer_date"] = *req.TransferDate
|
||||
if _, err := s.ProjectFlockRepo.GetByID(c.Context(), req.SourceProjectFlockId, nil); err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Source project flock not found")
|
||||
}
|
||||
|
||||
if req.Reason != nil {
|
||||
updateBody["notes"] = *req.Reason
|
||||
if _, err := s.ProjectFlockRepo.GetByID(c.Context(), req.TargetProjectFlockId, nil); err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Target project flock not found")
|
||||
}
|
||||
|
||||
if len(updateBody) == 0 {
|
||||
return s.GetOne(c, id)
|
||||
transferDate, err := time.Parse("2006-01-02", req.TransferDate)
|
||||
if err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid transfer date format")
|
||||
}
|
||||
|
||||
if err := s.Repository.PatchOne(c.Context(), id, updateBody, nil); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "TransferLaying not found")
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||
projectFlockPopulationRepoTx := s.ProjectFlockPopulationRepo.WithTx(dbTransaction)
|
||||
productWarehouseRepoTx := s.ProductWarehouseRepo.WithTx(dbTransaction)
|
||||
|
||||
for _, oldSource := range existingTransfer.Sources {
|
||||
if oldSource.ProductWarehouseId != nil && oldSource.Qty > 0 {
|
||||
|
||||
if err := productWarehouseRepoTx.PatchOne(c.Context(), *oldSource.ProductWarehouseId, map[string]any{
|
||||
"quantity": gorm.Expr("quantity + ?", oldSource.Qty),
|
||||
}, nil); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to restore warehouse quantity")
|
||||
}
|
||||
|
||||
if err := s.restoreProjectFlockPopulation(c.Context(), projectFlockPopulationRepoTx, oldSource.SourceProjectFlockKandangId, oldSource.Qty); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
s.Log.Errorf("Failed to update transferLaying: %+v", err)
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to update transfer laying")
|
||||
|
||||
for _, oldSource := range existingTransfer.Sources {
|
||||
if err := dbTransaction.Delete(&oldSource).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete old source")
|
||||
}
|
||||
}
|
||||
|
||||
for _, oldTarget := range existingTransfer.Targets {
|
||||
if err := dbTransaction.Delete(&oldTarget).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete old target")
|
||||
}
|
||||
}
|
||||
|
||||
totalSourceQty := 0.0
|
||||
for _, source := range req.SourceKandangs {
|
||||
totalSourceQty += source.Quantity
|
||||
}
|
||||
|
||||
if err := s.Repository.WithTx(dbTransaction).PatchOne(c.Context(), id, map[string]any{
|
||||
"transfer_date": transferDate,
|
||||
"notes": req.Reason,
|
||||
"pending_usage_qty": &totalSourceQty,
|
||||
}, nil); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update transfer header")
|
||||
}
|
||||
|
||||
sourceWarehouseMap := make(map[uint]uint)
|
||||
for _, sourceDetail := range req.SourceKandangs {
|
||||
|
||||
populations, err := projectFlockPopulationRepoTx.GetByProjectFlockKandangID(c.Context(), sourceDetail.ProjectFlockKandangId)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get populations")
|
||||
}
|
||||
|
||||
if len(populations) == 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Source kandang %d has no population available", sourceDetail.ProjectFlockKandangId))
|
||||
}
|
||||
|
||||
var totalPopulation float64
|
||||
var productWarehouseId uint
|
||||
|
||||
for _, pop := range populations {
|
||||
totalPopulation += pop.TotalQty
|
||||
if pop.ProductWarehouseId > 0 {
|
||||
productWarehouseId = pop.ProductWarehouseId
|
||||
}
|
||||
}
|
||||
|
||||
if totalPopulation < sourceDetail.Quantity {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Source kandang %d has insufficient quantity. Available: %.0f, Requested: %.0f", sourceDetail.ProjectFlockKandangId, totalPopulation, sourceDetail.Quantity))
|
||||
}
|
||||
|
||||
sourceWarehouseMap[sourceDetail.ProjectFlockKandangId] = productWarehouseId
|
||||
|
||||
source := entity.LayingTransferSource{
|
||||
LayingTransferId: id,
|
||||
SourceProjectFlockKandangId: sourceDetail.ProjectFlockKandangId,
|
||||
Qty: sourceDetail.Quantity,
|
||||
ProductWarehouseId: &productWarehouseId,
|
||||
}
|
||||
if err := dbTransaction.Create(&source).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create transfer source")
|
||||
}
|
||||
|
||||
if err := s.reduceProjectFlockPopulation(c.Context(), projectFlockPopulationRepoTx, sourceDetail.ProjectFlockKandangId, sourceDetail.Quantity); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := productWarehouseRepoTx.PatchOne(c.Context(), productWarehouseId, map[string]any{"quantity": gorm.Expr("quantity - ?", sourceDetail.Quantity)}, nil); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update source warehouse quantity")
|
||||
}
|
||||
}
|
||||
|
||||
for _, targetDetail := range req.TargetKandangs {
|
||||
targetPFK, err := s.ProjectFlockKandangRepo.GetByID(c.Context(), targetDetail.ProjectFlockKandangId)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get target project flock kandang")
|
||||
}
|
||||
|
||||
targetWarehouse, err := s.WarehouseRepo.GetLatestByKandangID(c.Context(), targetPFK.KandangId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("No warehouse found for target kandang %d", targetDetail.ProjectFlockKandangId))
|
||||
}
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get target warehouse")
|
||||
}
|
||||
|
||||
target := entity.LayingTransferTarget{
|
||||
LayingTransferId: id,
|
||||
TargetProjectFlockKandangId: targetDetail.ProjectFlockKandangId,
|
||||
Qty: targetDetail.Quantity,
|
||||
ProductWarehouseId: &targetWarehouse.Id,
|
||||
}
|
||||
if err := dbTransaction.Create(&target).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create transfer target")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.GetOne(c, id)
|
||||
@@ -464,9 +580,8 @@ func (s transferLayingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
for i := len(populations) - 1; i >= 0 && remainingToRestore > 0; i-- {
|
||||
pop := populations[i]
|
||||
restoreAmount := remainingToRestore
|
||||
if remainingToRestore < pop.TotalQty {
|
||||
|
||||
restoreAmount = remainingToRestore
|
||||
if pop.TotalQty < remainingToRestore {
|
||||
restoreAmount = pop.TotalQty
|
||||
}
|
||||
|
||||
newQty := pop.TotalQty + restoreAmount
|
||||
@@ -725,3 +840,26 @@ func (s *transferLayingService) reduceProjectFlockPopulation(ctx context.Context
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *transferLayingService) restoreProjectFlockPopulation(ctx context.Context, populationRepo ProjectFlockRepository.ProjectFlockPopulationRepository, projectFlockKandangID uint, quantityToRestore float64) error {
|
||||
populations, err := populationRepo.GetByProjectFlockKandangID(ctx, projectFlockKandangID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(populations) == 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "No populations found for restoration")
|
||||
}
|
||||
|
||||
// Restore in LIFO order (from newest to oldest)
|
||||
// Add all quantity back to the last (newest) population
|
||||
if len(populations) > 0 {
|
||||
lastPop := populations[len(populations)-1]
|
||||
newQty := lastPop.TotalQty + quantityToRestore
|
||||
if err := populationRepo.PatchOne(ctx, lastPop.Id, map[string]any{"total_qty": newQty}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user