package service import ( "context" "apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/processor" "apskel-pos-be/internal/transformer" "github.com/google/uuid" ) type InventoryService interface { CreateInventory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateInventoryRequest) *contract.Response UpdateInventory(ctx context.Context, id uuid.UUID, req *contract.UpdateInventoryRequest) *contract.Response DeleteInventory(ctx context.Context, id uuid.UUID) *contract.Response GetInventoryByID(ctx context.Context, id uuid.UUID) *contract.Response ListInventory(ctx context.Context, req *contract.ListInventoryRequest) *contract.Response AdjustInventory(ctx context.Context, req *contract.AdjustInventoryRequest) *contract.Response GetLowStockItems(ctx context.Context, outletID uuid.UUID) *contract.Response GetZeroStockItems(ctx context.Context, outletID uuid.UUID) *contract.Response } type InventoryServiceImpl struct { inventoryProcessor processor.InventoryProcessor } func NewInventoryService(inventoryProcessor processor.InventoryProcessor) *InventoryServiceImpl { return &InventoryServiceImpl{ inventoryProcessor: inventoryProcessor, } } func (s *InventoryServiceImpl) CreateInventory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateInventoryRequest) *contract.Response { modelReq := transformer.CreateInventoryRequestToModel(req) inventoryResponse, err := s.inventoryProcessor.CreateInventory(ctx, modelReq) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponse := transformer.InventoryModelResponseToResponse(inventoryResponse) return contract.BuildSuccessResponse(contractResponse) } func (s *InventoryServiceImpl) UpdateInventory(ctx context.Context, id uuid.UUID, req *contract.UpdateInventoryRequest) *contract.Response { modelReq := transformer.UpdateInventoryRequestToModel(req) inventoryResponse, err := s.inventoryProcessor.UpdateInventory(ctx, id, modelReq) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponse := transformer.InventoryModelResponseToResponse(inventoryResponse) return contract.BuildSuccessResponse(contractResponse) } func (s *InventoryServiceImpl) DeleteInventory(ctx context.Context, id uuid.UUID) *contract.Response { err := s.inventoryProcessor.DeleteInventory(ctx, id) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } return contract.BuildSuccessResponse(map[string]interface{}{ "message": "Inventory deleted successfully", }) } func (s *InventoryServiceImpl) GetInventoryByID(ctx context.Context, id uuid.UUID) *contract.Response { inventoryResponse, err := s.inventoryProcessor.GetInventoryByID(ctx, id) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponse := transformer.InventoryModelResponseToResponse(inventoryResponse) return contract.BuildSuccessResponse(contractResponse) } func (s *InventoryServiceImpl) ListInventory(ctx context.Context, req *contract.ListInventoryRequest) *contract.Response { // Build filters filters := make(map[string]interface{}) if req.OutletID != nil { filters["outlet_id"] = *req.OutletID } if req.ProductID != nil { filters["product_id"] = *req.ProductID } if req.CategoryID != nil { filters["category_id"] = *req.CategoryID } if req.LowStockOnly != nil && *req.LowStockOnly { filters["low_stock"] = true } if req.ZeroStockOnly != nil && *req.ZeroStockOnly { filters["zero_stock"] = true } if req.Search != "" { filters["search"] = req.Search } inventory, totalCount, err := s.inventoryProcessor.ListInventory(ctx, filters, req.Page, req.Limit) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } // Convert to contract responses contractResponses := transformer.InventoryToResponses(inventory) // Calculate total pages totalPages := totalCount / req.Limit if totalCount%req.Limit > 0 { totalPages++ } listResponse := &contract.ListInventoryResponse{ Inventory: contractResponses, TotalCount: totalCount, Page: req.Page, Limit: req.Limit, TotalPages: totalPages, } return contract.BuildSuccessResponse(listResponse) } func (s *InventoryServiceImpl) AdjustInventory(ctx context.Context, req *contract.AdjustInventoryRequest) *contract.Response { modelReq := transformer.AdjustInventoryRequestToModel(req) inventoryResponse, err := s.inventoryProcessor.AdjustInventory(ctx, req.ProductID, req.OutletID, modelReq) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponse := transformer.InventoryModelResponseToResponse(inventoryResponse) return contract.BuildSuccessResponse(contractResponse) } func (s *InventoryServiceImpl) GetLowStockItems(ctx context.Context, outletID uuid.UUID) *contract.Response { inventory, err := s.inventoryProcessor.GetLowStockItems(ctx, outletID) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponses := transformer.InventoryToResponses(inventory) return contract.BuildSuccessResponse(contractResponses) } func (s *InventoryServiceImpl) GetZeroStockItems(ctx context.Context, outletID uuid.UUID) *contract.Response { inventory, err := s.inventoryProcessor.GetZeroStockItems(ctx, outletID) if err != nil { errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.InventoryServiceEntity, err.Error()) return contract.BuildErrorResponse([]*contract.ResponseError{errorResp}) } contractResponses := transformer.InventoryToResponses(inventory) return contract.BuildSuccessResponse(contractResponses) }