mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat[BE]: add GetOverheadByProjectFlockKandang endpoint and update related services
This commit is contained in:
@@ -78,6 +78,36 @@ func (u *ClosingController) GetOne(c *fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ClosingController) GetOverheadByProjectFlockKandang(c *fiber.Ctx) error {
|
||||||
|
projectParam := c.Params("project_flock_id")
|
||||||
|
kandangParam := c.Params("project_flock_kandang_id")
|
||||||
|
|
||||||
|
projectFlockID, err := strconv.Atoi(projectParam)
|
||||||
|
if err != nil || projectFlockID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
pfkID, err := strconv.Atoi(kandangParam)
|
||||||
|
if err != nil || pfkID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_kandang_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
kandangID := uint(pfkID)
|
||||||
|
|
||||||
|
result, err := u.ClosingService.GetOverhead(c, uint(projectFlockID), &kandangID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).
|
||||||
|
JSON(response.Success{
|
||||||
|
Code: fiber.StatusOK,
|
||||||
|
Status: "success",
|
||||||
|
Message: "Get overhead by project flock kandang successfully",
|
||||||
|
Data: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ClosingController) GetClosingSummary(c *fiber.Ctx) error {
|
func (u *ClosingController) GetClosingSummary(c *fiber.Ctx) error {
|
||||||
param := c.Params("projectFlockId")
|
param := c.Params("projectFlockId")
|
||||||
|
|
||||||
@@ -153,14 +183,25 @@ func (u *ClosingController) GetPenjualanByProjectFlockKandang(c *fiber.Ctx) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *ClosingController) GetOverhead(c *fiber.Ctx) error {
|
func (u *ClosingController) GetOverhead(c *fiber.Ctx) error {
|
||||||
param := c.Params("project_flock_id")
|
projectParam := c.Params("project_flock_id")
|
||||||
|
kandangParam := c.Params("project_flock_kandang_id") // bisa kosong
|
||||||
|
|
||||||
projectFlockID, err := strconv.Atoi(param)
|
projectFlockID, err := strconv.Atoi(projectParam)
|
||||||
if err != nil {
|
if err != nil || projectFlockID <= 0 {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Project Flock Id")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id")
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := u.ClosingService.GetOverhead(c, uint(projectFlockID))
|
var projectFlockKandangID *uint
|
||||||
|
if kandangParam != "" {
|
||||||
|
pfkID, err := strconv.Atoi(kandangParam)
|
||||||
|
if err != nil || pfkID <= 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_kandang_id")
|
||||||
|
}
|
||||||
|
kandangID := uint(pfkID)
|
||||||
|
projectFlockKandangID = &kandangID
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := u.ClosingService.GetOverhead(c, uint(projectFlockID), projectFlockKandangID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,10 +79,11 @@ type HppGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SummaryHpp struct {
|
type SummaryHpp struct {
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Comparison `json:"-"`
|
Budgeting FinancialMetrics `json:"budgeting"`
|
||||||
EggBudgeting *FinancialMetrics `json:"egg_budgeting,omitempty"`
|
Realization FinancialMetrics `json:"realization"`
|
||||||
EggRealization *FinancialMetrics `json:"egg_realization,omitempty"`
|
EggBudgeting *FinancialMetrics `json:"egg_budgeting,omitempty"`
|
||||||
|
EggRealization *FinancialMetrics `json:"egg_realization,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HppPurchasesSection struct {
|
type HppPurchasesSection struct {
|
||||||
@@ -246,11 +247,9 @@ func ToSummaryHpp(label string, purchaseItems []entities.PurchaseItem, budgets [
|
|||||||
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(totalRealization, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
realizationRpPerBird, realizationRpPerKg := calculatePerUnitMetrics(totalRealization, ctx.TotalPopulation, ctx.TotalWeightProduced)
|
||||||
|
|
||||||
summary := SummaryHpp{
|
summary := SummaryHpp{
|
||||||
Label: label,
|
Label: label,
|
||||||
Comparison: ToComparison(
|
Budgeting: ToFinancialMetrics(budgetRpPerBird, budgetRpPerKg, totalBudget),
|
||||||
ToFinancialMetrics(budgetRpPerBird, budgetRpPerKg, totalBudget),
|
Realization: ToFinancialMetrics(realizationRpPerBird, realizationRpPerKg, totalRealization),
|
||||||
ToFinancialMetrics(realizationRpPerBird, realizationRpPerKg, totalRealization),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if projectFlockCategory == string(utils.ProjectFlockCategoryLaying) && ctx.TotalEggWeightKg > 0 {
|
if projectFlockCategory == string(utils.ProjectFlockCategoryLaying) && ctx.TotalEggWeightKg > 0 {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package dto
|
package dto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -69,7 +71,7 @@ func ToOverheadDTO(budget *entity.ProjectBudget, realization *entity.ExpenseReal
|
|||||||
return dto
|
return dto
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty, totalActualPopulation float64) OverheadListDTO {
|
func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.ExpenseRealization, totalChickinQty, totalActualPopulation float64, isPerKandang bool, totalKandangCount int) OverheadListDTO {
|
||||||
overheadsByNonstockID := make(map[uint]*OverheadDTO)
|
overheadsByNonstockID := make(map[uint]*OverheadDTO)
|
||||||
latestDateByNonstockID := make(map[uint]string)
|
latestDateByNonstockID := make(map[uint]string)
|
||||||
|
|
||||||
@@ -82,9 +84,19 @@ func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.Ex
|
|||||||
itemName, itemUOM := getItemInfo(budgets[i].Nonstock)
|
itemName, itemUOM := getItemInfo(budgets[i].Nonstock)
|
||||||
overheadsByNonstockID[nonstockID].ItemName = itemName
|
overheadsByNonstockID[nonstockID].ItemName = itemName
|
||||||
overheadsByNonstockID[nonstockID].UOMName = itemUOM
|
overheadsByNonstockID[nonstockID].UOMName = itemUOM
|
||||||
overheadsByNonstockID[nonstockID].BudgetQuantity = budgets[i].Qty
|
|
||||||
overheadsByNonstockID[nonstockID].BudgetUnitPrice = budgets[i].Price
|
budgetQty := budgets[i].Qty
|
||||||
overheadsByNonstockID[nonstockID].BudgetTotalAmount = calculateTotal(budgets[i].Qty, budgets[i].Price)
|
budgetPrice := budgets[i].Price
|
||||||
|
budgetTotal := calculateTotal(budgets[i].Qty, budgets[i].Price)
|
||||||
|
|
||||||
|
if isPerKandang && totalKandangCount > 0 {
|
||||||
|
budgetQty = budgetQty / float64(totalKandangCount)
|
||||||
|
budgetTotal = budgetTotal / float64(totalKandangCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetQuantity = budgetQty
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetUnitPrice = budgetPrice
|
||||||
|
overheadsByNonstockID[nonstockID].BudgetTotalAmount = budgetTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range realizations {
|
for i := range realizations {
|
||||||
@@ -97,8 +109,22 @@ func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.Ex
|
|||||||
overheadsByNonstockID[nonstockID] = &OverheadDTO{}
|
overheadsByNonstockID[nonstockID] = &OverheadDTO{}
|
||||||
}
|
}
|
||||||
|
|
||||||
overheadsByNonstockID[nonstockID].ActualQuantity += realizations[i].Qty
|
// Check if this is farm-level expense (multiple project flocks)
|
||||||
overheadsByNonstockID[nonstockID].ActualTotalAmount += calculateTotal(realizations[i].Qty, realizations[i].Price)
|
qty := realizations[i].Qty
|
||||||
|
totalAmount := calculateTotal(realizations[i].Qty, realizations[i].Price)
|
||||||
|
|
||||||
|
if realizations[i].ExpenseNonstock.Expense != nil &&
|
||||||
|
realizations[i].ExpenseNonstock.Expense.ProjectFlockId != nil {
|
||||||
|
projectFlockCount := countProjectFlocksInJSON(*realizations[i].ExpenseNonstock.Expense.ProjectFlockId)
|
||||||
|
if projectFlockCount > 1 {
|
||||||
|
// Bagi biaya sesuai jumlah project flock
|
||||||
|
qty = qty / float64(projectFlockCount)
|
||||||
|
totalAmount = totalAmount / float64(projectFlockCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overheadsByNonstockID[nonstockID].ActualQuantity += qty
|
||||||
|
overheadsByNonstockID[nonstockID].ActualTotalAmount += totalAmount
|
||||||
|
|
||||||
if overheadsByNonstockID[nonstockID].ItemName == "" {
|
if overheadsByNonstockID[nonstockID].ItemName == "" {
|
||||||
itemName, itemUOM := getItemInfo(realizations[i].ExpenseNonstock.Nonstock)
|
itemName, itemUOM := getItemInfo(realizations[i].ExpenseNonstock.Nonstock)
|
||||||
@@ -148,6 +174,23 @@ func ToOverheadListDTOs(budgets []entity.ProjectBudget, realizations []entity.Ex
|
|||||||
|
|
||||||
// === Helper Functions ===
|
// === Helper Functions ===
|
||||||
|
|
||||||
|
func countProjectFlocksInJSON(projectFlockJSON string) int {
|
||||||
|
if projectFlockJSON == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectFlocks []int
|
||||||
|
if err := json.Unmarshal([]byte(projectFlockJSON), &projectFlocks); err != nil {
|
||||||
|
return 1 // default to 1 if parsing fails
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(projectFlocks) == 0 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(projectFlocks)
|
||||||
|
}
|
||||||
|
|
||||||
func getItemInfo(nonstock *entity.Nonstock) (string, string) {
|
func getItemInfo(nonstock *entity.Nonstock) (string, string) {
|
||||||
if nonstock != nil && nonstock.Id != 0 {
|
if nonstock != nil && nonstock.Id != 0 {
|
||||||
return nonstock.Name, nonstock.Uom.Name
|
return nonstock.Name, nonstock.Uom.Name
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func (ClosingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *
|
|||||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||||
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||||
|
|
||||||
closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, expenseRealizationRepo, projectBudgetRepo, chickinRepo, purchaseRepo, recordingRepo, validate)
|
closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, projectFlockKandangRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, expenseRealizationRepo, projectBudgetRepo, chickinRepo, purchaseRepo, recordingRepo, validate)
|
||||||
sapronakService := sClosing.NewSapronakService(closingRepo, projectFlockKandangRepo, validate)
|
sapronakService := sClosing.NewSapronakService(closingRepo, projectFlockKandangRepo, validate)
|
||||||
userService := sUser.NewUserService(userRepo, validate)
|
userService := sUser.NewUserService(userRepo, validate)
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
|||||||
route.Get("/:project_flock_id/:project_flock_kandang_id/penjualan", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetPenjualanByProjectFlockKandang)
|
route.Get("/:project_flock_id/:project_flock_kandang_id/penjualan", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetPenjualanByProjectFlockKandang)
|
||||||
route.Get("/:projectFlockId", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSummary)
|
route.Get("/:projectFlockId", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSummary)
|
||||||
route.Get("/:project_flock_id/overhead", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetOverhead)
|
route.Get("/:project_flock_id/overhead", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetOverhead)
|
||||||
|
route.Get("/:project_flock_id/:project_flock_kandang_id/overhead", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetOverhead)
|
||||||
route.Get("/:project_flock_id/:project_flock_kandang_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByKandang)
|
route.Get("/:project_flock_id/:project_flock_kandang_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByKandang)
|
||||||
route.Get("/:project_flock_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByProject)
|
route.Get("/:project_flock_id/perhitungan_sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetSapronakByProject)
|
||||||
route.Get("/:projectFlockId/sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSapronak)
|
route.Get("/:projectFlockId/sapronak", m.RequirePermissions(m.P_ClosingDetail), ctrl.GetClosingSapronak)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ type ClosingService interface {
|
|||||||
GetProjectFlockByID(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
GetProjectFlockByID(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
||||||
GetPenjualan(ctx *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error)
|
GetPenjualan(ctx *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) ([]entity.MarketingDeliveryProduct, error)
|
||||||
GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error)
|
GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error)
|
||||||
GetOverhead(ctx *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error)
|
GetOverhead(ctx *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) (*dto.OverheadListDTO, error)
|
||||||
GetClosingDataProduksi(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error)
|
GetClosingDataProduksi(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingProductionReportDTO, error)
|
||||||
GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.ClosingSapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error)
|
GetClosingSapronak(ctx *fiber.Ctx, projectFlockID uint, params *validation.ClosingSapronakQuery) ([]dto.ClosingSapronakItemDTO, int64, error)
|
||||||
GetClosingKeuangan(ctx *fiber.Ctx, projectFlockID uint) (*dto.ReportResponse, error)
|
GetClosingKeuangan(ctx *fiber.Ctx, projectFlockID uint) (*dto.ReportResponse, error)
|
||||||
@@ -46,6 +46,7 @@ type closingService struct {
|
|||||||
Validate *validator.Validate
|
Validate *validator.Validate
|
||||||
Repository repository.ClosingRepository
|
Repository repository.ClosingRepository
|
||||||
ProjectFlockRepo projectflockRepository.ProjectflockRepository
|
ProjectFlockRepo projectflockRepository.ProjectflockRepository
|
||||||
|
ProjectFlockKandangRepo projectflockRepository.ProjectFlockKandangRepository
|
||||||
MarketingRepo marketingRepository.MarketingRepository
|
MarketingRepo marketingRepository.MarketingRepository
|
||||||
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
||||||
ApprovalSvc commonSvc.ApprovalService
|
ApprovalSvc commonSvc.ApprovalService
|
||||||
@@ -56,12 +57,13 @@ type closingService struct {
|
|||||||
RecordingRepo recordingRepository.RecordingRepository
|
RecordingRepo recordingRepository.RecordingRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
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, purchaseRepo purchaseRepository.PurchaseRepository, recordingRepo recordingRepository.RecordingRepository, validate *validator.Validate) ClosingService {
|
func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, projectFlockKandangRepo projectflockRepository.ProjectFlockKandangRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, expenseRealizationRepo expenseRealizationRepository.ExpenseRealizationRepository, projectBudgetRepo projectflockRepository.ProjectBudgetRepository, chickinRepo chickinRepository.ProjectChickinRepository, purchaseRepo purchaseRepository.PurchaseRepository, recordingRepo recordingRepository.RecordingRepository, validate *validator.Validate) ClosingService {
|
||||||
return &closingService{
|
return &closingService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
Validate: validate,
|
Validate: validate,
|
||||||
Repository: repo,
|
Repository: repo,
|
||||||
ProjectFlockRepo: projectFlockRepo,
|
ProjectFlockRepo: projectFlockRepo,
|
||||||
|
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||||
MarketingRepo: marketingRepo,
|
MarketingRepo: marketingRepo,
|
||||||
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
||||||
ApprovalSvc: approvalSvc,
|
ApprovalSvc: approvalSvc,
|
||||||
@@ -355,35 +357,67 @@ func (s closingService) getApprovalStatuses(ctx context.Context, projectFlockID
|
|||||||
return statusProject, statusClosing, nil
|
return statusProject, statusClosing, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint) (*dto.OverheadListDTO, error) {
|
func (s closingService) GetOverhead(c *fiber.Ctx, projectFlockID uint, projectFlockKandangID *uint) (*dto.OverheadListDTO, error) {
|
||||||
budgets, err := s.ProjectBudgetRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
budgets, err := s.ProjectBudgetRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
realizations, err := s.ExpenseRealizationRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
realizations, err := s.ExpenseRealizationRepo.GetClosingOverhead(c.Context(), projectFlockID, projectFlockKandangID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count total kandang in project flock (for budget division if per kandang)
|
||||||
|
projectFlockKandangs, err := s.ProjectFlockKandangRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
totalKandangCount := len(projectFlockKandangs)
|
||||||
|
|
||||||
chickins, err := s.ChickinRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
chickins, err := s.ChickinRepo.GetByProjectFlockID(c.Context(), projectFlockID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalChickinQty float64
|
var totalChickinQty float64
|
||||||
for _, chickin := range chickins {
|
var totalDepletion float64
|
||||||
totalChickinQty += chickin.UsageQty
|
|
||||||
}
|
|
||||||
|
|
||||||
totalDepletion, err := s.RecordingRepo.GetTotalDepletionByProjectFlockID(c.Context(), projectFlockID)
|
if projectFlockKandangID != nil {
|
||||||
if err != nil {
|
|
||||||
s.Log.Warnf("GetTotalDepletionByProjectFlockID error: %v", err)
|
for _, chickin := range chickins {
|
||||||
|
if chickin.ProjectFlockKandangId == *projectFlockKandangID {
|
||||||
|
totalChickinQty += chickin.UsageQty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var depletionResult float64
|
||||||
|
err = s.RecordingRepo.DB().WithContext(c.Context()).
|
||||||
|
Table("recording_depletions").
|
||||||
|
Select("COALESCE(SUM(recording_depletions.qty), 0)").
|
||||||
|
Joins("JOIN recordings ON recordings.id = recording_depletions.recording_id").
|
||||||
|
Where("recordings.project_flock_kandangs_id = ?", *projectFlockKandangID).
|
||||||
|
Scan(&depletionResult).Error
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Warnf("GetTotalDepletionByProjectFlockKandangID error: %v", err)
|
||||||
|
} else {
|
||||||
|
totalDepletion = depletionResult
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for _, chickin := range chickins {
|
||||||
|
totalChickinQty += chickin.UsageQty
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDepletion, err = s.RecordingRepo.GetTotalDepletionByProjectFlockID(c.Context(), projectFlockID)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Warnf("GetTotalDepletionByProjectFlockID error: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalActualPopulation := totalChickinQty - totalDepletion
|
totalActualPopulation := totalChickinQty - totalDepletion
|
||||||
|
|
||||||
result := dto.ToOverheadListDTOs(budgets, realizations, totalChickinQty, totalActualPopulation)
|
result := dto.ToOverheadListDTOs(budgets, realizations, totalChickinQty, totalActualPopulation, projectFlockKandangID != nil, totalKandangCount)
|
||||||
|
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"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"
|
||||||
@@ -15,6 +16,7 @@ type ExpenseRealizationRepository interface {
|
|||||||
IdExists(ctx context.Context, id uint64) (bool, error)
|
IdExists(ctx context.Context, id uint64) (bool, error)
|
||||||
GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error)
|
GetByExpenseNonstockID(ctx context.Context, expenseNonstockID uint64) (*entity.ExpenseRealization, error)
|
||||||
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error)
|
GetByProjectFlockID(ctx context.Context, projectFlockID uint) ([]entity.ExpenseRealization, error)
|
||||||
|
GetClosingOverhead(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]entity.ExpenseRealization, error)
|
||||||
GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.ExpenseQuery) ([]entity.ExpenseRealization, int64, error)
|
GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.ExpenseQuery) ([]entity.ExpenseRealization, int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +57,44 @@ func (r *ExpenseRealizationRepositoryImpl) GetByProjectFlockID(ctx context.Conte
|
|||||||
return realizations, err
|
return realizations, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ExpenseRealizationRepositoryImpl) GetClosingOverhead(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]entity.ExpenseRealization, error) {
|
||||||
|
var realizations []entity.ExpenseRealization
|
||||||
|
|
||||||
|
db := r.DB().WithContext(ctx).
|
||||||
|
Preload("ExpenseNonstock").
|
||||||
|
Preload("ExpenseNonstock.Nonstock").
|
||||||
|
Preload("ExpenseNonstock.Nonstock.Uom").
|
||||||
|
Preload("ExpenseNonstock.Nonstock.Flags").
|
||||||
|
Preload("ExpenseNonstock.Expense").
|
||||||
|
Joins("JOIN expense_nonstocks ON expense_nonstocks.id = expense_realizations.expense_nonstock_id").
|
||||||
|
Joins("JOIN expenses ON expenses.id = expense_nonstocks.expense_id").
|
||||||
|
Joins("LEFT JOIN project_flock_kandangs ON project_flock_kandangs.id = expense_nonstocks.project_flock_kandang_id").
|
||||||
|
Joins("LEFT JOIN kandangs ON kandangs.id = expense_nonstocks.kandang_id").
|
||||||
|
Where("expenses.realization_date IS NOT NULL")
|
||||||
|
|
||||||
|
// Build WHERE clause for project flock filtering
|
||||||
|
if projectFlockKandangID != nil {
|
||||||
|
// Per kandang: hanya ambil expense yang specific ke kandang tersebut
|
||||||
|
// SKIP expense level farm (yang punya multiple project flocks di JSON array)
|
||||||
|
// IMPORTANT: Untuk kandang_id, pastikan kandang tersebut belong to project_flock_kandang ini
|
||||||
|
db = db.Where(`(
|
||||||
|
expense_nonstocks.project_flock_kandang_id = ? OR
|
||||||
|
(expense_nonstocks.kandang_id = (SELECT kandang_id FROM project_flock_kandangs WHERE id = ?) AND
|
||||||
|
expense_nonstocks.project_flock_kandang_id IS NULL)
|
||||||
|
)`, *projectFlockKandangID, *projectFlockKandangID)
|
||||||
|
} else {
|
||||||
|
// All kandang: include expense kandang-specific DAN expense level farm
|
||||||
|
db = db.Where(`(
|
||||||
|
project_flock_kandangs.project_flock_id = ? OR
|
||||||
|
kandangs.id IN (SELECT kandang_id FROM project_flock_kandangs WHERE project_flock_id = ?) OR
|
||||||
|
(expenses.project_flock_id IS NOT NULL AND expenses.project_flock_id::jsonb @> ?::jsonb)
|
||||||
|
)`, projectFlockID, projectFlockID, fmt.Sprintf("[%d]", projectFlockID))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := db.Find(&realizations).Error
|
||||||
|
return realizations, err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *ExpenseRealizationRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.ExpenseQuery) ([]entity.ExpenseRealization, int64, error) {
|
func (r *ExpenseRealizationRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, filters *validation.ExpenseQuery) ([]entity.ExpenseRealization, int64, error) {
|
||||||
var realizations []entity.ExpenseRealization
|
var realizations []entity.ExpenseRealization
|
||||||
var total int64
|
var total int64
|
||||||
|
|||||||
Reference in New Issue
Block a user