mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 06:45:43 +00:00
Merge branch 'development' of https://gitlab.com/mbugroup/lti-api into FEAT/BE/report_customer_payment
This commit is contained in:
@@ -82,6 +82,7 @@ func (c *RepportController) GetMarketing(ctx *fiber.Ctx) error {
|
||||
ProductId: int64(ctx.QueryInt("product_id", 0)),
|
||||
WarehouseId: int64(ctx.QueryInt("warehouse_id", 0)),
|
||||
SalesPersonId: int64(ctx.QueryInt("sales_person_id", 0)),
|
||||
MarketingType: ctx.Query("marketing_type", ""),
|
||||
FilterBy: ctx.Query("filter_by", ""),
|
||||
StartDate: ctx.Query("start_date", ""),
|
||||
EndDate: ctx.Query("end_date", ""),
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
type DebtSupplierRowDTO struct {
|
||||
PrNumber string `json:"pr_number"`
|
||||
PoNumber string `json:"po_number"`
|
||||
PrDate string `json:"pr_date"`
|
||||
PoDate string `json:"po_date"`
|
||||
ReceivedDate string `json:"received_date"`
|
||||
Aging int `json:"aging"`
|
||||
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
|
||||
Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse,omitempty"`
|
||||
@@ -21,6 +21,7 @@ type DebtSupplierRowDTO struct {
|
||||
DebtPrice float64 `json:"debt_price"`
|
||||
Status string `json:"status"`
|
||||
TravelNumber string `json:"travel_number"`
|
||||
Balance float64 `json:"balance"`
|
||||
}
|
||||
|
||||
type DebtSupplierTotalDTO struct {
|
||||
@@ -31,7 +32,8 @@ type DebtSupplierTotalDTO struct {
|
||||
}
|
||||
|
||||
type DebtSupplierDTO struct {
|
||||
Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"`
|
||||
Rows []DebtSupplierRowDTO `json:"rows"`
|
||||
Total DebtSupplierTotalDTO `json:"total"`
|
||||
Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"`
|
||||
InitialBalance float64 `json:"initial_balance"`
|
||||
Rows []DebtSupplierRowDTO `json:"rows"`
|
||||
Total DebtSupplierTotalDTO `json:"total"`
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
marketingDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/dto"
|
||||
customerDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/dto"
|
||||
productCategoryDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/product-categories/dto"
|
||||
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
|
||||
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
|
||||
uomDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/dto"
|
||||
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
|
||||
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
@@ -22,7 +26,7 @@ type RepportMarketingItemDTO struct {
|
||||
DoNumber string `json:"do_number"`
|
||||
Sales *userDTO.UserRelationDTO `json:"sales,omitempty"`
|
||||
VehicleNumber string `json:"vehicle_number"`
|
||||
Product *productDTO.ProductRelationDTO `json:"product,omitempty"`
|
||||
Product *ProductRelationDTOFixed `json:"product,omitempty"`
|
||||
MarketingType string `json:"marketing_type"`
|
||||
Qty float64 `json:"qty"`
|
||||
AverageWeightKg float64 `json:"average_weight_kg"`
|
||||
@@ -46,6 +50,12 @@ type RepportMarketingResponseDTO struct {
|
||||
Total *Summary `json:"total,omitempty"`
|
||||
}
|
||||
|
||||
type ProductRelationDTOFixed struct {
|
||||
productDTO.ProductRelationDTO
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
SellingPrice *float64 `json:"selling_price,omitempty"`
|
||||
}
|
||||
|
||||
func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerKg float64, category string) RepportMarketingItemDTO {
|
||||
soDate := time.Time{}
|
||||
agingDays := 0
|
||||
@@ -106,7 +116,7 @@ func ToRepportMarketingItemDTO(mdp entity.MarketingDeliveryProduct, hppPricePerK
|
||||
|
||||
if mdp.MarketingProduct.ProductWarehouse.ProductId != 0 {
|
||||
mapped := productDTO.ToProductRelationDTO(mdp.MarketingProduct.ProductWarehouse.Product)
|
||||
item.Product = &mapped
|
||||
item.Product = newProductRelationDTOFixedPtr(&mapped)
|
||||
}
|
||||
|
||||
return item
|
||||
@@ -139,7 +149,7 @@ func ToRepportMarketingItemDTOsWithHppMap(mdps []entity.MarketingDeliveryProduct
|
||||
}
|
||||
|
||||
func getMarketingType(mdp entity.MarketingDeliveryProduct) string {
|
||||
hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags)
|
||||
hasAyam, hasTelur, hasTrading := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags)
|
||||
|
||||
if hasAyam {
|
||||
return "ayam"
|
||||
@@ -147,12 +157,15 @@ func getMarketingType(mdp entity.MarketingDeliveryProduct) string {
|
||||
if hasTelur {
|
||||
return "telur"
|
||||
}
|
||||
return "trading"
|
||||
if hasTrading {
|
||||
return "trading"
|
||||
}
|
||||
return "trading" // default to trading if no flags found
|
||||
}
|
||||
|
||||
func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur bool) {
|
||||
func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur, hasTrading bool) {
|
||||
if len(flags) == 0 {
|
||||
return false, false
|
||||
return false, false, false
|
||||
}
|
||||
|
||||
for _, flag := range flags {
|
||||
@@ -167,13 +180,18 @@ func checkProductFlags(flags []entity.Flag) (hasAyam, hasTelur bool) {
|
||||
ft == utils.FlagTelurPutih || ft == utils.FlagTelurRetak {
|
||||
hasTelur = true
|
||||
}
|
||||
|
||||
if ft == utils.FlagOVK || ft == utils.FlagObat || ft == utils.FlagVitamin || ft == utils.FlagKimia ||
|
||||
ft == utils.FlagPakan || ft == utils.FlagPreStarter || ft == utils.FlagStarter || ft == utils.FlagFinisher {
|
||||
hasTrading = true
|
||||
}
|
||||
}
|
||||
|
||||
return hasAyam, hasTelur
|
||||
return hasAyam, hasTelur, hasTrading
|
||||
}
|
||||
|
||||
func isProductEligibleForHpp(mdp entity.MarketingDeliveryProduct, category string) bool {
|
||||
hasAyam, hasTelur := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags)
|
||||
hasAyam, hasTelur, _ := checkProductFlags(mdp.MarketingProduct.ProductWarehouse.Product.Flags)
|
||||
|
||||
if utils.ProjectFlockCategory(category) == utils.ProjectFlockCategoryGrowing {
|
||||
return hasAyam
|
||||
@@ -259,3 +277,39 @@ func ToRepportMarketingResponseDTO(mdps []entity.MarketingDeliveryProduct, hppPr
|
||||
Total: total,
|
||||
}
|
||||
}
|
||||
|
||||
func newProductRelationDTOFixedPtr(original *productDTO.ProductRelationDTO) *ProductRelationDTOFixed {
|
||||
if original == nil {
|
||||
return nil
|
||||
}
|
||||
fixed := ProductRelationDTOFixed{
|
||||
ProductRelationDTO: *original,
|
||||
ProductPrice: original.ProductPrice,
|
||||
SellingPrice: original.SellingPrice,
|
||||
}
|
||||
return &fixed
|
||||
}
|
||||
|
||||
func (p ProductRelationDTOFixed) MarshalJSON() ([]byte, error) {
|
||||
type Alias struct {
|
||||
Id uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ProductPrice float64 `json:"product_price"`
|
||||
SellingPrice *float64 `json:"selling_price"`
|
||||
Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"`
|
||||
Flags *[]string `json:"flags,omitempty"`
|
||||
ProductCategory *productCategoryDTO.ProductCategoryRelationDTO `json:"product_category,omitempty"`
|
||||
Suppliers []supplierDTO.SupplierRelationDTO `json:"suppliers"`
|
||||
}
|
||||
|
||||
return json.Marshal(&Alias{
|
||||
Id: p.ProductRelationDTO.Id,
|
||||
Name: p.ProductRelationDTO.Name,
|
||||
ProductPrice: p.ProductPrice,
|
||||
SellingPrice: p.SellingPrice,
|
||||
Uom: p.ProductRelationDTO.Uom,
|
||||
Flags: p.ProductRelationDTO.Flags,
|
||||
ProductCategory: p.ProductRelationDTO.ProductCategory,
|
||||
Suppliers: p.ProductRelationDTO.Suppliers,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ import (
|
||||
type DebtSupplierRepository interface {
|
||||
GetSuppliersWithPurchases(ctx context.Context, offset, limit int, filters *validation.DebtSupplierQuery) ([]entity.Supplier, int64, error)
|
||||
GetPurchasesBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) ([]entity.Purchase, error)
|
||||
GetPaymentsBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) ([]entity.Payment, error)
|
||||
GetPaymentTotalsByReferences(ctx context.Context, supplierIDs []uint, references []string) (map[string]float64, error)
|
||||
GetPurchaseTotalsBeforeDate(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) (map[uint]float64, error)
|
||||
GetPaymentTotalsBeforeDate(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) (map[uint]float64, error)
|
||||
}
|
||||
|
||||
type debtSupplierRepositoryImpl struct {
|
||||
@@ -28,10 +31,10 @@ 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 "pr_date":
|
||||
return "purchases.created_at"
|
||||
case "do_date", "received_date", "":
|
||||
return "purchase_items.received_date"
|
||||
default:
|
||||
@@ -157,6 +160,39 @@ func (r *debtSupplierRepositoryImpl) GetPurchasesBySuppliers(ctx context.Context
|
||||
return purchases, nil
|
||||
}
|
||||
|
||||
func (r *debtSupplierRepositoryImpl) GetPaymentsBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) ([]entity.Payment, error) {
|
||||
if len(supplierIDs) == 0 {
|
||||
return []entity.Payment{}, nil
|
||||
}
|
||||
|
||||
db := r.db.WithContext(ctx).
|
||||
Model(&entity.Payment{}).
|
||||
Where("party_type = ?", string(utils.PaymentPartySupplier)).
|
||||
Where("direction = ?", "OUT").
|
||||
Where("party_id IN ?", supplierIDs)
|
||||
|
||||
if strings.TrimSpace(filters.StartDate) != "" {
|
||||
if dateFrom, err := utils.ParseDateString(filters.StartDate); err == nil {
|
||||
db = db.Where("DATE(payment_date) >= ?", dateFrom)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.TrimSpace(filters.EndDate) != "" {
|
||||
if dateTo, err := utils.ParseDateString(filters.EndDate); err == nil {
|
||||
db = db.Where("DATE(payment_date) <= ?", dateTo)
|
||||
}
|
||||
}
|
||||
|
||||
var payments []entity.Payment
|
||||
if err := db.
|
||||
Order("payment_date ASC, id ASC").
|
||||
Find(&payments).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return payments, nil
|
||||
}
|
||||
|
||||
func (r *debtSupplierRepositoryImpl) getPurchaseIDs(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) ([]uint, error) {
|
||||
dateColumn := resolveDebtSupplierDateColumn(filters.FilterBy)
|
||||
|
||||
@@ -219,3 +255,76 @@ func (r *debtSupplierRepositoryImpl) GetPaymentTotalsByReferences(ctx context.Co
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *debtSupplierRepositoryImpl) GetPurchaseTotalsBeforeDate(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) (map[uint]float64, error) {
|
||||
if len(supplierIDs) == 0 || strings.TrimSpace(filters.StartDate) == "" {
|
||||
return map[uint]float64{}, nil
|
||||
}
|
||||
|
||||
dateFrom, err := utils.ParseDateString(filters.StartDate)
|
||||
if err != nil {
|
||||
return map[uint]float64{}, nil
|
||||
}
|
||||
|
||||
dateColumn := resolveDebtSupplierDateColumn(filters.FilterBy)
|
||||
|
||||
type purchaseTotalRow struct {
|
||||
SupplierID uint `gorm:"column:supplier_id"`
|
||||
Total float64 `gorm:"column:total"`
|
||||
}
|
||||
|
||||
rows := make([]purchaseTotalRow, 0)
|
||||
if err := r.db.WithContext(ctx).
|
||||
Table("purchases").
|
||||
Select("purchases.supplier_id AS supplier_id, SUM(purchase_items.total_price) AS total").
|
||||
Joins("JOIN purchase_items ON purchase_items.purchase_id = purchases.id").
|
||||
Where("purchases.supplier_id IN ?", supplierIDs).
|
||||
Where(fmt.Sprintf("DATE(%s) < ?", dateColumn), dateFrom).
|
||||
Group("purchases.supplier_id").
|
||||
Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]float64, len(rows))
|
||||
for _, row := range rows {
|
||||
result[row.SupplierID] = row.Total
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *debtSupplierRepositoryImpl) GetPaymentTotalsBeforeDate(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) (map[uint]float64, error) {
|
||||
if len(supplierIDs) == 0 || strings.TrimSpace(filters.StartDate) == "" {
|
||||
return map[uint]float64{}, nil
|
||||
}
|
||||
|
||||
dateFrom, err := utils.ParseDateString(filters.StartDate)
|
||||
if err != nil {
|
||||
return map[uint]float64{}, nil
|
||||
}
|
||||
|
||||
type paymentTotalRow struct {
|
||||
SupplierID uint `gorm:"column:supplier_id"`
|
||||
Total float64 `gorm:"column:total"`
|
||||
}
|
||||
|
||||
rows := make([]paymentTotalRow, 0)
|
||||
if err := r.db.WithContext(ctx).
|
||||
Model(&entity.Payment{}).
|
||||
Select("party_id AS supplier_id, SUM(nominal) AS total").
|
||||
Where("party_type = ?", string(utils.PaymentPartySupplier)).
|
||||
Where("direction = ?", "OUT").
|
||||
Where("party_id IN ?", supplierIDs).
|
||||
Where("DATE(payment_date) < ?", dateFrom).
|
||||
Group("party_id").
|
||||
Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]float64, len(rows))
|
||||
for _, row := range rows {
|
||||
result[row.SupplierID] = row.Total
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -643,8 +643,8 @@ 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 == "" {
|
||||
params.FilterBy = "do_date"
|
||||
if params.FilterBy == "" || strings.EqualFold(strings.TrimSpace(params.FilterBy), "do_date") {
|
||||
params.FilterBy = "received_date"
|
||||
}
|
||||
|
||||
if err := s.Validate.Struct(params); err != nil {
|
||||
@@ -676,6 +676,11 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
payments, err := s.DebtSupplierRepo.GetPaymentsBySuppliers(c.Context(), supplierIDs, params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
purchasesBySupplier := make(map[uint][]entity.Purchase, len(supplierIDs))
|
||||
references := make([]string, 0)
|
||||
seenRefs := make(map[string]struct{})
|
||||
@@ -698,6 +703,21 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
paymentsBySupplier := make(map[uint][]entity.Payment, len(supplierIDs))
|
||||
for _, payment := range payments {
|
||||
paymentsBySupplier[payment.PartyId] = append(paymentsBySupplier[payment.PartyId], payment)
|
||||
}
|
||||
|
||||
initialPurchaseTotals, err := s.DebtSupplierRepo.GetPurchaseTotalsBeforeDate(c.Context(), supplierIDs, params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
initialPaymentTotals, err := s.DebtSupplierRepo.GetPaymentTotalsBeforeDate(c.Context(), supplierIDs, params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
location, err := time.LoadLocation("Asia/Jakarta")
|
||||
if err != nil {
|
||||
return nil, 0, fiber.NewError(fiber.StatusInternalServerError, "failed to load timezone configuration")
|
||||
@@ -711,29 +731,81 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu
|
||||
continue
|
||||
}
|
||||
|
||||
initialBalance := initialPaymentTotals[supplierID] - initialPurchaseTotals[supplierID]
|
||||
|
||||
items := purchasesBySupplier[supplierID]
|
||||
rows := make([]dto.DebtSupplierRowDTO, 0, len(items))
|
||||
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)
|
||||
rows = append(rows, row)
|
||||
sortTime := resolveDebtSupplierSortTime(purchase, params.FilterBy, location)
|
||||
combinedRows = append(combinedRows, debtSupplierRowItem{
|
||||
Row: row,
|
||||
SortTime: sortTime,
|
||||
Order: 0,
|
||||
DeltaBalance: -row.TotalPrice,
|
||||
CountTotals: true,
|
||||
})
|
||||
}
|
||||
|
||||
if row.Aging > total.Aging {
|
||||
total.Aging = row.Aging
|
||||
for _, payment := range paymentItems {
|
||||
row := buildDebtSupplierPaymentRow(payment, location)
|
||||
sortTime := payment.PaymentDate.In(location)
|
||||
combinedRows = append(combinedRows, debtSupplierRowItem{
|
||||
Row: row,
|
||||
SortTime: sortTime,
|
||||
Order: 1,
|
||||
DeltaBalance: payment.Nominal,
|
||||
CountTotals: false,
|
||||
})
|
||||
}
|
||||
|
||||
sort.SliceStable(combinedRows, func(i, j int) bool {
|
||||
if combinedRows[i].SortTime.Equal(combinedRows[j].SortTime) {
|
||||
return combinedRows[i].Order < combinedRows[j].Order
|
||||
}
|
||||
return combinedRows[i].SortTime.Before(combinedRows[j].SortTime)
|
||||
})
|
||||
|
||||
balance := initialBalance
|
||||
for i := range combinedRows {
|
||||
balance += combinedRows[i].DeltaBalance
|
||||
combinedRows[i].Row.Balance = balance
|
||||
|
||||
if combinedRows[i].CountTotals {
|
||||
row := combinedRows[i].Row
|
||||
if row.Aging > total.Aging {
|
||||
total.Aging = row.Aging
|
||||
}
|
||||
total.TotalPrice += row.TotalPrice
|
||||
total.PaymentPrice += row.PaymentPrice
|
||||
total.DebtPrice += row.DebtPrice
|
||||
} else {
|
||||
combinedRows[i].Row.DebtPrice = balance
|
||||
}
|
||||
total.TotalPrice += row.TotalPrice
|
||||
total.PaymentPrice += row.PaymentPrice
|
||||
total.DebtPrice += row.DebtPrice
|
||||
}
|
||||
|
||||
sortDesc := strings.EqualFold(params.SortOrder, "desc")
|
||||
sort.SliceStable(rows, func(i, j int) bool {
|
||||
if sortDesc {
|
||||
return rows[i].PrDate > rows[j].PrDate
|
||||
if sortDesc {
|
||||
for i := len(combinedRows) - 1; i >= 0; i-- {
|
||||
rows = append(rows, combinedRows[i].Row)
|
||||
}
|
||||
return rows[i].PrDate < rows[j].PrDate
|
||||
})
|
||||
} else {
|
||||
for i := range combinedRows {
|
||||
rows = append(rows, combinedRows[i].Row)
|
||||
}
|
||||
}
|
||||
|
||||
var supplierDTORef *supplierDTO.SupplierRelationDTO
|
||||
if supplier.Id != 0 {
|
||||
@@ -742,9 +814,10 @@ func (s *repportService) GetDebtSupplier(c *fiber.Ctx, params *validation.DebtSu
|
||||
}
|
||||
|
||||
result = append(result, dto.DebtSupplierDTO{
|
||||
Supplier: supplierDTORef,
|
||||
Rows: rows,
|
||||
Total: total,
|
||||
Supplier: supplierDTORef,
|
||||
InitialBalance: initialBalance,
|
||||
Rows: rows,
|
||||
Total: total,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -770,6 +843,7 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo
|
||||
|
||||
totalPrice := 0.0
|
||||
travelNumber := "-"
|
||||
receivedDate := ""
|
||||
var area *areaDTO.AreaRelationDTO
|
||||
var warehouse *warehouseDTO.WarehouseRelationDTO
|
||||
|
||||
@@ -788,8 +862,19 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo
|
||||
}
|
||||
}
|
||||
|
||||
earliestReceived := time.Time{}
|
||||
for _, item := range purchase.Items {
|
||||
totalPrice += item.TotalPrice
|
||||
if item.ReceivedDate == nil || item.ReceivedDate.IsZero() {
|
||||
continue
|
||||
}
|
||||
received := item.ReceivedDate.In(loc)
|
||||
if earliestReceived.IsZero() || received.Before(earliestReceived) {
|
||||
earliestReceived = received
|
||||
}
|
||||
}
|
||||
if !earliestReceived.IsZero() {
|
||||
receivedDate = earliestReceived.Format("2006-01-02")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,8 +906,8 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo
|
||||
return dto.DebtSupplierRowDTO{
|
||||
PrNumber: prNumber,
|
||||
PoNumber: poNumber,
|
||||
PrDate: prDate.Format("2006-01-02"),
|
||||
PoDate: poDate,
|
||||
ReceivedDate: receivedDate,
|
||||
Aging: aging,
|
||||
Area: area,
|
||||
Warehouse: warehouse,
|
||||
@@ -836,6 +921,62 @@ func buildDebtSupplierRow(purchase entity.Purchase, paymentTotals map[string]flo
|
||||
}
|
||||
}
|
||||
|
||||
func buildDebtSupplierPaymentRow(payment entity.Payment, loc *time.Location) dto.DebtSupplierRowDTO {
|
||||
referenceNumber := ""
|
||||
if payment.ReferenceNumber != nil {
|
||||
referenceNumber = *payment.ReferenceNumber
|
||||
}
|
||||
|
||||
prNumber := payment.PaymentCode
|
||||
if strings.TrimSpace(prNumber) == "" {
|
||||
prNumber = referenceNumber
|
||||
}
|
||||
|
||||
return dto.DebtSupplierRowDTO{
|
||||
PrNumber: prNumber,
|
||||
PoNumber: referenceNumber,
|
||||
PoDate: "-",
|
||||
ReceivedDate: payment.PaymentDate.In(loc).Format("2006-01-02"),
|
||||
Aging: 0,
|
||||
Area: nil,
|
||||
Warehouse: nil,
|
||||
DueDate: "-",
|
||||
DueStatus: "-",
|
||||
TotalPrice: 0,
|
||||
PaymentPrice: payment.Nominal,
|
||||
DebtPrice: 0,
|
||||
Status: "Pembayaran",
|
||||
TravelNumber: "-",
|
||||
}
|
||||
}
|
||||
|
||||
func resolveDebtSupplierSortTime(purchase entity.Purchase, filterBy string, loc *time.Location) time.Time {
|
||||
switch strings.ToLower(strings.TrimSpace(filterBy)) {
|
||||
case "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
|
||||
}
|
||||
}
|
||||
if !earliest.IsZero() {
|
||||
return earliest
|
||||
}
|
||||
}
|
||||
|
||||
return purchase.CreatedAt.In(loc)
|
||||
}
|
||||
|
||||
func (s *repportService) GetHppPerKandang(ctx *fiber.Ctx) (*dto.HppPerKandangResponseData, *dto.HppPerKandangMetaDTO, error) {
|
||||
params, filters, err := s.parseHppPerKandangQuery(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -23,6 +23,7 @@ type MarketingQuery struct {
|
||||
ProductId int64 `query:"product_id" validate:"omitempty"`
|
||||
WarehouseId int64 `query:"warehouse_id" validate:"omitempty"`
|
||||
SalesPersonId int64 `query:"sales_person_id" validate:"omitempty"`
|
||||
MarketingType string `query:"marketing_type" validate:"omitempty,oneof=ayam telur trading"`
|
||||
FilterBy string `query:"filter_by" validate:"omitempty,oneof=so_date realization_date"`
|
||||
StartDate string `query:"start_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
EndDate string `query:"end_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
@@ -49,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=do_date po_date pr_date"`
|
||||
FilterBy string `query:"filter_by" validate:"omitempty,oneof=received_date po_date pr_date do_date"`
|
||||
SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user