package service import ( "apskel-pos-be/internal/entities" "apskel-pos-be/internal/repository" "context" "time" "github.com/google/uuid" ) type InventoryMovementService interface { CreateIngredientMovement(ctx context.Context, ingredientID, organizationID, outletID, userID uuid.UUID, movementType entities.InventoryMovementType, quantity float64, unitCost float64, reason string, referenceType *entities.InventoryMovementReferenceType, referenceID *uuid.UUID) error CreateProductMovement(ctx context.Context, productID, organizationID, outletID, userID uuid.UUID, movementType entities.InventoryMovementType, quantity float64, unitCost float64, reason string, referenceType *entities.InventoryMovementReferenceType, referenceID *uuid.UUID) error } type InventoryMovementServiceImpl struct { inventoryMovementRepo repository.InventoryMovementRepository ingredientRepo *repository.IngredientRepository } func NewInventoryMovementService(inventoryMovementRepo repository.InventoryMovementRepository, ingredientRepo *repository.IngredientRepository) InventoryMovementService { return &InventoryMovementServiceImpl{ inventoryMovementRepo: inventoryMovementRepo, ingredientRepo: ingredientRepo, } } func (s *InventoryMovementServiceImpl) CreateIngredientMovement(ctx context.Context, ingredientID, organizationID, outletID, userID uuid.UUID, movementType entities.InventoryMovementType, quantity float64, unitCost float64, reason string, referenceType *entities.InventoryMovementReferenceType, referenceID *uuid.UUID) error { ingredient, err := s.ingredientRepo.GetByID(ctx, ingredientID, organizationID) if err != nil { return err } previousQuantity := ingredient.Stock newQuantity := previousQuantity + quantity movement := &entities.InventoryMovement{ ID: uuid.New(), OrganizationID: organizationID, OutletID: outletID, ItemID: ingredientID, ItemType: "INGREDIENT", MovementType: movementType, Quantity: quantity, PreviousQuantity: previousQuantity, NewQuantity: newQuantity, UnitCost: unitCost, TotalCost: unitCost * quantity, ReferenceType: referenceType, ReferenceID: referenceID, UserID: userID, Reason: &reason, CreatedAt: time.Now(), } err = s.inventoryMovementRepo.Create(ctx, movement) if err != nil { return err } err = s.ingredientRepo.UpdateStock(ctx, ingredientID, quantity, organizationID) if err != nil { return err } return nil } func (s *InventoryMovementServiceImpl) CreateProductMovement(ctx context.Context, productID, organizationID, outletID, userID uuid.UUID, movementType entities.InventoryMovementType, quantity float64, unitCost float64, reason string, referenceType *entities.InventoryMovementReferenceType, referenceID *uuid.UUID) error { movement := &entities.InventoryMovement{ ID: uuid.New(), OrganizationID: organizationID, OutletID: outletID, ItemID: productID, ItemType: "PRODUCT", MovementType: movementType, Quantity: quantity, PreviousQuantity: 0, // TODO This would be fetched from product inventory NewQuantity: 0, // TODO This would be calculated UnitCost: unitCost, TotalCost: unitCost * quantity, ReferenceType: referenceType, ReferenceID: referenceID, UserID: userID, Reason: &reason, CreatedAt: time.Now(), } err := s.inventoryMovementRepo.Create(ctx, movement) if err != nil { return err } return nil }