Files
lti-api/internal/modules/repports/repositories/purchase_supplier.repository.go
T

212 lines
6.0 KiB
Go

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 {
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 || filters.AllowedAreaIDs != nil {
db = db.Joins("JOIN warehouses ON warehouses.id = purchase_items.warehouse_id")
if filters.AreaId > 0 {
db = db.Where("warehouses.area_id = ?", filters.AreaId)
}
if filters.AllowedAreaIDs != nil {
if len(filters.AllowedAreaIDs) == 0 {
db = db.Where("1 = 0")
} else {
db = db.Where("warehouses.area_id IN ?", filters.AllowedAreaIDs)
}
}
}
if filters.StartDate != "" {
if dateFrom, err := utils.ParseDateString(filters.StartDate); err == nil {
db = db.Where(fmt.Sprintf("DATE(%s) >= ?", dateColumn), dateFrom)
}
}
if filters.EndDate != "" {
if dateTo, err := utils.ParseDateString(filters.EndDate); 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 || filters.AllowedAreaIDs != nil {
db = db.Joins("JOIN warehouses ON warehouses.id = purchase_items.warehouse_id")
if filters.AreaId > 0 {
db = db.Where("warehouses.area_id = ?", filters.AreaId)
}
if filters.AllowedAreaIDs != nil {
if len(filters.AllowedAreaIDs) == 0 {
db = db.Where("1 = 0")
} else {
db = db.Where("warehouses.area_id IN ?", filters.AllowedAreaIDs)
}
}
}
if filters.StartDate != "" {
if dateFrom, err := utils.ParseDateString(filters.StartDate); err == nil {
db = db.Where(fmt.Sprintf("DATE(%s) >= ?", dateColumn), dateFrom)
}
}
if filters.EndDate != "" {
if dateTo, err := utils.ParseDateString(filters.EndDate); 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
}