apskel-pos-backend/internal/service/inventory_service.go
aditya.siregar 4f5950543e init
2025-07-18 20:10:29 +07:00

167 lines
6.6 KiB
Go

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)
}