237 lines
7.3 KiB
Go
237 lines
7.3 KiB
Go
package processor
|
|
|
|
import (
|
|
"apskel-pos-be/internal/entities"
|
|
"apskel-pos-be/internal/mappers"
|
|
"apskel-pos-be/internal/models"
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type IngredientProcessorImpl struct {
|
|
ingredientRepo IngredientRepository
|
|
unitRepo UnitRepository
|
|
}
|
|
|
|
func NewIngredientProcessor(ingredientRepo IngredientRepository, unitRepo UnitRepository) *IngredientProcessorImpl {
|
|
return &IngredientProcessorImpl{
|
|
ingredientRepo: ingredientRepo,
|
|
unitRepo: unitRepo,
|
|
}
|
|
}
|
|
|
|
func (p *IngredientProcessorImpl) CreateIngredient(ctx context.Context, req *models.CreateIngredientRequest) (*models.IngredientResponse, error) {
|
|
_, err := p.unitRepo.GetByID(ctx, req.UnitID, req.OrganizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ingredient := &entities.Ingredient{
|
|
ID: uuid.New(),
|
|
OrganizationID: req.OrganizationID,
|
|
OutletID: req.OutletID,
|
|
Name: req.Name,
|
|
UnitID: req.UnitID,
|
|
Cost: req.Cost,
|
|
Stock: req.Stock,
|
|
IsSemiFinished: req.IsSemiFinished,
|
|
IsActive: req.IsActive,
|
|
Metadata: req.Metadata,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Save to database
|
|
err = p.ingredientRepo.Create(ctx, ingredient)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get with relations
|
|
ingredientWithUnit, err := p.ingredientRepo.GetByID(ctx, ingredient.ID, req.OrganizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Map to response
|
|
ingredientModel := mappers.MapIngredientEntityToModel(ingredientWithUnit)
|
|
response := &models.IngredientResponse{
|
|
ID: ingredientModel.ID,
|
|
OrganizationID: ingredientModel.OrganizationID,
|
|
OutletID: ingredientModel.OutletID,
|
|
Name: ingredientModel.Name,
|
|
UnitID: ingredientModel.UnitID,
|
|
Cost: ingredientModel.Cost,
|
|
Stock: ingredientModel.Stock,
|
|
IsSemiFinished: ingredientModel.IsSemiFinished,
|
|
IsActive: ingredientModel.IsActive,
|
|
Metadata: ingredientModel.Metadata,
|
|
CreatedAt: ingredientModel.CreatedAt,
|
|
UpdatedAt: ingredientModel.UpdatedAt,
|
|
Unit: ingredientModel.Unit,
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (p *IngredientProcessorImpl) GetIngredientByID(ctx context.Context, id uuid.UUID) (*models.IngredientResponse, error) {
|
|
// For now, we'll need to get organizationID from context or request
|
|
// This is a limitation of the current interface design
|
|
organizationID := uuid.Nil // This should come from context
|
|
|
|
ingredient, err := p.ingredientRepo.GetByID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ingredientModel := mappers.MapIngredientEntityToModel(ingredient)
|
|
response := &models.IngredientResponse{
|
|
ID: ingredientModel.ID,
|
|
OrganizationID: ingredientModel.OrganizationID,
|
|
OutletID: ingredientModel.OutletID,
|
|
Name: ingredientModel.Name,
|
|
UnitID: ingredientModel.UnitID,
|
|
Cost: ingredientModel.Cost,
|
|
Stock: ingredientModel.Stock,
|
|
IsSemiFinished: ingredientModel.IsSemiFinished,
|
|
IsActive: ingredientModel.IsActive,
|
|
Metadata: ingredientModel.Metadata,
|
|
CreatedAt: ingredientModel.CreatedAt,
|
|
UpdatedAt: ingredientModel.UpdatedAt,
|
|
Unit: ingredientModel.Unit,
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (p *IngredientProcessorImpl) ListIngredients(ctx context.Context, organizationID uuid.UUID, outletID *uuid.UUID, page, limit int, search string) (*models.PaginatedResponse[models.IngredientResponse], error) {
|
|
// Set default values
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if limit < 1 {
|
|
limit = 10
|
|
}
|
|
if limit > 100 {
|
|
limit = 100
|
|
}
|
|
|
|
ingredients, total, err := p.ingredientRepo.GetAll(ctx, organizationID, outletID, page, limit, search, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Map to response models
|
|
ingredientModels := mappers.MapIngredientEntitiesToModels(ingredients)
|
|
ingredientResponses := make([]models.IngredientResponse, len(ingredientModels))
|
|
|
|
for i, ingredientModel := range ingredientModels {
|
|
ingredientResponses[i] = models.IngredientResponse{
|
|
ID: ingredientModel.ID,
|
|
OrganizationID: ingredientModel.OrganizationID,
|
|
OutletID: ingredientModel.OutletID,
|
|
Name: ingredientModel.Name,
|
|
UnitID: ingredientModel.UnitID,
|
|
Cost: ingredientModel.Cost,
|
|
Stock: ingredientModel.Stock,
|
|
IsSemiFinished: ingredientModel.IsSemiFinished,
|
|
IsActive: ingredientModel.IsActive,
|
|
Metadata: ingredientModel.Metadata,
|
|
CreatedAt: ingredientModel.CreatedAt,
|
|
UpdatedAt: ingredientModel.UpdatedAt,
|
|
Unit: ingredientModel.Unit,
|
|
}
|
|
}
|
|
|
|
// Create paginated response
|
|
paginatedResponse := &models.PaginatedResponse[models.IngredientResponse]{
|
|
Data: ingredientResponses,
|
|
Pagination: models.Pagination{
|
|
Page: page,
|
|
Limit: limit,
|
|
Total: int64(total),
|
|
TotalPages: (total + limit - 1) / limit,
|
|
},
|
|
}
|
|
|
|
return paginatedResponse, nil
|
|
}
|
|
|
|
func (p *IngredientProcessorImpl) UpdateIngredient(ctx context.Context, id uuid.UUID, req *models.UpdateIngredientRequest) (*models.IngredientResponse, error) {
|
|
// For now, we'll need to get organizationID from context or request
|
|
// This is a limitation of the current interface design
|
|
organizationID := uuid.Nil // This should come from context
|
|
|
|
// Get existing ingredient
|
|
existingIngredient, err := p.ingredientRepo.GetByID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Validate unit exists if changed
|
|
if req.UnitID != existingIngredient.UnitID {
|
|
_, err := p.unitRepo.GetByID(ctx, req.UnitID, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// Update fields
|
|
existingIngredient.OutletID = req.OutletID
|
|
existingIngredient.Name = req.Name
|
|
existingIngredient.UnitID = req.UnitID
|
|
existingIngredient.Cost = req.Cost
|
|
existingIngredient.Stock = req.Stock
|
|
existingIngredient.IsSemiFinished = req.IsSemiFinished
|
|
existingIngredient.IsActive = req.IsActive
|
|
existingIngredient.Metadata = req.Metadata
|
|
existingIngredient.UpdatedAt = time.Now()
|
|
|
|
// Save to database
|
|
err = p.ingredientRepo.Update(ctx, existingIngredient)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get with relations
|
|
ingredientWithUnit, err := p.ingredientRepo.GetByID(ctx, id, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Map to response
|
|
ingredientModel := mappers.MapIngredientEntityToModel(ingredientWithUnit)
|
|
response := &models.IngredientResponse{
|
|
ID: ingredientModel.ID,
|
|
OrganizationID: ingredientModel.OrganizationID,
|
|
OutletID: ingredientModel.OutletID,
|
|
Name: ingredientModel.Name,
|
|
UnitID: ingredientModel.UnitID,
|
|
Cost: ingredientModel.Cost,
|
|
Stock: ingredientModel.Stock,
|
|
IsSemiFinished: ingredientModel.IsSemiFinished,
|
|
IsActive: ingredientModel.IsActive,
|
|
Metadata: ingredientModel.Metadata,
|
|
CreatedAt: ingredientModel.CreatedAt,
|
|
UpdatedAt: ingredientModel.UpdatedAt,
|
|
Unit: ingredientModel.Unit,
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
func (p *IngredientProcessorImpl) DeleteIngredient(ctx context.Context, id uuid.UUID) error {
|
|
// For now, we'll need to get organizationID from context or request
|
|
// This is a limitation of the current interface design
|
|
organizationID := uuid.Nil // This should come from context
|
|
|
|
err := p.ingredientRepo.Delete(ctx, id, organizationID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|