From 511e5501bba491cc6c2a9fec3b719c5262ddfd1c Mon Sep 17 00:00:00 2001 From: aguhh18 Date: Tue, 9 Dec 2025 15:32:11 +0700 Subject: [PATCH] feat[BE]: create GetOverhead API, and fixing chickin use newest productwarehouse schema --- .../controllers/closing.controller.go | 22 +++ .../closings/dto/closingMarketing.dto.go | 1 - .../closings/dto/closingOverhead.dto.go | 175 ++++++++++++++++++ internal/modules/closings/module.go | 7 +- internal/modules/closings/route.go | 2 + .../closings/services/closing.service.go | 37 +++- .../expense_realization.repository.go | 26 ++- .../expenses/services/expense.service.go | 24 ++- .../modules/inventory/adjustments/route.go | 4 +- .../project_chickin.repository.go | 11 ++ .../chickins/services/chickin.service.go | 8 +- .../repositories/project_budget.repository.go | 13 ++ 12 files changed, 309 insertions(+), 21 deletions(-) create mode 100644 internal/modules/closings/dto/closingOverhead.dto.go diff --git a/internal/modules/closings/controllers/closing.controller.go b/internal/modules/closings/controllers/closing.controller.go index a9282f21..4ad6e02e 100644 --- a/internal/modules/closings/controllers/closing.controller.go +++ b/internal/modules/closings/controllers/closing.controller.go @@ -123,3 +123,25 @@ func (u *ClosingController) GetPenjualan(c *fiber.Ctx) error { Data: dto.ToPenjualanRealisasiResponseDTO(projectFlock.Category, uint(projectFlockID), result), }) } + +func (u *ClosingController) GetOverhead(c *fiber.Ctx) error { + param := c.Params("project_flock_id") + + projectFlockID, err := strconv.Atoi(param) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, "Invalid Project Flock Id") + } + + result, err := u.ClosingService.GetOverhead(c, uint(projectFlockID)) + if err != nil { + return err + } + + return c.Status(fiber.StatusOK). + JSON(response.Success{ + Code: fiber.StatusOK, + Status: "success", + Message: "Get overhead successfully", + Data: result, + }) +} diff --git a/internal/modules/closings/dto/closingMarketing.dto.go b/internal/modules/closings/dto/closingMarketing.dto.go index 4c47a7e0..e64a6735 100644 --- a/internal/modules/closings/dto/closingMarketing.dto.go +++ b/internal/modules/closings/dto/closingMarketing.dto.go @@ -11,7 +11,6 @@ import ( ) // === Response DTO === - type SalesDTO struct { Id uint `json:"id"` RealizationDate time.Time `json:"realization_date"` diff --git a/internal/modules/closings/dto/closingOverhead.dto.go b/internal/modules/closings/dto/closingOverhead.dto.go new file mode 100644 index 00000000..95f3e10b --- /dev/null +++ b/internal/modules/closings/dto/closingOverhead.dto.go @@ -0,0 +1,175 @@ +package dto + +import ( + entity "gitlab.com/mbugroup/lti-api.git/internal/entities" +) + +// === DTO Structs === + +type OverheadDTO struct { + ItemName string `json:"item_name"` + UOMName string `json:"uom_name"` + BudgetQuantity float64 `json:"budget_quantity"` + BudgetUnitPrice float64 `json:"budget_unit_price"` + BudgetTotalAmount float64 `json:"budget_total_amount"` + ActualDate string `json:"actual_date"` + ActualQuantity float64 `json:"actual_quantity"` + ActualUnitPrice float64 `json:"actual_unit_price"` + ActualTotalAmount float64 `json:"actual_total_amount"` + CostPerBird float64 `json:"cost_per_bird"` +} + +type TotalDTO struct { + BudgetQuantity float64 `json:"budget_quantity"` + BudgetTotalAmount float64 `json:"budget_total_amount"` + ActualQuantity float64 `json:"actual_quantity"` + ActualTotalAmount float64 `json:"actual_total_amount"` + CostPerBird float64 `json:"cost_per_bird"` +} + +type OverheadListDTO struct { + Total TotalDTO `json:"total"` + Overheads []OverheadDTO `json:"overheads"` +} + +// === Mapper Functions === + +func ToOverheadDTO(budget *entity.ProjectBudget, realization *entity.ExpenseRealization) OverheadDTO { + if budget == nil && realization == nil { + return OverheadDTO{} + } + + var itemName, itemUOM string + if budget != nil { + itemName, itemUOM = getItemInfo(budget.Nonstock) + } + + if itemName == "" && realization != nil && realization.ExpenseNonstock != nil { + itemName, itemUOM = getItemInfo(realization.ExpenseNonstock.Nonstock) + } + + dto := OverheadDTO{ + ItemName: itemName, + UOMName: itemUOM, + } + + if budget != nil { + dto.BudgetQuantity = budget.Qty + dto.BudgetUnitPrice = budget.Price + dto.BudgetTotalAmount = calculateTotal(budget.Qty, budget.Price) + } + + if realization != nil { + dto.ActualQuantity = realization.Qty + dto.ActualUnitPrice = realization.Price + dto.ActualTotalAmount = calculateTotal(realization.Qty, realization.Price) + dto.ActualDate = formatRealizationDate(realization) + } + + return dto +} + +func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty float64) OverheadListDTO { + overheadsByNonstockID := make(map[uint]*OverheadDTO) + latestDateByNonstockID := make(map[uint]string) + + for i := range budgets { + nonstockID := budgets[i].NonstockId + if overheadsByNonstockID[nonstockID] == nil { + overheadsByNonstockID[nonstockID] = &OverheadDTO{} + } + + itemName, itemUOM := getItemInfo(budgets[i].Nonstock) + overheadsByNonstockID[nonstockID].ItemName = itemName + overheadsByNonstockID[nonstockID].UOMName = itemUOM + overheadsByNonstockID[nonstockID].BudgetQuantity = budgets[i].Qty + overheadsByNonstockID[nonstockID].BudgetUnitPrice = budgets[i].Price + overheadsByNonstockID[nonstockID].BudgetTotalAmount = calculateTotal(budgets[i].Qty, budgets[i].Price) + } + + for i := range realizations { + if realizations[i].ExpenseNonstock == nil || realizations[i].ExpenseNonstock.NonstockId == nil { + continue + } + + nonstockID := uint(*realizations[i].ExpenseNonstock.NonstockId) + if overheadsByNonstockID[nonstockID] == nil { + overheadsByNonstockID[nonstockID] = &OverheadDTO{} + } + + overheadsByNonstockID[nonstockID].ActualQuantity += realizations[i].Qty + overheadsByNonstockID[nonstockID].ActualTotalAmount += calculateTotal(realizations[i].Qty, realizations[i].Price) + + if overheadsByNonstockID[nonstockID].ItemName == "" { + itemName, itemUOM := getItemInfo(realizations[i].ExpenseNonstock.Nonstock) + overheadsByNonstockID[nonstockID].ItemName = itemName + overheadsByNonstockID[nonstockID].UOMName = itemUOM + } + + realizationDateStr := formatRealizationDate(&realizations[i]) + if realizationDateStr != "" { + if latestDateByNonstockID[nonstockID] == "" || realizationDateStr > latestDateByNonstockID[nonstockID] { + latestDateByNonstockID[nonstockID] = realizationDateStr + } + } + } + + var totalBudgetQuantity, totalBudgetAmount, totalActualQuantity, totalActualAmount float64 + overheadItems := make([]OverheadDTO, 0, len(overheadsByNonstockID)) + + for nonstockID, overhead := range overheadsByNonstockID { + overhead.ActualDate = latestDateByNonstockID[nonstockID] + overhead.CostPerBird = calculateCostPerBird(overhead.ActualTotalAmount, totalChickinQty) + + if overhead.ActualQuantity > 0 { + overhead.ActualUnitPrice = overhead.ActualTotalAmount / overhead.ActualQuantity + } + + totalBudgetQuantity += overhead.BudgetQuantity + totalBudgetAmount += overhead.BudgetTotalAmount + totalActualQuantity += overhead.ActualQuantity + totalActualAmount += overhead.ActualTotalAmount + + overheadItems = append(overheadItems, *overhead) + } + + return OverheadListDTO{ + Total: TotalDTO{ + BudgetQuantity: totalBudgetQuantity, + BudgetTotalAmount: totalBudgetAmount, + ActualQuantity: totalActualQuantity, + ActualTotalAmount: totalActualAmount, + CostPerBird: calculateCostPerBird(totalActualAmount, totalChickinQty), + }, + Overheads: overheadItems, + } +} + +// === Helper Functions === + +func getItemInfo(nonstock *entity.Nonstock) (string, string) { + if nonstock != nil && nonstock.Id != 0 { + return nonstock.Name, nonstock.Uom.Name + } + return "", "" +} + +func calculateTotal(qty, price float64) float64 { + return qty * price +} + +func calculateCostPerBird(totalPrice, totalChickinQty float64) float64 { + if totalChickinQty > 0 { + return totalPrice / totalChickinQty + } + return 0 +} + +func formatRealizationDate(realization *entity.ExpenseRealization) string { + if realization != nil && realization.ExpenseNonstock != nil && realization.ExpenseNonstock.Expense != nil { + if !realization.ExpenseNonstock.Expense.RealizationDate.IsZero() { + return realization.ExpenseNonstock.Expense.RealizationDate.Format("2006-01-02T15:04:05Z07:00") + } + } + return "" +} diff --git a/internal/modules/closings/module.go b/internal/modules/closings/module.go index 77941256..af129eda 100644 --- a/internal/modules/closings/module.go +++ b/internal/modules/closings/module.go @@ -9,7 +9,9 @@ import ( commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" rClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories" sClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/services" + rExpenseRealization "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories" rMarketings "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories" + rChickin "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories" rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories" @@ -22,12 +24,15 @@ func (ClosingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate * closingRepo := rClosing.NewClosingRepository(db) userRepo := rUser.NewUserRepository(db) projectFlockRepo := rProjectFlock.NewProjectflockRepository(db) + projectBudgetRepo := rProjectFlock.NewProjectBudgetRepository(db) marketingRepo := rMarketings.NewMarketingRepository(db) marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db) + expenseRealizationRepo := rExpenseRealization.NewExpenseRealizationRepository(db) + chickinRepo := rChickin.NewChickinRepository(db) approvalRepo := commonRepo.NewApprovalRepository(db) approvalService := commonSvc.NewApprovalService(approvalRepo) - closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, validate) + closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, expenseRealizationRepo, projectBudgetRepo, chickinRepo, validate) userService := sUser.NewUserService(userRepo, validate) ClosingRoutes(router, userService, closingService) diff --git a/internal/modules/closings/route.go b/internal/modules/closings/route.go index ba18f3b9..2d2221a8 100644 --- a/internal/modules/closings/route.go +++ b/internal/modules/closings/route.go @@ -22,5 +22,7 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService route.Get("/", ctrl.GetAll) route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan) + route.Get("/:project_flock_id/overhead", ctrl.GetOverhead) route.Get("/:projectFlockId", ctrl.GetClosingSummary) + } diff --git a/internal/modules/closings/services/closing.service.go b/internal/modules/closings/services/closing.service.go index 7fcd51ec..621fdb8f 100644 --- a/internal/modules/closings/services/closing.service.go +++ b/internal/modules/closings/services/closing.service.go @@ -9,8 +9,10 @@ import ( "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/dto" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/validations" + expenseRealizationRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories" marketingDeliveryProductRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories" marketingRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories" + chickinRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories" projectflockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories" "gitlab.com/mbugroup/lti-api.git/internal/utils" approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals" @@ -26,6 +28,7 @@ type ClosingService interface { GetProjectFlockByID(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error) GetPenjualan(ctx *fiber.Ctx, projectFlockID uint) ([]entity.MarketingDeliveryProduct, error) GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error) + GetOverhead(ctx *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error) } type closingService struct { @@ -36,9 +39,12 @@ type closingService struct { MarketingRepo marketingRepository.MarketingRepository MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository ApprovalSvc commonSvc.ApprovalService + ExpenseRealizationRepo expenseRealizationRepository.ExpenseRealizationRepository + ProjectBudgetRepo projectflockRepository.ProjectBudgetRepository + ChickinRepo chickinRepository.ProjectChickinRepository } -func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, validate *validator.Validate) ClosingService { +func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, expenseRealizationRepo expenseRealizationRepository.ExpenseRealizationRepository, projectBudgetRepo projectflockRepository.ProjectBudgetRepository, chickinRepo chickinRepository.ProjectChickinRepository, validate *validator.Validate) ClosingService { return &closingService{ Log: utils.Log, Validate: validate, @@ -47,6 +53,9 @@ func NewClosingService(repo repository.ClosingRepository, projectFlockRepo proje MarketingRepo: marketingRepo, MarketingDeliveryProductRepo: marketingDeliveryProductRepo, ApprovalSvc: approvalSvc, + ExpenseRealizationRepo: expenseRealizationRepo, + ProjectBudgetRepo: projectBudgetRepo, + ChickinRepo: chickinRepo, } } @@ -188,3 +197,29 @@ func (s closingService) getApprovalStatuses(ctx context.Context, projectFlockID return statusProject, statusClosing, nil } + +func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error) { + budgets, err := s.ProjectBudgetRepo.GetByProjectFlockID(c.Context(), projectFlockID) + if err != nil { + return nil, err + } + + realizations, err := s.ExpenseRealizationRepo.GetByProjectFlockID(c.Context(), projectFlockID) + if err != nil { + return nil, err + } + + chickins, err := s.ChickinRepo.GetByProjectFlockID(c.Context(), projectFlockID) + if err != nil { + return nil, err + } + + var totalChickinQty float64 + for _, chickin := range chickins { + totalChickinQty += chickin.UsageQty + } + + result := dto.ToOverheadListDTOs(budgets, realizations, totalChickinQty) + + return &result, nil +} diff --git a/internal/modules/expenses/repositories/expense_realization.repository.go b/internal/modules/expenses/repositories/expense_realization.repository.go index 77f075f7..e60324ca 100644 --- a/internal/modules/expenses/repositories/expense_realization.repository.go +++ b/internal/modules/expenses/repositories/expense_realization.repository.go @@ -12,6 +12,7 @@ type ExpenseRealizationRepository interface { repository.BaseRepository[entity.ExpenseRealization] IdExists(ctx context.Context, id uint64) (bool, error) GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error) + GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error) } type ExpenseRealizationRepositoryImpl struct { @@ -30,11 +31,22 @@ func (r *ExpenseRealizationRepositoryImpl) IdExists(ctx context.Context, id uint func (r *ExpenseRealizationRepositoryImpl) GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error) { var realization entity.ExpenseRealization - err := r.DB().WithContext(ctx). - Where("expense_nonstock_id = ?", expenseNonstockID). - First(&realization).Error - if err != nil { - return nil, err - } - return &realization, nil + err := r.DB().WithContext(ctx).Where("expense_nonstock_id = ?", expenseNonstockID).First(&realization).Error + return &realization, err +} + +func (r *ExpenseRealizationRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error) { + var realizations []entity.ExpenseRealization + err := r.DB().WithContext(ctx). + Preload("ExpenseNonstock"). + Preload("ExpenseNonstock.Nonstock"). + Preload("ExpenseNonstock.Nonstock.Uom"). + Preload("ExpenseNonstock.Expense"). + Joins("JOIN expense_nonstocks ON expense_nonstocks.id = expense_realizations.expense_nonstock_id"). + Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = expense_nonstocks.project_flock_kandang_id"). + Joins("JOIN expenses ON expenses.id = expense_nonstocks.expense_id"). + Where("project_flock_kandangs.project_flock_id = ?", projectFlockID). + Where("expenses.category = ?", "BOP"). + Find(&realizations).Error + return realizations, err } diff --git a/internal/modules/expenses/services/expense.service.go b/internal/modules/expenses/services/expense.service.go index 7de05689..0b768f0a 100644 --- a/internal/modules/expenses/services/expense.service.go +++ b/internal/modules/expenses/services/expense.service.go @@ -11,6 +11,7 @@ import ( commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository" commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" + middleware "gitlab.com/mbugroup/lti-api.git/internal/middleware" expenseDto "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/dto" repository "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories" validation "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/validations" @@ -188,7 +189,11 @@ func (s *expenseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*expen return fiber.NewError(fiber.StatusInternalServerError, "Failed to generate reference number") } - createdBy := uint64(1) //todo get from auth + actorID, err := middleware.ActorIDFromContext(c) + if err != nil { + return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") + } + createdBy := uint64(actorID) expense = &entity.Expense{ ReferenceNumber: referenceNumber, PoNumber: req.PoNumber, @@ -496,7 +501,10 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) } } - actorID := uint(1) // TODO: replace with authenticated user id + actorID, err := middleware.ActorIDFromContext(c) + if err != nil { + return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") + } if *latestApproval.Action != entity.ApprovalActionUpdated { approvalAction := entity.ApprovalActionUpdated @@ -655,7 +663,10 @@ func (s *expenseService) CompleteExpense(c *fiber.Ctx, id uint, notes *string) ( return nil, err } - actorID := uint(1) // TODO: replace with authenticated user id + actorID, err := middleware.ActorIDFromContext(c) + if err != nil { + return nil, fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") + } latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowExpense, id, nil) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { @@ -960,11 +971,14 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest, return nil, fiber.NewError(fiber.StatusBadRequest, "No expense IDs provided") } - actorID := uint(1) // TODO: replace with authenticated user id + actorID, err := middleware.ActorIDFromContext(c) + if err != nil { + return nil, fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") + } var results []expenseDto.ExpenseDetailDTO - err := s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { + err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error { approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(tx)) expenseRepoTx := repository.NewExpenseRepository(tx) diff --git a/internal/modules/inventory/adjustments/route.go b/internal/modules/inventory/adjustments/route.go index 8f58bb4d..57200215 100644 --- a/internal/modules/inventory/adjustments/route.go +++ b/internal/modules/inventory/adjustments/route.go @@ -1,7 +1,7 @@ package adjustments import ( - // m "gitlab.com/mbugroup/lti-api.git/internal/middleware" + m "gitlab.com/mbugroup/lti-api.git/internal/middleware" controller "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/controllers" adjustment "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/services" user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" @@ -13,7 +13,7 @@ func AdjustmentRoutes(v1 fiber.Router, u user.UserService, s adjustment.Adjustme ctrl := controller.NewAdjustmentController(s) route := v1.Group("/adjustments") - + route.Use(m.Auth(u)) // Standard CRUD routes following master data pattern route.Get("/", ctrl.AdjustmentHistory) // Get all with pagination and filters route.Post("/", ctrl.Adjustment) // Create adjustment diff --git a/internal/modules/production/chickins/repositories/project_chickin.repository.go b/internal/modules/production/chickins/repositories/project_chickin.repository.go index a98dab67..bef062f5 100644 --- a/internal/modules/production/chickins/repositories/project_chickin.repository.go +++ b/internal/modules/production/chickins/repositories/project_chickin.repository.go @@ -11,6 +11,7 @@ import ( type ProjectChickinRepository interface { repository.BaseRepository[entity.ProjectChickin] GetFirstByProjectFlockID(ctx context.Context, projectFlockID uint) (*entity.ProjectChickin, error) + GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectChickin, error) GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) GetPendingByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) GetTotalPendingUsageQtyByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error) @@ -40,6 +41,16 @@ func (r *ChickinRepositoryImpl) GetFirstByProjectFlockID(ctx context.Context, pr return &chickin, nil } +func (r *ChickinRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectChickin, error) { + var chickins []entity.ProjectChickin + err := r.db.WithContext(ctx). + Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = project_chickins.project_flock_kandang_id"). + Where("project_flock_kandangs.project_flock_id = ?", projectFlockID). + Order("project_chickins.created_at DESC"). + Find(&chickins).Error + return chickins, err +} + func (r *ChickinRepositoryImpl) GetByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) ([]entity.ProjectChickin, error) { var chickins []entity.ProjectChickin err := r.db.WithContext(ctx). diff --git a/internal/modules/production/chickins/services/chickin.service.go b/internal/modules/production/chickins/services/chickin.service.go index 660f1e7e..54fd2cb1 100644 --- a/internal/modules/production/chickins/services/chickin.service.go +++ b/internal/modules/production/chickins/services/chickin.service.go @@ -197,7 +197,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti if category == string(utils.ProjectFlockCategoryLaying) { for _, chickin := range newChikins { - updates := map[string]any{"quantity": gorm.Expr("quantity - ?", chickin.PendingUsageQty)} + updates := map[string]any{"qty": gorm.Expr("qty - ?", chickin.PendingUsageQty)} if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -498,7 +498,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit for _, chickin := range chickins { if categoryForRejection == string(utils.ProjectFlockCategoryGrowing) { - updates := map[string]any{"quantity": gorm.Expr("quantity + ?", chickin.PendingUsageQty)} + updates := map[string]any{"qty": gorm.Expr("qty + ?", chickin.PendingUsageQty)} if err := productWarehouseTx.PatchOne(c.Context(), chickin.ProductWarehouseId, updates, nil); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -600,7 +600,7 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti if chickin.ProductWarehouseId != targetPW.Id { if err := productWarehouseTx.PatchOne(ctx.Context(), chickin.ProductWarehouseId, map[string]any{ - "quantity": gorm.Expr("quantity - ?", quantityToConvert), + "qty": gorm.Expr("qty - ?", quantityToConvert), }, nil); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Source product warehouse %d not found", chickin.ProductWarehouseId)) @@ -610,7 +610,7 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti } if err := productWarehouseTx.PatchOne(ctx.Context(), targetPW.Id, map[string]any{ - "quantity": gorm.Expr("quantity + ?", quantityToConvert), + "qty": gorm.Expr("qty + ?", quantityToConvert), }, nil); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Target product warehouse %d not found", targetPW.Id)) diff --git a/internal/modules/production/project_flocks/repositories/project_budget.repository.go b/internal/modules/production/project_flocks/repositories/project_budget.repository.go index 943a22b3..720bfc40 100644 --- a/internal/modules/production/project_flocks/repositories/project_budget.repository.go +++ b/internal/modules/production/project_flocks/repositories/project_budget.repository.go @@ -1,6 +1,8 @@ package repository import ( + "context" + "gitlab.com/mbugroup/lti-api.git/internal/common/repository" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" @@ -8,6 +10,7 @@ import ( type ProjectBudgetRepository interface { repository.BaseRepository[entity.ProjectBudget] + GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectBudget, error) } type ProjectBudgetRepositoryImpl struct { @@ -21,3 +24,13 @@ func NewProjectBudgetRepository(db *gorm.DB) ProjectBudgetRepository { db: db, } } + +func (r *ProjectBudgetRepositoryImpl) GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ProjectBudget, error) { + var budgets []entity.ProjectBudget + err := r.db.WithContext(ctx). + Where("project_flock_id = ?", projectFlockID). + Preload("Nonstock"). + Preload("Nonstock.Uom"). + Find(&budgets).Error + return budgets, err +}