diff --git a/.gitignore b/.gitignore index 4a814ebe..24887418 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ Makefile docker-compose.local.yml docker-compose.yaml Dockerfile +Dockerfile.local .gitlab-ci.yml # Go build cache .gocache/ diff --git a/internal/modules/repports/repositories/debt_supplier.repository.go b/internal/modules/repports/repositories/debt_supplier.repository.go index 3d415606..e8f548d6 100644 --- a/internal/modules/repports/repositories/debt_supplier.repository.go +++ b/internal/modules/repports/repositories/debt_supplier.repository.go @@ -31,11 +31,9 @@ func NewDebtSupplierRepository(db *gorm.DB) DebtSupplierRepository { func resolveDebtSupplierDateColumn(filterBy string) string { switch strings.ToLower(strings.TrimSpace(filterBy)) { - case "receive_date": - return "purchases.receive_date" case "po_date": return "purchases.po_date" - case "do_date", "received_date", "": + case "received_date", "": return "purchase_items.received_date" default: return "purchase_items.received_date" @@ -130,7 +128,7 @@ func (r *debtSupplierRepositoryImpl) GetPurchasesBySuppliers(ctx context.Context Preload("Warehouse.Area"). Order("purchase_items.id ASC") - if strings.EqualFold(strings.TrimSpace(filters.FilterBy), "do_date") || strings.EqualFold(strings.TrimSpace(filters.FilterBy), "received_date") || strings.TrimSpace(filters.FilterBy) == "" { + if strings.EqualFold(strings.TrimSpace(filters.FilterBy), "received_date") || strings.TrimSpace(filters.FilterBy) == "" { if filters.StartDate != "" { if dateFrom, err := utils.ParseDateString(filters.StartDate); err == nil { db = db.Where("DATE(purchase_items.received_date) >= ?", dateFrom) diff --git a/internal/modules/repports/services/repport.service.go b/internal/modules/repports/services/repport.service.go index 5f3cbbad..c4883b72 100644 --- a/internal/modules/repports/services/repport.service.go +++ b/internal/modules/repports/services/repport.service.go @@ -642,7 +642,7 @@ func (s *repportService) GetPurchaseSupplier(c *fiber.Ctx, params *validation.Pu } func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSupplierQuery) ([]dto.DebtSupplierDTO, int64, error) { - if params.FilterBy == "" || strings.EqualFold(strings.TrimSpace(params.FilterBy), "do_date") { + if params.FilterBy == "" { params.FilterBy = "received_date" } @@ -681,25 +681,8 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu } purchasesBySupplier := make(map[uint][]entity.Purchase, len(supplierIDs)) - references := make([]string, 0) - seenRefs := make(map[string]struct{}) for _, purchase := range purchases { - supplierID := purchase.SupplierId - purchasesBySupplier[supplierID] = append(purchasesBySupplier[supplierID], purchase) - - reference := purchase.PrNumber - if purchase.PoNumber != nil && strings.TrimSpace(*purchase.PoNumber) != "" { - reference = *purchase.PoNumber - } - if _, exists := seenRefs[reference]; !exists { - seenRefs[reference] = struct{}{} - references = append(references, reference) - } - } - - paymentTotals, err := s.DebtSupplierRepo.GetPaymentTotalsByReferences(c.Context(), supplierIDs, references) - if err != nil { - return nil, 0, err + purchasesBySupplier[purchase.SupplierId] = append(purchasesBySupplier[purchase.SupplierId], purchase) } paymentsBySupplier := make(map[uint][]entity.Payment, len(supplierIDs)) @@ -724,6 +707,14 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu now := time.Now().In(location) result := make([]dto.DebtSupplierDTO, 0, len(supplierIDs)) + type debtSupplierRowItem struct { + Row dto.DebtSupplierRowDTO + SortTime time.Time + Order int + DeltaBalance float64 + CountTotals bool + } + for _, supplierID := range supplierIDs { supplier, exists := supplierMap[supplierID] if !exists { @@ -731,23 +722,13 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu } initialBalance := initialPaymentTotals[supplierID] - initialPurchaseTotals[supplierID] - items := purchasesBySupplier[supplierID] paymentItems := paymentsBySupplier[supplierID] - rows := make([]dto.DebtSupplierRowDTO, 0, len(items)+len(paymentItems)) total := dto.DebtSupplierTotalDTO{} - type debtSupplierRowItem struct { - Row dto.DebtSupplierRowDTO - SortTime time.Time - Order int - DeltaBalance float64 - CountTotals bool - } - combinedRows := make([]debtSupplierRowItem, 0, len(items)+len(paymentItems)) for _, purchase := range items { - row := buildDebtSupplierRow(purchase, paymentTotals, now, location) + row := buildDebtSupplierRow(purchase, now, location) sortTime := resolveDebtSupplierSortTime(purchase, params.FilterBy, location) combinedRows = append(combinedRows, debtSupplierRowItem{ Row: row, @@ -780,6 +761,7 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu balance := initialBalance for i := range combinedRows { balance += combinedRows[i].DeltaBalance + combinedRows[i].Row.DebtPrice = balance combinedRows[i].Row.Balance = balance if combinedRows[i].CountTotals { @@ -788,13 +770,13 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu total.Aging = row.Aging } total.TotalPrice += row.TotalPrice - total.PaymentPrice += row.PaymentPrice - total.DebtPrice += row.DebtPrice } else { - combinedRows[i].Row.DebtPrice = balance + total.PaymentPrice += combinedRows[i].Row.PaymentPrice } } + total.DebtPrice = balance + rows := make([]dto.DebtSupplierRowDTO, 0, len(combinedRows)) sortDesc := strings.EqualFold(params.SortOrder, "desc") if sortDesc { for i := len(combinedRows) - 1; i >= 0; i-- { @@ -823,18 +805,13 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu return result, totalSuppliers, nil } -func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]float64, now time.Time, loc *time.Location) dto.DebtSupplierRowDTO { +func buildDebtSupplierRow(purchase entity.Purchase, now time.Time, loc *time.Location) dto.DebtSupplierRowDTO { prNumber := purchase.PrNumber poNumber := "" if purchase.PoNumber != nil { poNumber = *purchase.PoNumber } - reference := prNumber - if strings.TrimSpace(poNumber) != "" { - reference = poNumber - } - prDate := purchase.CreatedAt.In(loc) startDate := time.Date(prDate.Year(), prDate.Month(), prDate.Day(), 0, 0, 0, 0, loc) endDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc) @@ -877,9 +854,6 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo } } - paymentPrice := paymentTotals[reference] - debtPrice := paymentPrice - totalPrice - dueDate := "" dueStatus := "-" if purchase.DueDate != nil && !purchase.DueDate.IsZero() { @@ -893,10 +867,6 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo } status := "Belum Lunas" - if debtPrice >= 0 { - status = "Lunas" - } - poDate := "" if purchase.PoDate != nil && !purchase.PoDate.IsZero() { poDate = purchase.PoDate.In(loc).Format("2006-01-02") @@ -913,10 +883,11 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo DueDate: dueDate, DueStatus: dueStatus, TotalPrice: totalPrice, - PaymentPrice: paymentPrice, - DebtPrice: debtPrice, + PaymentPrice: 0, + DebtPrice: 0, Status: status, TravelNumber: travelNumber, + Balance: 0, } } @@ -946,32 +917,30 @@ func buildDebtSupplierPaymentRow(payment entity.Payment, loc *time.Location) dto DebtPrice: 0, Status: "Pembayaran", TravelNumber: "-", + Balance: 0, } } func resolveDebtSupplierSortTime(purchase entity.Purchase, filterBy string, loc *time.Location) time.Time { - switch strings.ToLower(strings.TrimSpace(filterBy)) { - case "po_date": + if strings.EqualFold(strings.TrimSpace(filterBy), "po_date") { if purchase.PoDate != nil && !purchase.PoDate.IsZero() { return purchase.PoDate.In(loc) } - case "pr_date": - return purchase.CreatedAt.In(loc) - default: - earliest := time.Time{} - for _, item := range purchase.Items { - if item.ReceivedDate == nil || item.ReceivedDate.IsZero() { - continue - } - received := item.ReceivedDate.In(loc) - if earliest.IsZero() || received.Before(earliest) { - earliest = received - } + } + + earliest := time.Time{} + for _, item := range purchase.Items { + if item.ReceivedDate == nil || item.ReceivedDate.IsZero() { + continue } - if !earliest.IsZero() { - return earliest + received := item.ReceivedDate.In(loc) + if earliest.IsZero() || received.Before(earliest) { + earliest = received } } + if !earliest.IsZero() { + return earliest + } return purchase.CreatedAt.In(loc) } diff --git a/internal/modules/repports/validations/repport.validation.go b/internal/modules/repports/validations/repport.validation.go index 5dde8f51..6d50f3e6 100644 --- a/internal/modules/repports/validations/repport.validation.go +++ b/internal/modules/repports/validations/repport.validation.go @@ -50,7 +50,7 @@ type DebtSupplierQuery struct { SupplierIDs []int64 `query:"-" validate:"omitempty,dive,gt=0"` StartDate string `query:"start_date" validate:"omitempty,datetime=2006-01-02"` EndDate string `query:"end_date" validate:"omitempty,datetime=2006-01-02"` - FilterBy string `query:"filter_by" validate:"omitempty,oneof=received_date po_date pr_date do_date"` + FilterBy string `query:"filter_by" validate:"omitempty,oneof=received_date po_date"` SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"` }