mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
fixing filter product warehouse transfer, cannot take from population
This commit is contained in:
@@ -220,6 +220,9 @@ func shouldSkipStockableForUsable(req AllocateRequest, stockableType string) boo
|
|||||||
if (usableType == "PROJECT_CHICKIN" || functionCode == "CHICKIN_OUT") && stockable == "PROJECT_FLOCK_POPULATION" {
|
if (usableType == "PROJECT_CHICKIN" || functionCode == "CHICKIN_OUT") && stockable == "PROJECT_FLOCK_POPULATION" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (usableType == "STOCK_TRANSFER_OUT" || functionCode == "STOCK_TRANSFER_OUT") && stockable == "PROJECT_FLOCK_POPULATION" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||||
fifoV2 "gitlab.com/mbugroup/lti-api.git/internal/common/service/fifo_stock_v2"
|
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||||
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||||
@@ -22,7 +21,6 @@ import (
|
|||||||
projectFlockKandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
projectFlockKandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||||
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -513,18 +511,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok tidak mencukupi untuk produk %d di gudang asal", product.ProductID))
|
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Stok tidak mencukupi untuk produk %d di gudang asal", product.ProductID))
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.EqualFold(flagGroupCode, "AYAM") && outUsageQty > 0 {
|
|
||||||
if err := s.allocatePopulationForStockTransferOut(
|
|
||||||
c.Context(),
|
|
||||||
tx,
|
|
||||||
detail,
|
|
||||||
uint(*detail.SourceProductWarehouseID),
|
|
||||||
outUsageQty,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stockLogDecrease := &entity.StockLog{
|
stockLogDecrease := &entity.StockLog{
|
||||||
ProductWarehouseId: uint(*detail.SourceProductWarehouseID),
|
ProductWarehouseId: uint(*detail.SourceProductWarehouseID),
|
||||||
CreatedBy: uint(actorID),
|
CreatedBy: uint(actorID),
|
||||||
@@ -633,57 +619,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *transferService) allocatePopulationForStockTransferOut(
|
|
||||||
ctx context.Context,
|
|
||||||
tx *gorm.DB,
|
|
||||||
detail *entity.StockTransferDetail,
|
|
||||||
sourceProductWarehouseID uint,
|
|
||||||
consumeQty float64,
|
|
||||||
) error {
|
|
||||||
if consumeQty <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if tx == nil {
|
|
||||||
return errors.New("transaction is required")
|
|
||||||
}
|
|
||||||
if detail == nil || detail.Id == 0 {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Data transfer detail tidak valid")
|
|
||||||
}
|
|
||||||
if sourceProductWarehouseID == 0 {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Gudang sumber tidak valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
pw, err := s.ProductWarehouseRepo.WithTx(tx).GetByID(ctx, sourceProductWarehouseID, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pw.ProjectFlockKandangId == nil || *pw.ProjectFlockKandangId == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
populations, err := s.ProjectFlockPopulationRepo.WithTx(tx).GetByProjectFlockKandangIDAndProductWarehouseID(
|
|
||||||
ctx,
|
|
||||||
*pw.ProjectFlockKandangId,
|
|
||||||
sourceProductWarehouseID,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(populations) == 0 {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Populasi tidak ditemukan untuk transfer")
|
|
||||||
}
|
|
||||||
|
|
||||||
return fifoV2.AllocatePopulationConsumption(
|
|
||||||
ctx,
|
|
||||||
tx,
|
|
||||||
populations,
|
|
||||||
sourceProductWarehouseID,
|
|
||||||
fifo.UsableKeyStockTransferOut.String(),
|
|
||||||
uint(detail.Id),
|
|
||||||
consumeQty,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *transferService) resolveTransferFlagGroup(
|
func (s *transferService) resolveTransferFlagGroup(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
tx *gorm.DB,
|
tx *gorm.DB,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
chickinDeletePopulationGuardMessage = "Chickin tidak dapat dihapus karena masih memiliki population aktif"
|
chickinDeletePopulationGuardMessage = "Chickin tidak dapat dihapus karena masih memiliki population aktif"
|
||||||
chickinDeleteRecordingGuardMessage = "Chickin tidak dapat dihapus karena masih terkait recording. Lakukan rollback/delete recording terlebih dahulu"
|
chickinDeleteDownstreamGuardMessage = "Chickin tidak bisa dihapus karena masih dipakai oleh transaksi turunan. Hapus/unexecute Marketing, Recording, dan Transfer to Laying terlebih dahulu."
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChickinService interface {
|
type ChickinService interface {
|
||||||
@@ -448,21 +449,13 @@ func (s chickinService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
|||||||
|
|
||||||
func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||||
|
|
||||||
chickin, err := s.Repository.GetByID(c.Context(), id, nil)
|
if _, err := s.Repository.GetByID(c.Context(), id, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return fiber.NewError(fiber.StatusNotFound, "Chickin not found")
|
return fiber.NewError(fiber.StatusNotFound, "Chickin not found")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.ensureNotTransferred(c.Context(), chickin.ProjectFlockKandangId); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.ensureNoExecutedTransferForDelete(c.Context(), chickin.ProjectFlockKandangId); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
actorID, err := m.ActorIDFromContext(c)
|
actorID, err := m.ActorIDFromContext(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -497,7 +490,7 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
|||||||
traceAllocBefore,
|
traceAllocBefore,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := s.ensureNoRelatedRecording(c.Context(), tx, lockedChickin); err != nil {
|
if err := s.ensureNoDownstreamConsumptionForDelete(c.Context(), tx, lockedChickin.Id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,51 +554,6 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s chickinService) ensureNoExecutedTransferForDelete(ctx context.Context, projectFlockKandangID uint) error {
|
|
||||||
if projectFlockKandangID == 0 || s.TransferLayingRepo == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete guard by executed transfer hanya untuk kandang kategori growing.
|
|
||||||
if s.ProjectflockKandangRepo != nil {
|
|
||||||
pfk, err := s.ProjectflockKandangRepo.GetByIDLight(ctx, projectFlockKandangID)
|
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
s.Log.Errorf("Failed to resolve project flock kandang %d for delete guard: %+v", projectFlockKandangID, err)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi transfer laying")
|
|
||||||
}
|
|
||||||
if err == nil && pfk != nil {
|
|
||||||
category := strings.ToUpper(strings.TrimSpace(pfk.ProjectFlock.Category))
|
|
||||||
if category != strings.ToUpper(string(utils.ProjectFlockCategoryGrowing)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isExecuted := func(transfer *entity.LayingTransfer) bool {
|
|
||||||
return transfer != nil && transfer.ExecutedAt != nil && !transfer.ExecutedAt.IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceTransfer, err := s.TransferLayingRepo.GetLatestApprovedBySourceKandang(ctx, projectFlockKandangID)
|
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
s.Log.Errorf("Failed to resolve transfer laying by source kandang %d for delete guard: %+v", projectFlockKandangID, err)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi transfer laying")
|
|
||||||
}
|
|
||||||
targetTransfer, err := s.TransferLayingRepo.GetLatestApprovedByTargetKandang(ctx, projectFlockKandangID)
|
|
||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
s.Log.Errorf("Failed to resolve transfer laying by target kandang %d for delete guard: %+v", projectFlockKandangID, err)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi transfer laying")
|
|
||||||
}
|
|
||||||
|
|
||||||
if isExecuted(sourceTransfer) || isExecuted(targetTransfer) {
|
|
||||||
return fiber.NewError(
|
|
||||||
fiber.StatusBadRequest,
|
|
||||||
"Chickin tidak dapat dihapus karena transfer laying sudah dieksekusi. Lakukan unexecute transfer terlebih dahulu",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *chickinService) resolveLayingTransferAvailableQty(ctx context.Context, tx *gorm.DB, targetProjectFlockKandangID, productWarehouseID uint) (float64, error) {
|
func (s *chickinService) resolveLayingTransferAvailableQty(ctx context.Context, tx *gorm.DB, targetProjectFlockKandangID, productWarehouseID uint) (float64, error) {
|
||||||
if targetProjectFlockKandangID == 0 || productWarehouseID == 0 {
|
if targetProjectFlockKandangID == 0 || productWarehouseID == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
@@ -674,8 +622,8 @@ func (s chickinService) ensurePopulationRouteScope(ctx context.Context, tx *gorm
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *chickinService) ensureNoRelatedRecording(ctx context.Context, tx *gorm.DB, chickin *entity.ProjectChickin) error {
|
func (s *chickinService) ensureNoDownstreamConsumptionForDelete(ctx context.Context, tx *gorm.DB, chickinID uint) error {
|
||||||
if chickin == nil || chickin.ProjectFlockKandangId == 0 {
|
if chickinID == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,30 +632,94 @@ func (s *chickinService) ensureNoRelatedRecording(ctx context.Context, tx *gorm.
|
|||||||
db = tx.WithContext(ctx)
|
db = tx.WithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
recordDateFloor := normalizeDateOnlyUTC(chickin.ChickInDate)
|
type downstreamRow struct {
|
||||||
var earliest entity.Recording
|
UsableType string `gorm:"column:usable_type"`
|
||||||
query := db.Model(&entity.Recording{}).
|
UsableID uint `gorm:"column:usable_id"`
|
||||||
Where("project_flock_kandangs_id = ?", chickin.ProjectFlockKandangId).
|
|
||||||
Where("deleted_at IS NULL")
|
|
||||||
if !recordDateFloor.IsZero() {
|
|
||||||
query = query.Where("record_datetime >= ?", recordDateFloor)
|
|
||||||
}
|
|
||||||
if err := query.Order("record_datetime ASC, id ASC").Take(&earliest).Error; err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s.Log.Errorf("Failed to validate related recordings for chickin %d: %+v", chickin.Id, err)
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi recording terkait chickin")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fiber.NewError(
|
var rows []downstreamRow
|
||||||
fiber.StatusBadRequest,
|
if err := db.Table("stock_allocations sa").
|
||||||
fmt.Sprintf(
|
Select("sa.usable_type, sa.usable_id").
|
||||||
"%s (recording tanggal %s)",
|
Joins("JOIN project_flock_populations pfp ON pfp.id = sa.stockable_id").
|
||||||
chickinDeleteRecordingGuardMessage,
|
Where("pfp.project_chickin_id = ?", chickinID).
|
||||||
normalizeDateOnlyUTC(earliest.RecordDatetime).Format("2006-01-02"),
|
Where("pfp.deleted_at IS NULL").
|
||||||
),
|
Where("sa.stockable_type = ?", fifo.StockableKeyProjectFlockPopulation.String()).
|
||||||
)
|
Where("sa.status = ?", entity.StockAllocationStatusActive).
|
||||||
|
Where("sa.allocation_purpose = ?", entity.StockAllocationPurposeConsume).
|
||||||
|
Where("sa.deleted_at IS NULL").
|
||||||
|
Where("sa.usable_type IN ?", []string{
|
||||||
|
fifo.UsableKeyMarketingDelivery.String(),
|
||||||
|
fifo.UsableKeyRecordingDepletion.String(),
|
||||||
|
fifo.UsableKeyTransferToLayingOut.String(),
|
||||||
|
}).
|
||||||
|
Group("sa.usable_type, sa.usable_id").
|
||||||
|
Scan(&rows).Error; err != nil {
|
||||||
|
s.Log.Errorf("Failed to validate downstream consumption for chickin %d: %+v", chickinID, err)
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi transaksi turunan chickin")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rows) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
marketingIDs := make(map[uint]struct{})
|
||||||
|
recordingIDs := make(map[uint]struct{})
|
||||||
|
transferLayingIDs := make(map[uint]struct{})
|
||||||
|
|
||||||
|
for _, row := range rows {
|
||||||
|
switch row.UsableType {
|
||||||
|
case fifo.UsableKeyMarketingDelivery.String():
|
||||||
|
marketingIDs[row.UsableID] = struct{}{}
|
||||||
|
case fifo.UsableKeyRecordingDepletion.String():
|
||||||
|
recordingIDs[row.UsableID] = struct{}{}
|
||||||
|
case fifo.UsableKeyTransferToLayingOut.String():
|
||||||
|
transferLayingIDs[row.UsableID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
details := make([]string, 0, 3)
|
||||||
|
if ids := sortedIDs(marketingIDs); len(ids) > 0 {
|
||||||
|
details = append(details, fmt.Sprintf("Marketing=%s", joinUint(ids)))
|
||||||
|
}
|
||||||
|
if ids := sortedIDs(recordingIDs); len(ids) > 0 {
|
||||||
|
details = append(details, fmt.Sprintf("Recording=%s", joinUint(ids)))
|
||||||
|
}
|
||||||
|
if ids := sortedIDs(transferLayingIDs); len(ids) > 0 {
|
||||||
|
details = append(details, fmt.Sprintf("TransferToLaying=%s", joinUint(ids)))
|
||||||
|
}
|
||||||
|
|
||||||
|
message := chickinDeleteDownstreamGuardMessage
|
||||||
|
if len(details) > 0 {
|
||||||
|
message = fmt.Sprintf("%s Dependensi aktif: %s.", message, strings.Join(details, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortedIDs(input map[uint]struct{}) []uint {
|
||||||
|
if len(input) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make([]uint, 0, len(input))
|
||||||
|
for id := range input {
|
||||||
|
if id == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, id)
|
||||||
|
}
|
||||||
|
sort.Slice(out, func(i, j int) bool { return out[i] < out[j] })
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinUint(values []uint) string {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return "-"
|
||||||
|
}
|
||||||
|
parts := make([]string, 0, len(values))
|
||||||
|
for _, value := range values {
|
||||||
|
parts = append(parts, fmt.Sprintf("%d", value))
|
||||||
|
}
|
||||||
|
return strings.Join(parts, "|")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *chickinService) hasActiveChickinConsumeAllocations(ctx context.Context, tx *gorm.DB, chickinID uint) (bool, error) {
|
func (s *chickinService) hasActiveChickinConsumeAllocations(ctx context.Context, tx *gorm.DB, chickinID uint) (bool, error) {
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ func (u *ProjectflockController) GetAll(c *fiber.Ctx) error {
|
|||||||
Search: c.Query("search", ""),
|
Search: c.Query("search", ""),
|
||||||
SortBy: c.Query("sort_by", ""),
|
SortBy: c.Query("sort_by", ""),
|
||||||
SortOrder: c.Query("sort_order", ""),
|
SortOrder: c.Query("sort_order", ""),
|
||||||
|
Status: strings.TrimSpace(c.Query("status", "")),
|
||||||
}
|
}
|
||||||
|
|
||||||
if area := c.QueryInt("area_id", 0); area > 0 {
|
if area := c.QueryInt("area_id", 0); area > 0 {
|
||||||
|
|||||||
+16
-5
@@ -51,6 +51,7 @@ func (r *projectFlockPopulationRepositoryImpl) GetByProjectFlockKandangID(ctx co
|
|||||||
err := r.DB().WithContext(ctx).
|
err := r.DB().WithContext(ctx).
|
||||||
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
Preload("ProjectChickin").
|
Preload("ProjectChickin").
|
||||||
Find(&records).Error
|
Find(&records).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,6 +88,7 @@ func (r *projectFlockPopulationRepositoryImpl) GetByProjectFlockKandangIDAndProd
|
|||||||
err := r.DB().WithContext(ctx).
|
err := r.DB().WithContext(ctx).
|
||||||
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
Where("project_chickins.project_flock_kandang_id = ? AND project_flock_populations.product_warehouse_id = ?", projectFlockKandangID, productWarehouseID).
|
Where("project_chickins.project_flock_kandang_id = ? AND project_flock_populations.product_warehouse_id = ?", projectFlockKandangID, productWarehouseID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
Find(&records).Error
|
Find(&records).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -99,8 +101,10 @@ func (r *projectFlockPopulationRepositoryImpl) GetTotalQtyByProjectFlockKandangI
|
|||||||
err := r.DB().WithContext(ctx).
|
err := r.DB().WithContext(ctx).
|
||||||
Table("project_flock_populations").
|
Table("project_flock_populations").
|
||||||
Select("COALESCE(SUM(total_qty - total_used_qty), 0) AS available_qty").
|
Select("COALESCE(SUM(total_qty - total_used_qty), 0) AS available_qty").
|
||||||
Joins("JOIN product_warehouses pw ON project_flock_populations.product_warehouse_id = pw.id").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
Where("pw.project_flock_kandang_id = ?", projectFlockKandangID).
|
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
|
Where("project_flock_populations.deleted_at IS NULL").
|
||||||
Scan(&total).Error
|
Scan(&total).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -111,9 +115,12 @@ func (r *projectFlockPopulationRepositoryImpl) GetTotalQtyByProjectFlockKandangI
|
|||||||
func (r *projectFlockPopulationRepositoryImpl) GetTotalQtyByProductWarehouseID(ctx context.Context, productWarehouseID uint) (float64, error) {
|
func (r *projectFlockPopulationRepositoryImpl) GetTotalQtyByProductWarehouseID(ctx context.Context, productWarehouseID uint) (float64, error) {
|
||||||
var total float64
|
var total float64
|
||||||
err := r.DB().WithContext(ctx).
|
err := r.DB().WithContext(ctx).
|
||||||
Model(&entity.ProjectFlockPopulation{}).
|
Table("project_flock_populations").
|
||||||
Where("product_warehouse_id = ?", productWarehouseID).
|
Select("COALESCE(SUM(project_flock_populations.total_qty - project_flock_populations.total_used_qty), 0)").
|
||||||
Select("COALESCE(SUM(total_qty - total_used_qty), 0)").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
|
Where("project_flock_populations.product_warehouse_id = ?", productWarehouseID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
|
Where("project_flock_populations.deleted_at IS NULL").
|
||||||
Scan(&total).Error
|
Scan(&total).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -128,6 +135,8 @@ func (r *projectFlockPopulationRepositoryImpl) GetAvailableQtyByProjectFlockKand
|
|||||||
Select("COALESCE(SUM(total_qty - total_used_qty), 0) AS total_qty").
|
Select("COALESCE(SUM(total_qty - total_used_qty), 0) AS total_qty").
|
||||||
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
|
Where("project_flock_populations.deleted_at IS NULL").
|
||||||
Scan(&total).Error
|
Scan(&total).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -145,6 +154,8 @@ func (r *projectFlockPopulationRepositoryImpl) GetTotalChickInByProjectFlockKand
|
|||||||
Select("COALESCE(SUM(project_flock_populations.total_qty - project_flock_populations.total_used_qty), 0) AS total_qty").
|
Select("COALESCE(SUM(project_flock_populations.total_qty - project_flock_populations.total_used_qty), 0) AS total_qty").
|
||||||
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
Joins("JOIN project_chickins ON project_chickins.id = project_flock_populations.project_chickin_id").
|
||||||
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
Where("project_chickins.project_flock_kandang_id = ?", projectFlockKandangID).
|
||||||
|
Where("project_chickins.deleted_at IS NULL").
|
||||||
|
Where("project_flock_populations.deleted_at IS NULL").
|
||||||
Scan(&total).Error
|
Scan(&total).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations"
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,6 +111,28 @@ func (r *ProjectflockRepositoryImpl) applyQueryFilters(db *gorm.DB, params *vali
|
|||||||
AND pfk.kandang_id IN ?
|
AND pfk.kandang_id IN ?
|
||||||
)`, params.KandangIds)
|
)`, params.KandangIds)
|
||||||
}
|
}
|
||||||
|
if params.Status != "" {
|
||||||
|
db = db.Where(`
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM approvals latest_approval
|
||||||
|
WHERE latest_approval.approvable_type = ?
|
||||||
|
AND latest_approval.approvable_id = project_flocks.id
|
||||||
|
AND latest_approval.id = (
|
||||||
|
SELECT a2.id
|
||||||
|
FROM approvals a2
|
||||||
|
WHERE a2.approvable_type = ?
|
||||||
|
AND a2.approvable_id = project_flocks.id
|
||||||
|
ORDER BY a2.id DESC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
AND LOWER(latest_approval.step_name) = LOWER(?)
|
||||||
|
)`,
|
||||||
|
utils.ApprovalWorkflowProjectFlock.String(),
|
||||||
|
utils.ApprovalWorkflowProjectFlock.String(),
|
||||||
|
params.Status,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
db = r.applySearchFilters(db, params.Search)
|
db = r.applySearchFilters(db, params.Search)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type Query struct {
|
|||||||
LocationId uint `query:"location_id" validate:"omitempty,number,gt=0"`
|
LocationId uint `query:"location_id" validate:"omitempty,number,gt=0"`
|
||||||
Period int `query:"period" validate:"omitempty,number,gt=0"`
|
Period int `query:"period" validate:"omitempty,number,gt=0"`
|
||||||
Category string `query:"category" validate:"omitempty"`
|
Category string `query:"category" validate:"omitempty"`
|
||||||
|
Status string `query:"status" validate:"omitempty,oneof=Pengajuan Aktif Selesai"`
|
||||||
KandangIds []uint `query:"kandang_id" validate:"omitempty,dive,gt=0"`
|
KandangIds []uint `query:"kandang_id" validate:"omitempty,dive,gt=0"`
|
||||||
TransferContext string `query:"transfer_context" validate:"omitempty,oneof=transfer_to_laying"`
|
TransferContext string `query:"transfer_context" validate:"omitempty,oneof=transfer_to_laying"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2409,15 +2409,10 @@ func (s *recordingService) reflowResetRecordingDepletionsOut(
|
|||||||
return errors.New("stock log repository is not available")
|
return errors.New("stock log repository is not available")
|
||||||
}
|
}
|
||||||
logState := newRecordingStockLogState()
|
logState := newRecordingStockLogState()
|
||||||
stockAllocationRepo := commonRepo.NewStockAllocationRepository(tx)
|
|
||||||
|
|
||||||
for _, depletion := range depletions {
|
for _, depletion := range depletions {
|
||||||
if depletion.Id == 0 {
|
if depletion.Id == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := stockAllocationRepo.ReleaseByUsable(ctx, fifo.UsableKeyRecordingDepletion.String(), depletion.Id, nil, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.logDepletionTrace("reflow_reset:start", depletion, "")
|
s.logDepletionTrace("reflow_reset:start", depletion, "")
|
||||||
|
|
||||||
sourceWarehouseID := uint(0)
|
sourceWarehouseID := uint(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user