package repository import ( "apskel-pos-be/internal/entities" "context" "github.com/google/uuid" "gorm.io/gorm" ) type OrderIngredientTransactionRepository interface { Create(ctx context.Context, transaction *entities.OrderIngredientTransaction) error GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.OrderIngredientTransaction, error) Update(ctx context.Context, transaction *entities.OrderIngredientTransaction) error Delete(ctx context.Context, id, organizationID uuid.UUID) error List(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, page, limit int) ([]*entities.OrderIngredientTransaction, int64, error) GetByOrderID(ctx context.Context, orderID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) GetByOrderItemID(ctx context.Context, orderItemID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) GetByIngredientID(ctx context.Context, ingredientID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) GetSummary(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}) ([]*entities.OrderIngredientTransaction, error) BulkCreate(ctx context.Context, transactions []*entities.OrderIngredientTransaction) error } type OrderIngredientTransactionRepositoryImpl struct { db *gorm.DB } func NewOrderIngredientTransactionRepositoryImpl(db *gorm.DB) OrderIngredientTransactionRepository { return &OrderIngredientTransactionRepositoryImpl{db: db} } func (r *OrderIngredientTransactionRepositoryImpl) Create(ctx context.Context, transaction *entities.OrderIngredientTransaction) error { return r.db.WithContext(ctx).Create(transaction).Error } func (r *OrderIngredientTransactionRepositoryImpl) GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.OrderIngredientTransaction, error) { var transaction entities.OrderIngredientTransaction err := r.db.WithContext(ctx). Where("id = ? AND organization_id = ?", id, organizationID). Preload("Organization"). Preload("Outlet"). Preload("Order"). Preload("OrderItem"). Preload("Product"). Preload("ProductVariant"). Preload("Ingredient"). Preload("CreatedByUser"). First(&transaction).Error if err != nil { return nil, err } return &transaction, nil } func (r *OrderIngredientTransactionRepositoryImpl) Update(ctx context.Context, transaction *entities.OrderIngredientTransaction) error { return r.db.WithContext(ctx).Save(transaction).Error } func (r *OrderIngredientTransactionRepositoryImpl) Delete(ctx context.Context, id, organizationID uuid.UUID) error { return r.db.WithContext(ctx). Where("id = ? AND organization_id = ?", id, organizationID). Delete(&entities.OrderIngredientTransaction{}).Error } func (r *OrderIngredientTransactionRepositoryImpl) List(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}, page, limit int) ([]*entities.OrderIngredientTransaction, int64, error) { var transactions []*entities.OrderIngredientTransaction var total int64 query := r.db.WithContext(ctx).Model(&entities.OrderIngredientTransaction{}). Where("organization_id = ?", organizationID) // Apply filters for key, value := range filters { switch key { case "order_id": if orderID, ok := value.(uuid.UUID); ok { query = query.Where("order_id = ?", orderID) } case "order_item_id": if orderItemID, ok := value.(uuid.UUID); ok { query = query.Where("order_item_id = ?", orderItemID) } case "product_id": if productID, ok := value.(uuid.UUID); ok { query = query.Where("product_id = ?", productID) } case "product_variant_id": if productVariantID, ok := value.(uuid.UUID); ok { query = query.Where("product_variant_id = ?", productVariantID) } case "ingredient_id": if ingredientID, ok := value.(uuid.UUID); ok { query = query.Where("ingredient_id = ?", ingredientID) } case "start_date": if startDate, ok := value.(string); ok { query = query.Where("transaction_date >= ?", startDate) } case "end_date": if endDate, ok := value.(string); ok { query = query.Where("transaction_date <= ?", endDate) } } } // Get total count if err := query.Count(&total).Error; err != nil { return nil, 0, err } // Apply pagination and get results offset := (page - 1) * limit err := query. Preload("Organization"). Preload("Outlet"). Preload("Order"). Preload("OrderItem"). Preload("Product"). Preload("ProductVariant"). Preload("Ingredient"). Preload("CreatedByUser"). Order("created_at DESC"). Offset(offset). Limit(limit). Find(&transactions).Error return transactions, total, err } func (r *OrderIngredientTransactionRepositoryImpl) GetByOrderID(ctx context.Context, orderID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) { var transactions []*entities.OrderIngredientTransaction err := r.db.WithContext(ctx). Where("order_id = ? AND organization_id = ?", orderID, organizationID). Preload("Organization"). Preload("Outlet"). Preload("Order"). Preload("OrderItem"). Preload("Product"). Preload("ProductVariant"). Preload("Ingredient"). Preload("CreatedByUser"). Order("created_at ASC"). Find(&transactions).Error return transactions, err } func (r *OrderIngredientTransactionRepositoryImpl) GetByOrderItemID(ctx context.Context, orderItemID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) { var transactions []*entities.OrderIngredientTransaction err := r.db.WithContext(ctx). Where("order_item_id = ? AND organization_id = ?", orderItemID, organizationID). Preload("Organization"). Preload("Outlet"). Preload("Order"). Preload("OrderItem"). Preload("Product"). Preload("ProductVariant"). Preload("Ingredient"). Preload("CreatedByUser"). Order("created_at ASC"). Find(&transactions).Error return transactions, err } func (r *OrderIngredientTransactionRepositoryImpl) GetByIngredientID(ctx context.Context, ingredientID, organizationID uuid.UUID) ([]*entities.OrderIngredientTransaction, error) { var transactions []*entities.OrderIngredientTransaction err := r.db.WithContext(ctx). Where("ingredient_id = ? AND organization_id = ?", ingredientID, organizationID). Preload("Organization"). Preload("Outlet"). Preload("Order"). Preload("OrderItem"). Preload("Product"). Preload("ProductVariant"). Preload("Ingredient"). Preload("CreatedByUser"). Order("created_at DESC"). Find(&transactions).Error return transactions, err } func (r *OrderIngredientTransactionRepositoryImpl) GetSummary(ctx context.Context, organizationID uuid.UUID, filters map[string]interface{}) ([]*entities.OrderIngredientTransaction, error) { var transactions []*entities.OrderIngredientTransaction query := r.db.WithContext(ctx).Model(&entities.OrderIngredientTransaction{}). Where("organization_id = ?", organizationID) // Apply filters for key, value := range filters { switch key { case "order_id": if orderID, ok := value.(uuid.UUID); ok { query = query.Where("order_id = ?", orderID) } case "order_item_id": if orderItemID, ok := value.(uuid.UUID); ok { query = query.Where("order_item_id = ?", orderItemID) } case "product_id": if productID, ok := value.(uuid.UUID); ok { query = query.Where("product_id = ?", productID) } case "product_variant_id": if productVariantID, ok := value.(uuid.UUID); ok { query = query.Where("product_variant_id = ?", productVariantID) } case "ingredient_id": if ingredientID, ok := value.(uuid.UUID); ok { query = query.Where("ingredient_id = ?", ingredientID) } case "start_date": if startDate, ok := value.(string); ok { query = query.Where("transaction_date >= ?", startDate) } case "end_date": if endDate, ok := value.(string); ok { query = query.Where("transaction_date <= ?", endDate) } } } err := query. Preload("Ingredient"). Order("ingredient_id, created_at ASC"). Find(&transactions).Error return transactions, err } func (r *OrderIngredientTransactionRepositoryImpl) BulkCreate(ctx context.Context, transactions []*entities.OrderIngredientTransaction) error { if len(transactions) == 0 { return nil } return r.db.WithContext(ctx).CreateInBatches(transactions, 100).Error }