mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
329 lines
9.8 KiB
Go
329 lines
9.8 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 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 {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewDebtSupplierRepository(db *gorm.DB) DebtSupplierRepository {
|
|
return &debtSupplierRepositoryImpl{db: db}
|
|
}
|
|
|
|
func resolveDebtSupplierDateColumn(filterBy string) string {
|
|
switch strings.ToLower(strings.TrimSpace(filterBy)) {
|
|
case "po_date":
|
|
return "purchases.po_date"
|
|
case "received_date", "":
|
|
return "purchase_items.received_date"
|
|
default:
|
|
return "purchase_items.received_date"
|
|
}
|
|
}
|
|
|
|
func (r *debtSupplierRepositoryImpl) baseSupplierQuery(ctx context.Context, filters *validation.DebtSupplierQuery) *gorm.DB {
|
|
dateColumn := resolveDebtSupplierDateColumn(filters.FilterBy)
|
|
|
|
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 len(filters.SupplierIDs) > 0 {
|
|
db = db.Where("suppliers.id IN ?", filters.SupplierIDs)
|
|
}
|
|
|
|
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 *debtSupplierRepositoryImpl) GetSuppliersWithPurchases(ctx context.Context, offset, limit int, filters *validation.DebtSupplierQuery) ([]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 *debtSupplierRepositoryImpl) GetPurchasesBySuppliers(ctx context.Context, supplierIDs []uint, filters *validation.DebtSupplierQuery) ([]entity.Purchase, error) {
|
|
if len(supplierIDs) == 0 {
|
|
return []entity.Purchase{}, nil
|
|
}
|
|
|
|
purchaseIDs, err := r.getPurchaseIDs(ctx, supplierIDs, filters)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(purchaseIDs) == 0 {
|
|
return []entity.Purchase{}, nil
|
|
}
|
|
|
|
preloadItems := func(db *gorm.DB) *gorm.DB {
|
|
db = db.
|
|
Preload("Warehouse").
|
|
Preload("Warehouse.Area").
|
|
Order("purchase_items.id ASC")
|
|
|
|
if strings.EqualFold(strings.TrimSpace(filters.FilterBy), "received_date") || strings.TrimSpace(filters.FilterBy) == "" {
|
|
if filters.StartDate != "" {
|
|
if dateFrom, err := utils.ParseDateString(filters.StartDate); err == nil {
|
|
db = db.Where("DATE(purchase_items.received_date) >= ?", dateFrom)
|
|
}
|
|
}
|
|
if filters.EndDate != "" {
|
|
if dateTo, err := utils.ParseDateString(filters.EndDate); err == nil {
|
|
db = db.Where("DATE(purchase_items.received_date) <= ?", dateTo)
|
|
}
|
|
}
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
var purchases []entity.Purchase
|
|
if err := r.db.WithContext(ctx).
|
|
Model(&entity.Purchase{}).
|
|
Preload("Supplier").
|
|
Preload("Items", preloadItems).
|
|
Where("purchases.id IN ?", purchaseIDs).
|
|
Order("purchases.id ASC").
|
|
Find(&purchases).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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)
|
|
|
|
db := r.db.WithContext(ctx).
|
|
Table("purchases").
|
|
Select("DISTINCT purchases.id").
|
|
Joins("JOIN purchase_items ON purchase_items.purchase_id = purchases.id").
|
|
Where("purchases.supplier_id IN ?", supplierIDs)
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
var purchaseIDs []uint
|
|
if err := db.Order("purchases.id ASC").Pluck("purchases.id", &purchaseIDs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return purchaseIDs, nil
|
|
}
|
|
|
|
func (r *debtSupplierRepositoryImpl) GetPaymentTotalsByReferences(ctx context.Context, supplierIDs []uint, references []string) (map[string]float64, error) {
|
|
if len(supplierIDs) == 0 || len(references) == 0 {
|
|
return map[string]float64{}, nil
|
|
}
|
|
|
|
type paymentRow struct {
|
|
ReferenceNumber *string `gorm:"column:reference_number"`
|
|
Total float64 `gorm:"column:total"`
|
|
}
|
|
|
|
rows := make([]paymentRow, 0)
|
|
if err := r.db.WithContext(ctx).
|
|
Model(&entity.Payment{}).
|
|
Select("reference_number, SUM(nominal) AS total").
|
|
Where("party_type = ?", string(utils.PaymentPartySupplier)).
|
|
Where("direction = ?", "OUT").
|
|
Where("party_id IN ?", supplierIDs).
|
|
Where("reference_number IN ?", references).
|
|
Group("reference_number").
|
|
Scan(&rows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := make(map[string]float64, len(rows))
|
|
for _, row := range rows {
|
|
if row.ReferenceNumber == nil || strings.TrimSpace(*row.ReferenceNumber) == "" {
|
|
continue
|
|
}
|
|
result[*row.ReferenceNumber] = row.Total
|
|
}
|
|
|
|
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
|
|
}
|