apskel-pos-backend/internal/repository/purchase_order_repository.go
2025-09-12 01:12:11 +07:00

249 lines
8.1 KiB
Go

package repository
import (
"context"
"strings"
"time"
"github.com/google/uuid"
"apskel-pos-be/internal/entities"
"gorm.io/gorm"
)
type PurchaseOrderRepositoryImpl struct {
db *gorm.DB
}
func NewPurchaseOrderRepositoryImpl(db *gorm.DB) *PurchaseOrderRepositoryImpl {
return &PurchaseOrderRepositoryImpl{
db: db,
}
}
func (r *PurchaseOrderRepositoryImpl) Create(ctx context.Context, po *entities.PurchaseOrder) error {
return r.db.WithContext(ctx).Create(po).Error
}
func (r *PurchaseOrderRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entities.PurchaseOrder, error) {
var po entities.PurchaseOrder
err := r.db.WithContext(ctx).
Preload("Vendor").
Preload("Items.Ingredient").
Preload("Items.Unit").
Preload("Attachments.File").
First(&po, "id = ?", id).Error
if err != nil {
return nil, err
}
return &po, nil
}
func (r *PurchaseOrderRepositoryImpl) GetByIDAndOrganizationID(ctx context.Context, id, organizationID uuid.UUID) (*entities.PurchaseOrder, error) {
var po entities.PurchaseOrder
err := r.db.WithContext(ctx).
Preload("Vendor").
Preload("Items.Ingredient").
Preload("Items.Unit").
Preload("Attachments.File").
Where("id = ? AND organization_id = ?", id, organizationID).
First(&po).Error
if err != nil {
return nil, err
}
return &po, nil
}
func (r *PurchaseOrderRepositoryImpl) Update(ctx context.Context, po *entities.PurchaseOrder) error {
return r.db.WithContext(ctx).Save(po).Error
}
func (r *PurchaseOrderRepositoryImpl) Delete(ctx context.Context, id uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&entities.PurchaseOrder{}, "id = ?", id).Error
}
func (r *PurchaseOrderRepositoryImpl) List(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, limit, offset int) ([]*entities.PurchaseOrder, int64, error) {
var pos []*entities.PurchaseOrder
var total int64
query := r.db.WithContext(ctx).Model(&entities.PurchaseOrder{}).Where("organization_id = ?", organizationID)
// Apply filters
for key, value := range filters {
switch key {
case "search":
if searchStr, ok := value.(string); ok && searchStr != "" {
searchPattern := "%" + strings.ToLower(searchStr) + "%"
query = query.Where("LOWER(po_number) LIKE ? OR LOWER(reference) LIKE ?", searchPattern, searchPattern)
}
case "status":
if status, ok := value.(string); ok && status != "" {
query = query.Where("status = ?", status)
}
case "vendor_id":
if vendorID, ok := value.(uuid.UUID); ok {
query = query.Where("vendor_id = ?", vendorID)
}
case "start_date":
if startDate, ok := value.(time.Time); ok {
query = query.Where("transaction_date >= ?", startDate)
}
case "end_date":
if endDate, ok := value.(time.Time); ok {
query = query.Where("transaction_date <= ?", endDate)
}
default:
query = query.Where(key+" = ?", value)
}
}
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
err := query.
Preload("Vendor").
Preload("Items.Ingredient").
Preload("Items.Unit").
Preload("Attachments.File").
Order("created_at DESC").
Limit(limit).
Offset(offset).
Find(&pos).Error
return pos, total, err
}
func (r *PurchaseOrderRepositoryImpl) Count(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}) (int64, error) {
var count int64
query := r.db.WithContext(ctx).Model(&entities.PurchaseOrder{}).Where("organization_id = ?", organizationID)
// Apply filters
for key, value := range filters {
switch key {
case "search":
if searchStr, ok := value.(string); ok && searchStr != "" {
searchPattern := "%" + strings.ToLower(searchStr) + "%"
query = query.Where("LOWER(po_number) LIKE ? OR LOWER(reference) LIKE ?", searchPattern, searchPattern)
}
case "status":
if status, ok := value.(string); ok && status != "" {
query = query.Where("status = ?", status)
}
case "vendor_id":
if vendorID, ok := value.(uuid.UUID); ok {
query = query.Where("vendor_id = ?", vendorID)
}
case "start_date":
if startDate, ok := value.(time.Time); ok {
query = query.Where("transaction_date >= ?", startDate)
}
case "end_date":
if endDate, ok := value.(time.Time); ok {
query = query.Where("transaction_date <= ?", endDate)
}
default:
query = query.Where(key+" = ?", value)
}
}
err := query.Count(&count).Error
return count, err
}
func (r *PurchaseOrderRepositoryImpl) GetByPONumber(ctx context.Context, poNumber string, organizationID uuid.UUID) (*entities.PurchaseOrder, error) {
var po entities.PurchaseOrder
err := r.db.WithContext(ctx).
Where("po_number = ? AND organization_id = ?", poNumber, organizationID).
First(&po).Error
if err != nil {
return nil, err
}
return &po, nil
}
func (r *PurchaseOrderRepositoryImpl) GetByStatus(ctx context.Context, organizationID uuid.UUID, status string) ([]*entities.PurchaseOrder, error) {
var pos []*entities.PurchaseOrder
err := r.db.WithContext(ctx).
Where("organization_id = ? AND status = ?", organizationID, status).
Preload("Vendor").
Preload("Items.Ingredient").
Preload("Items.Unit").
Find(&pos).Error
return pos, err
}
func (r *PurchaseOrderRepositoryImpl) GetOverdue(ctx context.Context, organizationID uuid.UUID) ([]*entities.PurchaseOrder, error) {
var pos []*entities.PurchaseOrder
err := r.db.WithContext(ctx).
Where("organization_id = ? AND due_date < ? AND status IN (?)", organizationID, time.Now(), []string{"draft", "sent", "approved"}).
Preload("Vendor").
Preload("Items.Ingredient").
Preload("Items.Unit").
Find(&pos).Error
return pos, err
}
func (r *PurchaseOrderRepositoryImpl) UpdateStatus(ctx context.Context, id uuid.UUID, status string) error {
return r.db.WithContext(ctx).
Model(&entities.PurchaseOrder{}).
Where("id = ?", id).
Update("status", status).Error
}
func (r *PurchaseOrderRepositoryImpl) UpdateTotalAmount(ctx context.Context, id uuid.UUID, totalAmount float64) error {
return r.db.WithContext(ctx).
Model(&entities.PurchaseOrder{}).
Where("id = ?", id).
Update("total_amount", totalAmount).Error
}
// Purchase Order Items methods
func (r *PurchaseOrderRepositoryImpl) CreateItem(ctx context.Context, item *entities.PurchaseOrderItem) error {
return r.db.WithContext(ctx).Create(item).Error
}
func (r *PurchaseOrderRepositoryImpl) UpdateItem(ctx context.Context, item *entities.PurchaseOrderItem) error {
return r.db.WithContext(ctx).Save(item).Error
}
func (r *PurchaseOrderRepositoryImpl) DeleteItem(ctx context.Context, id uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&entities.PurchaseOrderItem{}, "id = ?", id).Error
}
func (r *PurchaseOrderRepositoryImpl) DeleteItemsByPurchaseOrderID(ctx context.Context, purchaseOrderID uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&entities.PurchaseOrderItem{}, "purchase_order_id = ?", purchaseOrderID).Error
}
func (r *PurchaseOrderRepositoryImpl) GetItemsByPurchaseOrderID(ctx context.Context, purchaseOrderID uuid.UUID) ([]*entities.PurchaseOrderItem, error) {
var items []*entities.PurchaseOrderItem
err := r.db.WithContext(ctx).
Preload("Ingredient").
Preload("Unit").
Where("purchase_order_id = ?", purchaseOrderID).
Find(&items).Error
return items, err
}
// Purchase Order Attachments methods
func (r *PurchaseOrderRepositoryImpl) CreateAttachment(ctx context.Context, attachment *entities.PurchaseOrderAttachment) error {
return r.db.WithContext(ctx).Create(attachment).Error
}
func (r *PurchaseOrderRepositoryImpl) DeleteAttachment(ctx context.Context, id uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&entities.PurchaseOrderAttachment{}, "id = ?", id).Error
}
func (r *PurchaseOrderRepositoryImpl) DeleteAttachmentsByPurchaseOrderID(ctx context.Context, purchaseOrderID uuid.UUID) error {
return r.db.WithContext(ctx).Delete(&entities.PurchaseOrderAttachment{}, "purchase_order_id = ?", purchaseOrderID).Error
}
func (r *PurchaseOrderRepositoryImpl) GetAttachmentsByPurchaseOrderID(ctx context.Context, purchaseOrderID uuid.UUID) ([]*entities.PurchaseOrderAttachment, error) {
var attachments []*entities.PurchaseOrderAttachment
err := r.db.WithContext(ctx).
Preload("File").
Where("purchase_order_id = ?", purchaseOrderID).
Find(&attachments).Error
return attachments, err
}