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,
|
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"
|
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
approvalService "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
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"
|
sRepport "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/services"
|
||||||
|
|
||||||
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
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)
|
expenseRealizationRepository := expenseRepo.NewExpenseRealizationRepository(db)
|
||||||
marketingDeliveryProductRepository := marketingRepo.NewMarketingDeliveryProductRepository(db)
|
marketingDeliveryProductRepository := marketingRepo.NewMarketingDeliveryProductRepository(db)
|
||||||
approvalRepository := commonRepo.NewApprovalRepository(db)
|
approvalRepository := commonRepo.NewApprovalRepository(db)
|
||||||
|
purchaseSupplierRepository := repportRepo.NewPurchaseSupplierRepository(db)
|
||||||
|
|
||||||
approvalSvc := approvalService.NewApprovalService(approvalRepository)
|
approvalSvc := approvalService.NewApprovalService(approvalRepository)
|
||||||
repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, approvalSvc)
|
repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, approvalSvc, purchaseSupplierRepository)
|
||||||
|
|
||||||
RepportRoutes(router, repportService)
|
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("/expense", ctrl.GetExpense)
|
||||||
route.Get("/marketing", ctrl.GetMarketing)
|
route.Get("/marketing", ctrl.GetMarketing)
|
||||||
|
route.Get("/purchase-supplier", ctrl.GetPurchaseSupplier)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/repports/dto"
|
"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"
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/repports/validations"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
|
|
||||||
@@ -10,6 +11,8 @@ import (
|
|||||||
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||||
marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/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/go-playground/validator/v10"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -19,6 +22,7 @@ import (
|
|||||||
type RepportService interface {
|
type RepportService interface {
|
||||||
GetExpense(ctx *fiber.Ctx, params *validation.ExpenseQuery) ([]dto.RepportExpenseListDTO, int64, error)
|
GetExpense(ctx *fiber.Ctx, params *validation.ExpenseQuery) ([]dto.RepportExpenseListDTO, int64, error)
|
||||||
GetMarketing(ctx *fiber.Ctx, params *validation.MarketingQuery) ([]dto.RepportMarketingListDTO, 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 {
|
type repportService struct {
|
||||||
@@ -27,15 +31,23 @@ type repportService struct {
|
|||||||
ExpenseRealizationRepo expenseRepo.ExpenseRealizationRepository
|
ExpenseRealizationRepo expenseRepo.ExpenseRealizationRepository
|
||||||
MarketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository
|
MarketingDeliveryRepo marketingRepo.MarketingDeliveryProductRepository
|
||||||
ApprovalSvc approvalService.ApprovalService
|
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{
|
return &repportService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
Validate: validate,
|
Validate: validate,
|
||||||
ExpenseRealizationRepo: expenseRealizationRepo,
|
ExpenseRealizationRepo: expenseRealizationRepo,
|
||||||
MarketingDeliveryRepo: marketingDeliveryRepo,
|
MarketingDeliveryRepo: marketingDeliveryRepo,
|
||||||
ApprovalSvc: approvalSvc,
|
ApprovalSvc: approvalSvc,
|
||||||
|
PurchaseSupplierRepo: purchaseSupplierRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,3 +125,58 @@ func (s *repportService) GetMarketing(c *fiber.Ctx, params *validation.Marketing
|
|||||||
|
|
||||||
return dto.ToRepportMarketingListDTOs(deliveryProducts), total, nil
|
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"`
|
SalesPersonId int64 `query:"sales_person_id" validate:"omitempty"`
|
||||||
MarketingId int64 `query:"marketing_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 {
|
type Meta struct {
|
||||||
Page int `json:"page"`
|
Page int `json:"page"`
|
||||||
Limit int `json:"limit"`
|
Limit int `json:"limit"`
|
||||||
TotalPages int64 `json:"total_pages"`
|
TotalPages int64 `json:"total_pages"`
|
||||||
TotalResults int64 `json:"total_results"`
|
TotalResults int64 `json:"total_results"`
|
||||||
|
Filters interface{} `json:"filters,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SuccessWithPaginate[T any] struct {
|
type SuccessWithPaginate[T any] struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user