mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Feat(BE-339): make a report for purchasing supplier
This commit is contained in:
@@ -97,3 +97,53 @@ func (c *RepportController) GetMarketing(ctx *fiber.Ctx) error {
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *RepportController) GetPurchaseSupplier(ctx *fiber.Ctx) error {
|
||||
query := &validation.PurchaseSupplierQuery{
|
||||
Page: ctx.QueryInt("page", 1),
|
||||
Limit: ctx.QueryInt("limit", 10),
|
||||
AreaId: int64(ctx.QueryInt("area_id", 0)),
|
||||
SupplierId: int64(ctx.QueryInt("supplier_id", 0)),
|
||||
ProductId: int64(ctx.QueryInt("product_id", 0)),
|
||||
ProductCategoryId: int64(ctx.QueryInt("product_category_id", 0)),
|
||||
DateFrom: ctx.Query("date_from", ""),
|
||||
DateTo: ctx.Query("date_to", ""),
|
||||
SortBy: ctx.Query("sort_by", ""),
|
||||
FilterBy: ctx.Query("filter_by", ""),
|
||||
}
|
||||
|
||||
if query.Page < 1 || query.Limit < 1 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
|
||||
}
|
||||
|
||||
result, totalResults, err := c.RepportService.GetPurchaseSupplier(ctx, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filters := map[string]interface{}{
|
||||
"area_id": query.AreaId,
|
||||
"supplier_id": query.SupplierId,
|
||||
"product_id": query.ProductId,
|
||||
"product_category_id": query.ProductCategoryId,
|
||||
"date_from": query.DateFrom,
|
||||
"date_to": query.DateTo,
|
||||
"sort_by": query.SortBy,
|
||||
"filter_by": query.FilterBy,
|
||||
}
|
||||
|
||||
return ctx.Status(fiber.StatusOK).
|
||||
JSON(response.SuccessWithPaginate[dto.PurchaseSupplierDTO]{
|
||||
Code: fiber.StatusOK,
|
||||
Status: "success",
|
||||
Message: "Get supplier purchase recap successfully",
|
||||
Meta: response.Meta{
|
||||
Page: query.Page,
|
||||
Limit: query.Limit,
|
||||
TotalPages: int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
|
||||
TotalResults: totalResults,
|
||||
Filters: filters,
|
||||
},
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
|
||||
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
|
||||
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
|
||||
)
|
||||
|
||||
type PurchaseSupplierRowDTO struct {
|
||||
ReceiveDate string `json:"receive_date"`
|
||||
PoDate string `json:"po_date"`
|
||||
PoNumber string `json:"po_number"`
|
||||
Product *productDTO.ProductRelationDTO `json:"product,omitempty"`
|
||||
Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse,omitempty"`
|
||||
Qty float64 `json:"qty"`
|
||||
UnitPrice float64 `json:"unit_price"`
|
||||
PurchaseValue float64 `json:"purchase_value"`
|
||||
TransportUnitPrice float64 `json:"transport_unit_price"`
|
||||
TransportValue float64 `json:"transport_value"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
Expedition string `json:"expedition"`
|
||||
DeliveryNumber string `json:"delivery_number"`
|
||||
}
|
||||
|
||||
type PurchaseSupplierSummaryDTO struct {
|
||||
TotalQty float64 `json:"total_qty"`
|
||||
TotalPurchaseValue float64 `json:"total_purchase_value"`
|
||||
TotalTransportValue float64 `json:"total_transport_value"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
}
|
||||
|
||||
type PurchaseSupplierDTO struct {
|
||||
Supplier *supplierDTO.SupplierRelationDTO `json:"supplier"`
|
||||
Rows []PurchaseSupplierRowDTO `json:"rows"`
|
||||
Summary PurchaseSupplierSummaryDTO `json:"summary"`
|
||||
}
|
||||
|
||||
func formatDatePtr(t *time.Time) string {
|
||||
if t == nil || t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return t.Format("02-Jan-2006")
|
||||
}
|
||||
|
||||
func ToPurchaseSupplierRowDTO(item *entity.PurchaseItem) PurchaseSupplierRowDTO {
|
||||
row := PurchaseSupplierRowDTO{
|
||||
ReceiveDate: formatDatePtr(item.ReceivedDate),
|
||||
Qty: item.TotalQty,
|
||||
UnitPrice: item.Price,
|
||||
}
|
||||
|
||||
if item.Purchase != nil {
|
||||
row.PoDate = formatDatePtr(item.Purchase.PoDate)
|
||||
if item.Purchase.PoNumber != nil {
|
||||
row.PoNumber = *item.Purchase.PoNumber
|
||||
}
|
||||
}
|
||||
|
||||
if item.Product != nil && item.Product.Id != 0 {
|
||||
product := productDTO.ToProductRelationDTO(*item.Product)
|
||||
row.Product = &product
|
||||
}
|
||||
|
||||
if item.Warehouse != nil && item.Warehouse.Id != 0 {
|
||||
warehouse := warehouseDTO.ToWarehouseRelationDTO(*item.Warehouse)
|
||||
row.Warehouse = &warehouse
|
||||
}
|
||||
|
||||
qty := row.Qty
|
||||
if qty < 0 {
|
||||
qty = 0
|
||||
}
|
||||
|
||||
row.PurchaseValue = row.UnitPrice * qty
|
||||
|
||||
var transportUnit float64
|
||||
var expeditionName string
|
||||
|
||||
if item.ExpenseNonstock != nil {
|
||||
transportUnit = item.ExpenseNonstock.Price
|
||||
|
||||
if item.ExpenseNonstock.Expense != nil &&
|
||||
item.ExpenseNonstock.Expense.Supplier != nil &&
|
||||
item.ExpenseNonstock.Expense.Supplier.Id != 0 {
|
||||
expSupplier := item.ExpenseNonstock.Expense.Supplier
|
||||
expeditionName = expSupplier.Name
|
||||
}
|
||||
}
|
||||
|
||||
row.TransportUnitPrice = transportUnit
|
||||
row.TransportValue = transportUnit * qty
|
||||
row.TotalAmount = row.PurchaseValue + row.TransportValue
|
||||
|
||||
if expeditionName == "" {
|
||||
row.Expedition = "-"
|
||||
} else {
|
||||
row.Expedition = expeditionName
|
||||
}
|
||||
|
||||
if item.TravelNumber != nil && *item.TravelNumber != "" {
|
||||
row.DeliveryNumber = *item.TravelNumber
|
||||
} else {
|
||||
row.DeliveryNumber = "-"
|
||||
}
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
func ToPurchaseSupplierDTO(supplier entity.Supplier, items []entity.PurchaseItem) PurchaseSupplierDTO {
|
||||
var supplierDTORef *supplierDTO.SupplierRelationDTO
|
||||
if supplier.Id != 0 {
|
||||
mapped := supplierDTO.ToSupplierRelationDTO(supplier)
|
||||
supplierDTORef = &mapped
|
||||
}
|
||||
|
||||
rows := make([]PurchaseSupplierRowDTO, 0, len(items))
|
||||
summary := PurchaseSupplierSummaryDTO{}
|
||||
|
||||
for i := range items {
|
||||
row := ToPurchaseSupplierRowDTO(&items[i])
|
||||
rows = append(rows, row)
|
||||
|
||||
summary.TotalQty += row.Qty
|
||||
summary.TotalPurchaseValue += row.PurchaseValue
|
||||
summary.TotalTransportValue += row.TransportValue
|
||||
summary.TotalAmount += row.TotalAmount
|
||||
}
|
||||
|
||||
return PurchaseSupplierDTO{
|
||||
Supplier: supplierDTORef,
|
||||
Rows: rows,
|
||||
Summary: summary,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
approvalService "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
repportRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/repositories"
|
||||
sRepport "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/services"
|
||||
|
||||
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||
@@ -20,9 +21,10 @@ func (RepportModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *
|
||||
expenseRealizationRepository := expenseRepo.NewExpenseRealizationRepository(db)
|
||||
marketingDeliveryProductRepository := marketingRepo.NewMarketingDeliveryProductRepository(db)
|
||||
approvalRepository := commonRepo.NewApprovalRepository(db)
|
||||
purchaseSupplierRepository := repportRepo.NewPurchaseSupplierRepository(db)
|
||||
|
||||
approvalSvc := approvalService.NewApprovalService(approvalRepository)
|
||||
repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, approvalSvc)
|
||||
repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, approvalSvc, purchaseSupplierRepository)
|
||||
|
||||
RepportRoutes(router, repportService)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PurchaseSupplierRepository interface {
|
||||
GetSuppliersWithPurchases(ctx context.Context, offset, limit int, filters *validation.PurchaseSupplierQuery) ([]entity.Supplier, int64, error)
|
||||
GetItemsBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.PurchaseSupplierQuery) ([]entity.PurchaseItem, error)
|
||||
}
|
||||
|
||||
type purchaseSupplierRepositoryImpl struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewPurchaseSupplierRepository(db *gorm.DB) PurchaseSupplierRepository {
|
||||
return &purchaseSupplierRepositoryImpl{db: db}
|
||||
}
|
||||
|
||||
func (r *purchaseSupplierRepositoryImpl) baseSupplierQuery(ctx context.Context, filters *validation.PurchaseSupplierQuery) *gorm.DB {
|
||||
// Tentukan kolom tanggal yang akan dipakai untuk filter
|
||||
dateColumn := "purchase_items.received_date"
|
||||
switch strings.ToLower(strings.TrimSpace(filters.FilterBy)) {
|
||||
case "po_date":
|
||||
dateColumn = "purchases.po_date"
|
||||
case "receive_date", "":
|
||||
dateColumn = "purchase_items.received_date"
|
||||
}
|
||||
|
||||
db := r.db.WithContext(ctx).
|
||||
Model(&entity.Supplier{}).
|
||||
Joins("JOIN purchases ON purchases.supplier_id = suppliers.id").
|
||||
Joins("JOIN purchase_items ON purchase_items.purchase_id = purchases.id")
|
||||
|
||||
if filters.SupplierId > 0 {
|
||||
db = db.Where("suppliers.id = ?", filters.SupplierId)
|
||||
}
|
||||
|
||||
if filters.ProductId > 0 {
|
||||
db = db.Where("purchase_items.product_id = ?", filters.ProductId)
|
||||
}
|
||||
|
||||
if filters.ProductCategoryId > 0 {
|
||||
db = db.
|
||||
Joins("JOIN products ON products.id = purchase_items.product_id").
|
||||
Where("products.product_category_id = ?", filters.ProductCategoryId)
|
||||
}
|
||||
|
||||
if filters.AreaId > 0 {
|
||||
db = db.
|
||||
Joins("JOIN warehouses ON warehouses.id = purchase_items.warehouse_id").
|
||||
Where("warehouses.area_id = ?", filters.AreaId)
|
||||
}
|
||||
|
||||
if filters.DateFrom != "" {
|
||||
if dateFrom, err := utils.ParseDateString(filters.DateFrom); err == nil {
|
||||
db = db.Where(fmt.Sprintf("DATE(%s) >= ?", dateColumn), dateFrom)
|
||||
}
|
||||
}
|
||||
|
||||
if filters.DateTo != "" {
|
||||
if dateTo, err := utils.ParseDateString(filters.DateTo); err == nil {
|
||||
db = db.Where(fmt.Sprintf("DATE(%s) <= ?", dateColumn), dateTo)
|
||||
}
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func (r *purchaseSupplierRepositoryImpl) GetSuppliersWithPurchases(ctx context.Context, offset, limit int, filters *validation.PurchaseSupplierQuery) ([]entity.Supplier, int64, error) {
|
||||
query := r.baseSupplierQuery(ctx, filters)
|
||||
|
||||
var totalSuppliers int64
|
||||
if err := query.
|
||||
Distinct("suppliers.id").
|
||||
Count(&totalSuppliers).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if totalSuppliers == 0 {
|
||||
return []entity.Supplier{}, 0, nil
|
||||
}
|
||||
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
|
||||
var supplierIDs []uint
|
||||
if err := query.
|
||||
Select("suppliers.id").
|
||||
Order("suppliers.id ASC").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
Pluck("suppliers.id", &supplierIDs).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if len(supplierIDs) == 0 {
|
||||
return []entity.Supplier{}, totalSuppliers, nil
|
||||
}
|
||||
|
||||
var suppliers []entity.Supplier
|
||||
if err := r.db.WithContext(ctx).
|
||||
Where("id IN ?", supplierIDs).
|
||||
Find(&suppliers).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return suppliers, totalSuppliers, nil
|
||||
}
|
||||
|
||||
func (r *purchaseSupplierRepositoryImpl) GetItemsBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.PurchaseSupplierQuery) ([]entity.PurchaseItem, error) {
|
||||
if len(supplierIDs) == 0 {
|
||||
return []entity.PurchaseItem{}, nil
|
||||
}
|
||||
|
||||
// Tentukan kolom tanggal yang akan dipakai untuk filter & sort
|
||||
dateColumn := "purchase_items.received_date"
|
||||
switch strings.ToLower(strings.TrimSpace(filters.FilterBy)) {
|
||||
case "po_date":
|
||||
dateColumn = "purchases.po_date"
|
||||
case "receive_date", "":
|
||||
dateColumn = "purchase_items.received_date"
|
||||
}
|
||||
|
||||
orderDirection := "ASC"
|
||||
switch strings.ToUpper(strings.TrimSpace(filters.SortBy)) {
|
||||
case "DESC":
|
||||
orderDirection = "DESC"
|
||||
case "ASC", "":
|
||||
orderDirection = "ASC"
|
||||
}
|
||||
|
||||
db := r.db.WithContext(ctx).
|
||||
Model(&entity.PurchaseItem{}).
|
||||
Preload("Purchase").
|
||||
Preload("Purchase.Supplier").
|
||||
Preload("Product").
|
||||
Preload("Product.ProductCategory").
|
||||
Preload("Warehouse").
|
||||
Preload("Warehouse.Area").
|
||||
Preload("Warehouse.Location").
|
||||
Preload("Warehouse.Kandang").
|
||||
Preload("ExpenseNonstock").
|
||||
Preload("ExpenseNonstock.Expense").
|
||||
Preload("ExpenseNonstock.Expense.Supplier").
|
||||
Joins("JOIN purchases ON purchases.id = purchase_items.purchase_id").
|
||||
Where("purchases.supplier_id IN ?", supplierIDs)
|
||||
|
||||
if filters.ProductId > 0 {
|
||||
db = db.Where("purchase_items.product_id = ?", filters.ProductId)
|
||||
}
|
||||
|
||||
if filters.ProductCategoryId > 0 {
|
||||
db = db.
|
||||
Joins("JOIN products ON products.id = purchase_items.product_id").
|
||||
Where("products.product_category_id = ?", filters.ProductCategoryId)
|
||||
}
|
||||
|
||||
if filters.AreaId > 0 {
|
||||
db = db.
|
||||
Joins("JOIN warehouses ON warehouses.id = purchase_items.warehouse_id").
|
||||
Where("warehouses.area_id = ?", filters.AreaId)
|
||||
}
|
||||
|
||||
if filters.DateFrom != "" {
|
||||
if dateFrom, err := utils.ParseDateString(filters.DateFrom); err == nil {
|
||||
db = db.Where(fmt.Sprintf("DATE(%s) >= ?", dateColumn), dateFrom)
|
||||
}
|
||||
}
|
||||
|
||||
if filters.DateTo != "" {
|
||||
if dateTo, err := utils.ParseDateString(filters.DateTo); err == nil {
|
||||
db = db.Where(fmt.Sprintf("DATE(%s) <= ?", dateColumn), dateTo)
|
||||
}
|
||||
}
|
||||
|
||||
// Urutkan berdasarkan kolom tanggal yang dipilih dan arah sort
|
||||
db = db.Order(fmt.Sprintf("%s %s", dateColumn, orderDirection)).
|
||||
Order("purchase_items.id ASC")
|
||||
|
||||
var items []entity.PurchaseItem
|
||||
if err := db.Find(&items).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
@@ -14,4 +14,5 @@ func RepportRoutes(v1 fiber.Router, s repport.RepportService) {
|
||||
|
||||
route.Get("/expense", ctrl.GetExpense)
|
||||
route.Get("/marketing", ctrl.GetMarketing)
|
||||
route.Get("/purchase-supplier", ctrl.GetPurchaseSupplier)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/repports/dto"
|
||||
repportRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/repositories"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
|
||||
@@ -10,6 +11,8 @@ import (
|
||||
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||
marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -19,6 +22,7 @@ import (
|
||||
type RepportService interface {
|
||||
GetExpense(ctx *fiber.Ctx, params *validation.ExpenseQuery) ([]dto.RepportExpenseListDTO, int64, error)
|
||||
GetMarketing(ctx *fiber.Ctx, params *validation.MarketingQuery) ([]dto.RepportMarketingListDTO, int64, error)
|
||||
GetPurchaseSupplier(ctx *fiber.Ctx, params *validation.PurchaseSupplierQuery) ([]dto.PurchaseSupplierDTO, int64, error)
|
||||
}
|
||||
|
||||
type repportService struct {
|
||||
@@ -27,15 +31,23 @@ type repportService struct {
|
||||
ExpenseRealizationRepo expenseRepo.ExpenseRealizationRepository
|
||||
MarketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository
|
||||
ApprovalSvc approvalService.ApprovalService
|
||||
PurchaseSupplierRepo repportRepo.PurchaseSupplierRepository
|
||||
}
|
||||
|
||||
func NewRepportService(validate *validator.Validate, expenseRealizationRepo expenseRepo.ExpenseRealizationRepository, marketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository, approvalSvc approvalService.ApprovalService) RepportService {
|
||||
func NewRepportService(
|
||||
validate *validator.Validate,
|
||||
expenseRealizationRepo expenseRepo.ExpenseRealizationRepository,
|
||||
marketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository,
|
||||
approvalSvc approvalService.ApprovalService,
|
||||
purchaseSupplierRepo repportRepo.PurchaseSupplierRepository,
|
||||
) RepportService {
|
||||
return &repportService{
|
||||
Log: utils.Log,
|
||||
Validate: validate,
|
||||
ExpenseRealizationRepo: expenseRealizationRepo,
|
||||
MarketingDeliveryRepo: marketingDeliveryRepo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
PurchaseSupplierRepo: purchaseSupplierRepo,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,3 +125,58 @@ func (s *repportService) GetMarketing(c *fiber.Ctx, params *validation.Marketing
|
||||
|
||||
return dto.ToRepportMarketingListDTOs(deliveryProducts), total, nil
|
||||
}
|
||||
|
||||
func (s *repportService) GetPurchaseSupplier(c *fiber.Ctx, params *validation.PurchaseSupplierQuery) ([]dto.PurchaseSupplierDTO, int64, error) {
|
||||
if err := s.Validate.Struct(params); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
offset := (params.Page - 1) * params.Limit
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
|
||||
suppliers, totalSuppliers, err := s.PurchaseSupplierRepo.GetSuppliersWithPurchases(c.Context(), offset, params.Limit, params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if totalSuppliers == 0 || len(suppliers) == 0 {
|
||||
return []dto.PurchaseSupplierDTO{}, totalSuppliers, nil
|
||||
}
|
||||
|
||||
supplierMap := make(map[uint]entity.Supplier, len(suppliers))
|
||||
supplierIDs := make([]uint, 0, len(suppliers))
|
||||
for _, supplier := range suppliers {
|
||||
supplierMap[supplier.Id] = supplier
|
||||
supplierIDs = append(supplierIDs, supplier.Id)
|
||||
}
|
||||
|
||||
items, err := s.PurchaseSupplierRepo.GetItemsBySuppliers(c.Context(), supplierIDs, params)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
itemsBySupplier := make(map[uint][]entity.PurchaseItem)
|
||||
for _, item := range items {
|
||||
if item.Purchase == nil {
|
||||
continue
|
||||
}
|
||||
supplierID := item.Purchase.SupplierId
|
||||
itemsBySupplier[supplierID] = append(itemsBySupplier[supplierID], item)
|
||||
}
|
||||
|
||||
result := make([]dto.PurchaseSupplierDTO, 0, len(supplierIDs))
|
||||
for _, supplierID := range supplierIDs {
|
||||
supplier, exists := supplierMap[supplierID]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
supplierItems := itemsBySupplier[supplierID]
|
||||
dtoItem := dto.ToPurchaseSupplierDTO(supplier, supplierItems)
|
||||
result = append(result, dtoItem)
|
||||
}
|
||||
|
||||
return result, totalSuppliers, nil
|
||||
}
|
||||
|
||||
@@ -27,3 +27,16 @@ type MarketingQuery struct {
|
||||
SalesPersonId int64 `query:"sales_person_id" validate:"omitempty"`
|
||||
MarketingId int64 `query:"marketing_id" validate:"omitempty"`
|
||||
}
|
||||
|
||||
type PurchaseSupplierQuery struct {
|
||||
Page int `query:"page" validate:"omitempty,min=1,gt=0"`
|
||||
Limit int `query:"limit" validate:"omitempty,min=1,max=100,gt=0"`
|
||||
AreaId int64 `query:"area_id" validate:"omitempty"`
|
||||
SupplierId int64 `query:"supplier_id" validate:"omitempty"`
|
||||
ProductId int64 `query:"product_id" validate:"omitempty"`
|
||||
ProductCategoryId int64 `query:"product_category_id" validate:"omitempty"`
|
||||
DateFrom string `query:"date_from" validate:"omitempty"`
|
||||
DateTo string `query:"date_to" validate:"omitempty"`
|
||||
SortBy string `query:"sort_by" validate:"omitempty"`
|
||||
FilterBy string `query:"filter_by" validate:"omitempty"`
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@ type Success struct {
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
TotalPages int64 `json:"total_pages"`
|
||||
TotalResults int64 `json:"total_results"`
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
TotalPages int64 `json:"total_pages"`
|
||||
TotalResults int64 `json:"total_results"`
|
||||
Filters interface{} `json:"filters,omitempty"`
|
||||
}
|
||||
|
||||
type SuccessWithPaginate[T any] struct {
|
||||
|
||||
Reference in New Issue
Block a user