mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
237 lines
7.1 KiB
Go
237 lines
7.1 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) latestPurchaseApproval(ctx context.Context) *gorm.DB {
|
|
return r.db.WithContext(ctx).
|
|
Table("approvals AS a").
|
|
Select("a.approvable_id, a.step_number, a.action").
|
|
Joins(`
|
|
JOIN (
|
|
SELECT approvable_id, MAX(action_at) AS latest_action_at
|
|
FROM approvals
|
|
WHERE approvable_type = ?
|
|
GROUP BY approvable_id
|
|
) AS la ON la.approvable_id = a.approvable_id AND la.latest_action_at = a.action_at`,
|
|
string(utils.ApprovalWorkflowPurchase),
|
|
)
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
latestApproval := r.latestPurchaseApproval(ctx)
|
|
|
|
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").
|
|
Joins("JOIN (?) AS la ON la.approvable_id = purchases.id", latestApproval).
|
|
Where("la.step_number >= ?", uint16(utils.PurchaseStepReceiving)).
|
|
Where("(la.action IS NULL OR la.action != ?)", string(entity.ApprovalActionRejected)).
|
|
Where("purchase_items.received_date IS NOT NULL")
|
|
|
|
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").
|
|
Joins("JOIN (?) AS la ON la.approvable_id = purchases.id", r.latestPurchaseApproval(ctx)).
|
|
Where("purchases.supplier_id IN ?", supplierIDs).
|
|
Where("la.step_number >= ?", uint16(utils.PurchaseStepReceiving)).
|
|
Where("(la.action IS NULL OR la.action != ?)", string(entity.ApprovalActionRejected)).
|
|
Where("purchase_items.received_date IS NOT NULL")
|
|
|
|
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
|
|
}
|