mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-24 15:25:43 +00:00
Fix adjusment stock chickin, transfer to laying and chickin
This commit is contained in:
@@ -26,11 +26,15 @@ import (
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/jackc/pgconn"
|
||||
pgconnv5 "github.com/jackc/pgx/v5/pgconn"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
const chickinDeletePopulationGuardMessage = "Chickin tidak dapat dihapus karena sudah memiliki population. Lakukan rollback/penyesuaian population terlebih dahulu"
|
||||
|
||||
type ChickinService interface {
|
||||
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectChickin, int64, error)
|
||||
GetOne(ctx *fiber.Ctx, id uint) (*entity.ProjectChickin, error)
|
||||
@@ -189,31 +193,31 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product warehouse %d belongs to different flock. Only product warehouses with project_flock_kandang_id = NULL or = %d can be used", chickinReq.ProductWarehouseId, req.ProjectFlockKandangId))
|
||||
}
|
||||
|
||||
if productWarehouse.Product.Id != 0 {
|
||||
category := strings.ToUpper(strings.TrimSpace(projectFlockKandang.ProjectFlock.Category))
|
||||
if category != string(utils.ProjectFlockCategoryGrowing) && category != string(utils.ProjectFlockCategoryLaying) {
|
||||
return nil, fmt.Errorf("invalid flock category for chickin")
|
||||
}
|
||||
if productWarehouse.Product.Id != 0 {
|
||||
category := strings.ToUpper(strings.TrimSpace(projectFlockKandang.ProjectFlock.Category))
|
||||
if category != string(utils.ProjectFlockCategoryGrowing) && category != string(utils.ProjectFlockCategoryLaying) {
|
||||
return nil, fmt.Errorf("invalid flock category for chickin")
|
||||
}
|
||||
|
||||
hasAyamFlag := false
|
||||
for _, flag := range productWarehouse.Product.Flags {
|
||||
if utils.CanonicalFlagType(flag.Name) == utils.FlagAyam {
|
||||
hasAyamFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAyamFlag {
|
||||
return nil, fmt.Errorf(
|
||||
"product warehouse %d cannot be used for %s chickin. Product must have AYAM flag (or legacy alias DOC/PULLET/LAYER) (product ID: %d, warehouse ID: %d)",
|
||||
chickinReq.ProductWarehouseId,
|
||||
projectFlockKandang.ProjectFlock.Category,
|
||||
productWarehouse.Product.Id,
|
||||
productWarehouse.Id,
|
||||
)
|
||||
hasAyamFlag := false
|
||||
for _, flag := range productWarehouse.Product.Flags {
|
||||
if utils.CanonicalFlagType(flag.Name) == utils.FlagAyam {
|
||||
hasAyamFlag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasAyamFlag {
|
||||
return nil, fmt.Errorf(
|
||||
"product warehouse %d cannot be used for %s chickin. Product must have AYAM flag (or legacy alias DOC/PULLET/LAYER) (product ID: %d, warehouse ID: %d)",
|
||||
chickinReq.ProductWarehouseId,
|
||||
projectFlockKandang.ProjectFlock.Category,
|
||||
productWarehouse.Product.Id,
|
||||
productWarehouse.Id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
chickinDate, err := utils.ParseDateString(chickinReq.ChickInDate)
|
||||
if err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid ChickInDate format for product warehouse %d", chickinReq.ProductWarehouseId))
|
||||
@@ -421,6 +425,14 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
if err := s.ensureNotTransferred(c.Context(), chickin.ProjectFlockKandangId); err != nil {
|
||||
return err
|
||||
}
|
||||
hasPopulation, err := s.ProjectflockPopulationRepo.ExistsByProjectChickinID(c.Context(), chickin.Id)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Failed to check population by chickin %d: %+v", chickin.Id, err)
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi population chickin")
|
||||
}
|
||||
if hasPopulation {
|
||||
return fiber.NewError(fiber.StatusBadRequest, chickinDeletePopulationGuardMessage)
|
||||
}
|
||||
|
||||
actorID, err := m.ActorIDFromContext(c)
|
||||
if err != nil {
|
||||
@@ -429,17 +441,35 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
||||
chickinRepoTx := repository.NewChickinRepository(tx)
|
||||
|
||||
if chickin.UsageQty > 0 || chickin.PendingUsageQty > 0 {
|
||||
if err := s.ReleaseChickinStocks(c.Context(), tx, chickin, actorID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
note := "delete chickin rollback"
|
||||
if err := tx.WithContext(c.Context()).
|
||||
Model(&entity.StockAllocation{}).
|
||||
Where("usable_type = ? AND usable_id = ? AND status = ?",
|
||||
fifo.UsableKeyProjectChickin.String(),
|
||||
chickin.Id,
|
||||
entity.StockAllocationStatusActive,
|
||||
).
|
||||
Updates(map[string]any{
|
||||
"status": entity.StockAllocationStatusReleased,
|
||||
"released_at": now,
|
||||
"note": note,
|
||||
}).Error; err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal release alokasi FIFO chickin")
|
||||
}
|
||||
|
||||
if err := chickinRepoTx.DeleteOne(c.Context(), id); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusNotFound, "Chickin not found")
|
||||
}
|
||||
if isForeignKeyViolation(err) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, chickinDeletePopulationGuardMessage)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -459,6 +489,24 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isForeignKeyViolation(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) {
|
||||
return pgErr.Code == "23503"
|
||||
}
|
||||
|
||||
var pgErrV5 *pgconnv5.PgError
|
||||
if errors.As(err, &pgErrV5) {
|
||||
return pgErrV5.Code == "23503"
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entity.ProjectChickin, error) {
|
||||
if err := s.Validate.Struct(req); err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user