This commit is contained in:
aditya.siregar
2025-07-18 20:10:29 +07:00
parent 1bceae010b
commit 4f5950543e
511 changed files with 24132 additions and 34137 deletions
+243
View File
@@ -0,0 +1,243 @@
package service
import (
"context"
"fmt"
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/processor"
"github.com/google/uuid"
)
type AnalyticsService interface {
GetPaymentMethodAnalytics(ctx context.Context, req *models.PaymentMethodAnalyticsRequest) (*models.PaymentMethodAnalyticsResponse, error)
GetSalesAnalytics(ctx context.Context, req *models.SalesAnalyticsRequest) (*models.SalesAnalyticsResponse, error)
GetProductAnalytics(ctx context.Context, req *models.ProductAnalyticsRequest) (*models.ProductAnalyticsResponse, error)
GetDashboardAnalytics(ctx context.Context, req *models.DashboardAnalyticsRequest) (*models.DashboardAnalyticsResponse, error)
GetProfitLossAnalytics(ctx context.Context, req *models.ProfitLossAnalyticsRequest) (*models.ProfitLossAnalyticsResponse, error)
}
type AnalyticsServiceImpl struct {
analyticsProcessor processor.AnalyticsProcessor
}
func NewAnalyticsServiceImpl(analyticsProcessor processor.AnalyticsProcessor) *AnalyticsServiceImpl {
return &AnalyticsServiceImpl{
analyticsProcessor: analyticsProcessor,
}
}
func (s *AnalyticsServiceImpl) GetPaymentMethodAnalytics(ctx context.Context, req *models.PaymentMethodAnalyticsRequest) (*models.PaymentMethodAnalyticsResponse, error) {
// Validate request
if err := s.validatePaymentMethodAnalyticsRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process analytics request
response, err := s.analyticsProcessor.GetPaymentMethodAnalytics(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to get payment method analytics: %w", err)
}
return response, nil
}
func (s *AnalyticsServiceImpl) GetSalesAnalytics(ctx context.Context, req *models.SalesAnalyticsRequest) (*models.SalesAnalyticsResponse, error) {
// Validate request
if err := s.validateSalesAnalyticsRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process analytics request
response, err := s.analyticsProcessor.GetSalesAnalytics(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to get sales analytics: %w", err)
}
return response, nil
}
func (s *AnalyticsServiceImpl) GetProductAnalytics(ctx context.Context, req *models.ProductAnalyticsRequest) (*models.ProductAnalyticsResponse, error) {
// Validate request
if err := s.validateProductAnalyticsRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process analytics request
response, err := s.analyticsProcessor.GetProductAnalytics(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to get product analytics: %w", err)
}
return response, nil
}
func (s *AnalyticsServiceImpl) GetDashboardAnalytics(ctx context.Context, req *models.DashboardAnalyticsRequest) (*models.DashboardAnalyticsResponse, error) {
// Validate request
if err := s.validateDashboardAnalyticsRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process analytics request
response, err := s.analyticsProcessor.GetDashboardAnalytics(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to get dashboard analytics: %w", err)
}
return response, nil
}
// Validation methods
func (s *AnalyticsServiceImpl) validatePaymentMethodAnalyticsRequest(req *models.PaymentMethodAnalyticsRequest) error {
if req.OrganizationID == uuid.Nil {
return fmt.Errorf("organization ID is required")
}
if req.DateFrom.IsZero() {
return fmt.Errorf("date_from is required")
}
if req.DateTo.IsZero() {
return fmt.Errorf("date_to is required")
}
if req.DateFrom.After(req.DateTo) {
return fmt.Errorf("date_from cannot be after date_to")
}
// Validate groupBy if provided
if req.GroupBy != "" {
validGroupBy := map[string]bool{
"day": true,
"hour": true,
"week": true,
"month": true,
}
if !validGroupBy[req.GroupBy] {
return fmt.Errorf("invalid group_by value: %s", req.GroupBy)
}
}
return nil
}
func (s *AnalyticsServiceImpl) validateSalesAnalyticsRequest(req *models.SalesAnalyticsRequest) error {
if req.OrganizationID == uuid.Nil {
return fmt.Errorf("organization ID is required")
}
if req.DateFrom.IsZero() {
return fmt.Errorf("date_from is required")
}
if req.DateTo.IsZero() {
return fmt.Errorf("date_to is required")
}
if req.DateFrom.After(req.DateTo) {
return fmt.Errorf("date_from cannot be after date_to")
}
// Validate groupBy if provided
if req.GroupBy != "" {
validGroupBy := map[string]bool{
"day": true,
"hour": true,
"week": true,
"month": true,
}
if !validGroupBy[req.GroupBy] {
return fmt.Errorf("invalid group_by value: %s", req.GroupBy)
}
}
return nil
}
func (s *AnalyticsServiceImpl) validateProductAnalyticsRequest(req *models.ProductAnalyticsRequest) error {
if req.OrganizationID == uuid.Nil {
return fmt.Errorf("organization ID is required")
}
if req.DateFrom.IsZero() {
return fmt.Errorf("date_from is required")
}
if req.DateTo.IsZero() {
return fmt.Errorf("date_to is required")
}
if req.DateFrom.After(req.DateTo) {
return fmt.Errorf("date_from cannot be after date_to")
}
if req.Limit < 1 || req.Limit > 100 {
return fmt.Errorf("limit must be between 1 and 100")
}
return nil
}
func (s *AnalyticsServiceImpl) validateDashboardAnalyticsRequest(req *models.DashboardAnalyticsRequest) error {
if req.OrganizationID == uuid.Nil {
return fmt.Errorf("organization ID is required")
}
if req.DateFrom.IsZero() {
return fmt.Errorf("date_from is required")
}
if req.DateTo.IsZero() {
return fmt.Errorf("date_to is required")
}
if req.DateFrom.After(req.DateTo) {
return fmt.Errorf("date_from cannot be after date_to")
}
return nil
}
func (s *AnalyticsServiceImpl) GetProfitLossAnalytics(ctx context.Context, req *models.ProfitLossAnalyticsRequest) (*models.ProfitLossAnalyticsResponse, error) {
// Validate request
if err := s.validateProfitLossAnalyticsRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Call processor
response, err := s.analyticsProcessor.GetProfitLossAnalytics(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to get profit/loss analytics: %w", err)
}
return response, nil
}
func (s *AnalyticsServiceImpl) validateProfitLossAnalyticsRequest(req *models.ProfitLossAnalyticsRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.OrganizationID == uuid.Nil {
return fmt.Errorf("organization_id is required")
}
if req.DateFrom.IsZero() {
return fmt.Errorf("date_from is required")
}
if req.DateTo.IsZero() {
return fmt.Errorf("date_to is required")
}
if req.DateFrom.After(req.DateTo) {
return fmt.Errorf("date_from cannot be after date_to")
}
if req.GroupBy != "" && req.GroupBy != "hour" && req.GroupBy != "day" && req.GroupBy != "week" && req.GroupBy != "month" {
return fmt.Errorf("invalid group_by value, must be one of: hour, day, week, month")
}
return nil
}
+184
View File
@@ -0,0 +1,184 @@
package service
import (
"context"
"errors"
"fmt"
"time"
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/transformer"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
)
type AuthService interface {
Login(ctx context.Context, req *contract.LoginRequest) (*contract.LoginResponse, error)
ValidateToken(tokenString string) (*contract.UserResponse, error)
RefreshToken(ctx context.Context, tokenString string) (*contract.LoginResponse, error)
Logout(ctx context.Context, tokenString string) error
}
type AuthServiceImpl struct {
userProcessor UserProcessor
jwtSecret string
tokenTTL time.Duration
}
type Claims struct {
UserID uuid.UUID `json:"user_id"`
Email string `json:"email"`
Role string `json:"role"`
OrganizationID uuid.UUID `json:"organization_id"`
jwt.RegisteredClaims
}
func NewAuthService(userProcessor UserProcessor, jwtSecret string) AuthService {
return &AuthServiceImpl{
userProcessor: userProcessor,
jwtSecret: jwtSecret,
tokenTTL: 24 * time.Hour,
}
}
func (s *AuthServiceImpl) Login(ctx context.Context, req *contract.LoginRequest) (*contract.LoginResponse, error) {
userResponse, err := s.userProcessor.GetUserByEmail(ctx, req.Email)
if err != nil {
return nil, fmt.Errorf("invalid credentials")
}
if !userResponse.IsActive {
return nil, fmt.Errorf("user account is deactivated")
}
userEntity, err := s.userProcessor.GetUserEntityByEmail(ctx, req.Email)
if err != nil {
return nil, fmt.Errorf("invalid credentials")
}
err = bcrypt.CompareHashAndPassword([]byte(userEntity.PasswordHash), []byte(req.Password))
if err != nil {
return nil, fmt.Errorf("invalid credentials")
}
contractUserResponse := transformer.UserModelResponseToResponse(userResponse)
token, expiresAt, err := s.generateToken(userResponse)
if err != nil {
return nil, fmt.Errorf("failed to generate token: %w", err)
}
return &contract.LoginResponse{
Token: token,
ExpiresAt: expiresAt,
User: *contractUserResponse,
}, nil
}
func (s *AuthServiceImpl) ValidateToken(tokenString string) (*contract.UserResponse, error) {
claims, err := s.parseToken(tokenString)
if err != nil {
return nil, fmt.Errorf("invalid token: %w", err)
}
userResponse, err := s.userProcessor.GetUserByID(context.Background(), claims.UserID)
if err != nil {
return nil, fmt.Errorf("user not found: %w", err)
}
if !userResponse.IsActive {
return nil, fmt.Errorf("user account is deactivated")
}
contractUserResponse := transformer.UserModelResponseToResponse(userResponse)
return contractUserResponse, nil
}
func (s *AuthServiceImpl) RefreshToken(ctx context.Context, tokenString string) (*contract.LoginResponse, error) {
claims, err := s.parseToken(tokenString)
if err != nil {
return nil, fmt.Errorf("invalid token: %w", err)
}
userResponse, err := s.userProcessor.GetUserByID(ctx, claims.UserID)
if err != nil {
return nil, fmt.Errorf("user not found: %w", err)
}
if !userResponse.IsActive {
return nil, fmt.Errorf("user account is deactivated")
}
contractUserResponse := transformer.UserModelResponseToResponse(userResponse)
newToken, expiresAt, err := s.generateToken(userResponse)
if err != nil {
return nil, fmt.Errorf("failed to generate token: %w", err)
}
return &contract.LoginResponse{
Token: newToken,
ExpiresAt: expiresAt,
User: *contractUserResponse,
}, nil
}
func (s *AuthServiceImpl) Logout(ctx context.Context, tokenString string) error {
// In a more sophisticated implementation, you might want to blacklist the token
// For now, we'll just validate that the token is valid
_, err := s.parseToken(tokenString)
if err != nil {
return fmt.Errorf("invalid token: %w", err)
}
// In the future, you could store blacklisted tokens in Redis or database
return nil
}
func (s *AuthServiceImpl) generateToken(user *models.UserResponse) (string, time.Time, error) {
expiresAt := time.Now().Add(s.tokenTTL)
claims := &Claims{
UserID: user.ID,
Email: user.Email,
Role: string(user.Role),
OrganizationID: user.OrganizationID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expiresAt),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
Issuer: "apskel-pos",
Subject: user.ID.String(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(s.jwtSecret))
if err != nil {
return "", time.Time{}, err
}
return tokenString, expiresAt, nil
}
func (s *AuthServiceImpl) parseToken(tokenString string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(s.jwtSecret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
+119
View File
@@ -0,0 +1,119 @@
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 CategoryService interface {
CreateCategory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCategoryRequest) *contract.Response
UpdateCategory(ctx context.Context, id uuid.UUID, req *contract.UpdateCategoryRequest) *contract.Response
DeleteCategory(ctx context.Context, id uuid.UUID) *contract.Response
GetCategoryByID(ctx context.Context, id uuid.UUID) *contract.Response
ListCategories(ctx context.Context, req *contract.ListCategoriesRequest) *contract.Response
}
type CategoryServiceImpl struct {
categoryProcessor processor.CategoryProcessor
}
func NewCategoryService(categoryProcessor processor.CategoryProcessor) *CategoryServiceImpl {
return &CategoryServiceImpl{
categoryProcessor: categoryProcessor,
}
}
func (s *CategoryServiceImpl) CreateCategory(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCategoryRequest) *contract.Response {
modelReq := transformer.CreateCategoryRequestToModel(apctx, req)
categoryResponse, err := s.categoryProcessor.CreateCategory(ctx, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *CategoryServiceImpl) UpdateCategory(ctx context.Context, id uuid.UUID, req *contract.UpdateCategoryRequest) *contract.Response {
modelReq := transformer.UpdateCategoryRequestToModel(req)
categoryResponse, err := s.categoryProcessor.UpdateCategory(ctx, id, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *CategoryServiceImpl) DeleteCategory(ctx context.Context, id uuid.UUID) *contract.Response {
err := s.categoryProcessor.DeleteCategory(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
return contract.BuildSuccessResponse(map[string]interface{}{
"message": "Category deleted successfully",
})
}
func (s *CategoryServiceImpl) GetCategoryByID(ctx context.Context, id uuid.UUID) *contract.Response {
categoryResponse, err := s.categoryProcessor.GetCategoryByID(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.CategoryModelResponseToResponse(categoryResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *CategoryServiceImpl) ListCategories(ctx context.Context, req *contract.ListCategoriesRequest) *contract.Response {
// Build filters
filters := make(map[string]interface{})
if req.OrganizationID != nil {
filters["organization_id"] = *req.OrganizationID
}
if req.BusinessType != "" {
filters["business_type"] = req.BusinessType
}
if req.Search != "" {
filters["search"] = req.Search
}
categories, totalCount, err := s.categoryProcessor.ListCategories(ctx, filters, req.Page, req.Limit)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
// Convert to contract responses
contractResponses := transformer.CategoriesToResponses(categories)
// Calculate total pages
totalPages := totalCount / req.Limit
if totalCount%req.Limit > 0 {
totalPages++
}
listResponse := &contract.ListCategoriesResponse{
Categories: contractResponses,
TotalCount: totalCount,
Page: req.Page,
Limit: req.Limit,
TotalPages: totalPages,
}
return contract.BuildSuccessResponse(listResponse)
}
+111
View File
@@ -0,0 +1,111 @@
package service
import (
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/processor"
"apskel-pos-be/internal/transformer"
"context"
"github.com/google/uuid"
)
type CustomerService interface {
CreateCustomer(ctx context.Context, req *contract.CreateCustomerRequest, organizationID uuid.UUID) (*contract.CustomerResponse, error)
GetCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error)
ListCustomers(ctx context.Context, query *contract.ListCustomersRequest, organizationID uuid.UUID) (*contract.PaginatedCustomerResponse, error)
UpdateCustomer(ctx context.Context, customerID, organizationID uuid.UUID, req *contract.UpdateCustomerRequest) (*contract.CustomerResponse, error)
DeleteCustomer(ctx context.Context, customerID, organizationID uuid.UUID) error
SetDefaultCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error)
GetDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error)
EnsureDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error)
}
type CustomerServiceImpl struct {
customerProcessor *processor.CustomerProcessor
}
func NewCustomerService(customerProcessor *processor.CustomerProcessor) *CustomerServiceImpl {
return &CustomerServiceImpl{
customerProcessor: customerProcessor,
}
}
func (s *CustomerServiceImpl) CreateCustomer(ctx context.Context, req *contract.CreateCustomerRequest, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
modelReq := transformer.CreateCustomerRequestToModel(req)
customerResponse, err := s.customerProcessor.CreateCustomer(ctx, modelReq, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) GetCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
customerResponse, err := s.customerProcessor.GetCustomer(ctx, customerID, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) ListCustomers(ctx context.Context, query *contract.ListCustomersRequest, organizationID uuid.UUID) (*contract.PaginatedCustomerResponse, error) {
modelQuery := transformer.ListCustomersRequestToModel(query)
customersResponse, err := s.customerProcessor.ListCustomers(ctx, modelQuery, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.PaginatedCustomerResponseToContract(customersResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) UpdateCustomer(ctx context.Context, customerID, organizationID uuid.UUID, req *contract.UpdateCustomerRequest) (*contract.CustomerResponse, error) {
modelReq := transformer.UpdateCustomerRequestToModel(req)
customerResponse, err := s.customerProcessor.UpdateCustomer(ctx, customerID, organizationID, modelReq)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) DeleteCustomer(ctx context.Context, customerID, organizationID uuid.UUID) error {
return s.customerProcessor.DeleteCustomer(ctx, customerID, organizationID)
}
func (s *CustomerServiceImpl) SetDefaultCustomer(ctx context.Context, customerID, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
customerResponse, err := s.customerProcessor.SetDefaultCustomer(ctx, customerID, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) GetDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
customerResponse, err := s.customerProcessor.GetDefaultCustomer(ctx, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
func (s *CustomerServiceImpl) EnsureDefaultCustomer(ctx context.Context, organizationID uuid.UUID) (*contract.CustomerResponse, error) {
customerResponse, err := s.customerProcessor.EnsureDefaultCustomer(ctx, organizationID)
if err != nil {
return nil, err
}
contractResponse := transformer.CustomerModelToResponse(customerResponse)
return contractResponse, nil
}
+166
View File
@@ -0,0 +1,166 @@
package service
import (
"context"
"fmt"
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/processor"
"mime/multipart"
"github.com/google/uuid"
)
type FileService interface {
UploadFile(ctx context.Context, file *multipart.FileHeader, req *models.UploadFileRequest, organizationID, userID uuid.UUID) (*models.FileResponse, error)
GetFileByID(ctx context.Context, id uuid.UUID) (*models.FileResponse, error)
UpdateFile(ctx context.Context, id uuid.UUID, req *models.UpdateFileRequest) (*models.FileResponse, error)
ListFiles(ctx context.Context, req *models.ListFilesRequest) (*models.ListFilesResponse, error)
GetFileByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]*models.FileResponse, error)
GetFileByUserID(ctx context.Context, userID uuid.UUID) ([]*models.FileResponse, error)
}
type FileServiceImpl struct {
fileProcessor processor.FileProcessor
}
func NewFileServiceImpl(fileProcessor processor.FileProcessor) *FileServiceImpl {
return &FileServiceImpl{
fileProcessor: fileProcessor,
}
}
func (s *FileServiceImpl) UploadFile(ctx context.Context, file *multipart.FileHeader, req *models.UploadFileRequest, organizationID, userID uuid.UUID) (*models.FileResponse, error) {
if err := s.validateUploadFileRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
if organizationID == uuid.Nil {
return nil, fmt.Errorf("organization ID is required")
}
if userID == uuid.Nil {
return nil, fmt.Errorf("user ID is required")
}
// Process file upload
response, err := s.fileProcessor.UploadFile(ctx, file, req, organizationID, userID)
if err != nil {
return nil, fmt.Errorf("failed to upload file: %w", err)
}
return response, nil
}
func (s *FileServiceImpl) GetFileByID(ctx context.Context, id uuid.UUID) (*models.FileResponse, error) {
if id == uuid.Nil {
return nil, fmt.Errorf("invalid file ID")
}
response, err := s.fileProcessor.GetFileByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get file: %w", err)
}
return response, nil
}
func (s *FileServiceImpl) UpdateFile(ctx context.Context, id uuid.UUID, req *models.UpdateFileRequest) (*models.FileResponse, error) {
// Validate inputs
if id == uuid.Nil {
return nil, fmt.Errorf("invalid file ID")
}
// Validate request
if err := s.validateUpdateFileRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process file update
response, err := s.fileProcessor.UpdateFile(ctx, id, req)
if err != nil {
return nil, fmt.Errorf("failed to update file: %w", err)
}
return response, nil
}
func (s *FileServiceImpl) ListFiles(ctx context.Context, req *models.ListFilesRequest) (*models.ListFilesResponse, error) {
// Validate request
if err := s.validateListFilesRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process file listing
response, err := s.fileProcessor.ListFiles(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to list files: %w", err)
}
return response, nil
}
func (s *FileServiceImpl) GetFileByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]*models.FileResponse, error) {
// Validate organization ID
if organizationID == uuid.Nil {
return nil, fmt.Errorf("invalid organization ID")
}
// Get files by organization
response, err := s.fileProcessor.GetFileByOrganizationID(ctx, organizationID)
if err != nil {
return nil, fmt.Errorf("failed to get files by organization: %w", err)
}
return response, nil
}
func (s *FileServiceImpl) GetFileByUserID(ctx context.Context, userID uuid.UUID) ([]*models.FileResponse, error) {
// Validate user ID
if userID == uuid.Nil {
return nil, fmt.Errorf("invalid user ID")
}
// Get files by user
response, err := s.fileProcessor.GetFileByUserID(ctx, userID)
if err != nil {
return nil, fmt.Errorf("failed to get files by user: %w", err)
}
return response, nil
}
// Validation methods
func (s *FileServiceImpl) validateUploadFileRequest(req *models.UploadFileRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
// File type validation is handled in the processor
return nil
}
func (s *FileServiceImpl) validateUpdateFileRequest(req *models.UpdateFileRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
// Additional validation can be added here if needed
return nil
}
func (s *FileServiceImpl) validateListFilesRequest(req *models.ListFilesRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.Page < 1 {
return fmt.Errorf("page must be greater than 0")
}
if req.Limit < 1 || req.Limit > 100 {
return fmt.Errorf("limit must be between 1 and 100")
}
return nil
}
+166
View File
@@ -0,0 +1,166 @@
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)
}
+386
View File
@@ -0,0 +1,386 @@
package service
import (
"context"
"fmt"
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/processor"
"github.com/google/uuid"
)
type OrderService interface {
CreateOrder(ctx context.Context, req *models.CreateOrderRequest, organizationID uuid.UUID) (*models.OrderResponse, error)
AddToOrder(ctx context.Context, orderID uuid.UUID, req *models.AddToOrderRequest) (*models.AddToOrderResponse, error)
UpdateOrder(ctx context.Context, id uuid.UUID, req *models.UpdateOrderRequest) (*models.OrderResponse, error)
GetOrderByID(ctx context.Context, id uuid.UUID) (*models.OrderResponse, error)
ListOrders(ctx context.Context, req *models.ListOrdersRequest) (*models.ListOrdersResponse, error)
VoidOrder(ctx context.Context, req *models.VoidOrderRequest, voidedBy uuid.UUID) error
RefundOrder(ctx context.Context, id uuid.UUID, req *models.RefundOrderRequest, refundedBy uuid.UUID) error
CreatePayment(ctx context.Context, req *models.CreatePaymentRequest) (*models.PaymentResponse, error)
RefundPayment(ctx context.Context, paymentID uuid.UUID, refundAmount float64, reason string, refundedBy uuid.UUID) error
SetOrderCustomer(ctx context.Context, orderID uuid.UUID, req *models.SetOrderCustomerRequest, organizationID uuid.UUID) (*models.SetOrderCustomerResponse, error)
}
type OrderServiceImpl struct {
orderProcessor processor.OrderProcessor
}
func NewOrderServiceImpl(orderProcessor processor.OrderProcessor) *OrderServiceImpl {
return &OrderServiceImpl{
orderProcessor: orderProcessor,
}
}
func (s *OrderServiceImpl) CreateOrder(ctx context.Context, req *models.CreateOrderRequest, organizationID uuid.UUID) (*models.OrderResponse, error) {
if err := s.validateCreateOrderRequest(req, organizationID); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
response, err := s.orderProcessor.CreateOrder(ctx, req, organizationID)
if err != nil {
return nil, fmt.Errorf("failed to create order: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) AddToOrder(ctx context.Context, orderID uuid.UUID, req *models.AddToOrderRequest) (*models.AddToOrderResponse, error) {
// Validate inputs
if orderID == uuid.Nil {
return nil, fmt.Errorf("invalid order ID")
}
// Validate request
if err := s.validateAddToOrderRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process adding items to order
response, err := s.orderProcessor.AddToOrder(ctx, orderID, req)
if err != nil {
return nil, fmt.Errorf("failed to add items to order: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) UpdateOrder(ctx context.Context, id uuid.UUID, req *models.UpdateOrderRequest) (*models.OrderResponse, error) {
// Validate request
if err := s.validateUpdateOrderRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process order update
response, err := s.orderProcessor.UpdateOrder(ctx, id, req)
if err != nil {
return nil, fmt.Errorf("failed to update order: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) GetOrderByID(ctx context.Context, id uuid.UUID) (*models.OrderResponse, error) {
if id == uuid.Nil {
return nil, fmt.Errorf("invalid order ID")
}
response, err := s.orderProcessor.GetOrderByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get order: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) ListOrders(ctx context.Context, req *models.ListOrdersRequest) (*models.ListOrdersResponse, error) {
// Validate request
if err := s.validateListOrdersRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process order listing
response, err := s.orderProcessor.ListOrders(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to list orders: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) VoidOrder(ctx context.Context, req *models.VoidOrderRequest, voidedBy uuid.UUID) error {
if req.OrderID == uuid.Nil {
return fmt.Errorf("invalid order ID")
}
if voidedBy == uuid.Nil {
return fmt.Errorf("invalid user ID")
}
if err := s.orderProcessor.VoidOrder(ctx, req, voidedBy); err != nil {
return fmt.Errorf("failed to void order: %w", err)
}
return nil
}
func (s *OrderServiceImpl) RefundOrder(ctx context.Context, id uuid.UUID, req *models.RefundOrderRequest, refundedBy uuid.UUID) error {
// Validate inputs
if id == uuid.Nil {
return fmt.Errorf("invalid order ID")
}
if refundedBy == uuid.Nil {
return fmt.Errorf("invalid user ID")
}
// Validate refund request
if err := s.validateRefundOrderRequest(req); err != nil {
return fmt.Errorf("validation error: %w", err)
}
// Process order refund
if err := s.orderProcessor.RefundOrder(ctx, id, req, refundedBy); err != nil {
return fmt.Errorf("failed to refund order: %w", err)
}
return nil
}
func (s *OrderServiceImpl) CreatePayment(ctx context.Context, req *models.CreatePaymentRequest) (*models.PaymentResponse, error) {
if err := s.validateCreatePaymentRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process payment creation
response, err := s.orderProcessor.CreatePayment(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to create payment: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) RefundPayment(ctx context.Context, paymentID uuid.UUID, refundAmount float64, reason string, refundedBy uuid.UUID) error {
// Validate inputs
if paymentID == uuid.Nil {
return fmt.Errorf("invalid payment ID")
}
if refundAmount <= 0 {
return fmt.Errorf("refund amount must be greater than zero")
}
if refundedBy == uuid.Nil {
return fmt.Errorf("invalid user ID")
}
// Process payment refund
if err := s.orderProcessor.RefundPayment(ctx, paymentID, refundAmount, reason, refundedBy); err != nil {
return fmt.Errorf("failed to refund payment: %w", err)
}
return nil
}
func (s *OrderServiceImpl) SetOrderCustomer(ctx context.Context, orderID uuid.UUID, req *models.SetOrderCustomerRequest, organizationID uuid.UUID) (*models.SetOrderCustomerResponse, error) {
// Validate inputs
if orderID == uuid.Nil {
return nil, fmt.Errorf("invalid order ID")
}
if organizationID == uuid.Nil {
return nil, fmt.Errorf("invalid organization ID")
}
// Validate request
if err := s.validateSetOrderCustomerRequest(req); err != nil {
return nil, fmt.Errorf("validation error: %w", err)
}
// Process setting customer for order
response, err := s.orderProcessor.SetOrderCustomer(ctx, orderID, req, organizationID)
if err != nil {
return nil, fmt.Errorf("failed to set customer for order: %w", err)
}
return response, nil
}
func (s *OrderServiceImpl) validateAddToOrderRequest(req *models.AddToOrderRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if len(req.OrderItems) == 0 {
return fmt.Errorf("must add at least one item")
}
for i, item := range req.OrderItems {
if item.ProductID == uuid.Nil {
return fmt.Errorf("product ID is required for item %d", i+1)
}
if item.Quantity <= 0 {
return fmt.Errorf("quantity must be greater than zero for item %d", i+1)
}
if item.UnitPrice != nil && *item.UnitPrice < 0 {
return fmt.Errorf("unit price cannot be negative for item %d", i+1)
}
}
return nil
}
func (s *OrderServiceImpl) validateCreateOrderRequest(req *models.CreateOrderRequest, organizationID uuid.UUID) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if organizationID == uuid.Nil {
return fmt.Errorf("organization ID is required")
}
if req.OutletID == uuid.Nil {
return fmt.Errorf("outlet ID is required")
}
if req.UserID == uuid.Nil {
return fmt.Errorf("user ID is required")
}
if len(req.OrderItems) == 0 {
return fmt.Errorf("order must have at least one item")
}
for i, item := range req.OrderItems {
if item.ProductID == uuid.Nil {
return fmt.Errorf("product ID is required for item %d", i+1)
}
if item.Quantity <= 0 {
return fmt.Errorf("quantity must be greater than zero for item %d", i+1)
}
if item.UnitPrice != nil && *item.UnitPrice < 0 {
return fmt.Errorf("unit price cannot be negative for item %d", i+1)
}
}
return nil
}
func (s *OrderServiceImpl) validateUpdateOrderRequest(req *models.UpdateOrderRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.DiscountAmount != nil && *req.DiscountAmount < 0 {
return fmt.Errorf("discount amount cannot be negative")
}
return nil
}
func (s *OrderServiceImpl) validateListOrdersRequest(req *models.ListOrdersRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.Page < 1 {
return fmt.Errorf("page must be greater than zero")
}
if req.Limit < 1 || req.Limit > 100 {
return fmt.Errorf("limit must be between 1 and 100")
}
return nil
}
func (s *OrderServiceImpl) validateRefundOrderRequest(req *models.RefundOrderRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
// Must have either refund amount or order items
if req.RefundAmount == nil && len(req.OrderItems) == 0 {
return fmt.Errorf("must specify either refund amount or order items to refund")
}
// Cannot have both refund amount and order items
if req.RefundAmount != nil && len(req.OrderItems) > 0 {
return fmt.Errorf("cannot specify both refund amount and order items")
}
if req.RefundAmount != nil && *req.RefundAmount <= 0 {
return fmt.Errorf("refund amount must be greater than zero")
}
// Validate order items if provided
for i, item := range req.OrderItems {
if item.OrderItemID == uuid.Nil {
return fmt.Errorf("order item ID is required for item %d", i+1)
}
if item.RefundQuantity < 0 {
return fmt.Errorf("refund quantity cannot be negative for item %d", i+1)
}
if item.RefundAmount != nil && *item.RefundAmount < 0 {
return fmt.Errorf("refund amount cannot be negative for item %d", i+1)
}
}
return nil
}
func (s *OrderServiceImpl) validateCreatePaymentRequest(req *models.CreatePaymentRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.OrderID == uuid.Nil {
return fmt.Errorf("order ID is required")
}
if req.PaymentMethodID == uuid.Nil {
return fmt.Errorf("payment method ID is required")
}
if req.Amount <= 0 {
return fmt.Errorf("payment amount must be greater than zero")
}
if len(req.PaymentOrderItems) > 0 {
totalItemAmount := float64(0)
for i, item := range req.PaymentOrderItems {
if item.OrderItemID == uuid.Nil {
return fmt.Errorf("order item ID is required for payment item %d", i+1)
}
if item.Amount <= 0 {
return fmt.Errorf("payment item amount must be greater than zero for item %d", i+1)
}
totalItemAmount += item.Amount
}
if totalItemAmount != req.Amount {
return fmt.Errorf("sum of payment item amounts must equal total payment amount")
}
}
return nil
}
func (s *OrderServiceImpl) validateSetOrderCustomerRequest(req *models.SetOrderCustomerRequest) error {
if req == nil {
return fmt.Errorf("request cannot be nil")
}
if req.CustomerID == uuid.Nil {
return fmt.Errorf("customer ID is required")
}
return nil
}
+119
View File
@@ -0,0 +1,119 @@
package service
import (
"apskel-pos-be/internal/appcontext"
"context"
"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 OrganizationService interface {
CreateOrganization(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateOrganizationRequest) *contract.Response
UpdateOrganization(ctx context.Context, id uuid.UUID, req *contract.UpdateOrganizationRequest) *contract.Response
DeleteOrganization(ctx context.Context, id uuid.UUID) *contract.Response
GetOrganizationByID(ctx context.Context, id uuid.UUID) *contract.Response
ListOrganizations(ctx context.Context, req *contract.ListOrganizationsRequest) *contract.Response
}
type OrganizationServiceImpl struct {
organizationProcessor processor.OrganizationProcessor
}
func NewOrganizationService(organizationProcessor processor.OrganizationProcessor) *OrganizationServiceImpl {
return &OrganizationServiceImpl{
organizationProcessor: organizationProcessor,
}
}
func (s *OrganizationServiceImpl) CreateOrganization(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateOrganizationRequest) *contract.Response {
modelReq := transformer.CreateOrganizationRequestToModel(req)
organizationResponse, err := s.organizationProcessor.CreateOrganization(ctx, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.CreateOrganizationResponseToContract(organizationResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OrganizationServiceImpl) UpdateOrganization(ctx context.Context, id uuid.UUID, req *contract.UpdateOrganizationRequest) *contract.Response {
modelReq := transformer.UpdateOrganizationRequestToModel(req)
organizationResponse, err := s.organizationProcessor.UpdateOrganization(ctx, id, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.OrganizationModelResponseToResponse(organizationResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OrganizationServiceImpl) DeleteOrganization(ctx context.Context, id uuid.UUID) *contract.Response {
err := s.organizationProcessor.DeleteOrganization(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
return contract.BuildSuccessResponse(map[string]interface{}{
"message": "Organization deleted successfully",
})
}
func (s *OrganizationServiceImpl) GetOrganizationByID(ctx context.Context, id uuid.UUID) *contract.Response {
organizationResponse, err := s.organizationProcessor.GetOrganizationByID(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.OrganizationModelResponseToResponse(organizationResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OrganizationServiceImpl) ListOrganizations(ctx context.Context, req *contract.ListOrganizationsRequest) *contract.Response {
filters := make(map[string]interface{})
if req.PlanType != "" {
filters["plan_type"] = req.PlanType
}
if req.Search != "" {
filters["name"] = req.Search
}
organizations, totalCount, err := s.organizationProcessor.ListOrganizations(ctx, filters, req.Page, req.Limit)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OrganizationServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponses := make([]contract.OrganizationResponse, len(organizations))
for i, org := range organizations {
response := transformer.OrganizationModelResponseToResponse(&org)
if response != nil {
contractResponses[i] = *response
}
}
totalPages := totalCount / req.Limit
if totalCount%req.Limit > 0 {
totalPages++
}
listResponse := &contract.ListOrganizationsResponse{
Organizations: contractResponses,
TotalCount: totalCount,
Page: req.Page,
Limit: req.Limit,
TotalPages: totalPages,
}
return contract.BuildSuccessResponse(listResponse)
}
+106
View File
@@ -0,0 +1,106 @@
package service
import (
"apskel-pos-be/internal/constants"
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/processor"
"apskel-pos-be/internal/transformer"
"context"
"github.com/google/uuid"
)
type OutletService interface {
ListOutlets(ctx context.Context, req *contract.ListOutletsRequest) *contract.Response
GetOutletByID(ctx context.Context, organizationID, outletID uuid.UUID) *contract.Response
CreateOutlet(ctx context.Context, req *contract.CreateOutletRequest) *contract.Response
UpdateOutlet(ctx context.Context, outletID uuid.UUID, req *contract.UpdateOutletRequest) *contract.Response
DeleteOutlet(ctx context.Context, outletID uuid.UUID) *contract.Response
}
type OutletServiceImpl struct {
outletProcessor processor.OutletProcessor
}
func NewOutletService(outletProcessor processor.OutletProcessor) *OutletServiceImpl {
return &OutletServiceImpl{
outletProcessor: outletProcessor,
}
}
func (s *OutletServiceImpl) ListOutlets(ctx context.Context, req *contract.ListOutletsRequest) *contract.Response {
// Validate request
if req.Page < 1 {
req.Page = 1
}
if req.Limit < 1 {
req.Limit = 10
}
if req.Limit > 100 {
req.Limit = 100
}
outlets, total, err := s.outletProcessor.ListOutletsByOrganization(ctx, req.OrganizationID, req.Page, req.Limit)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OutletServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractOutlets := make([]contract.OutletResponse, len(outlets))
for i, outlet := range outlets {
contractOutlets[i] = transformer.OutletModelResponseToResponse(outlet)
}
// Create paginated response
response := transformer.CreateListOutletsResponse(contractOutlets, int(total), req.Page, req.Limit)
return contract.BuildSuccessResponse(response)
}
func (s *OutletServiceImpl) GetOutletByID(ctx context.Context, organizationID, outletID uuid.UUID) *contract.Response {
outlet, err := s.outletProcessor.GetOutletByID(ctx, organizationID, outletID)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OutletServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.OutletModelResponseToResponse(outlet)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OutletServiceImpl) CreateOutlet(ctx context.Context, req *contract.CreateOutletRequest) *contract.Response {
modelReq := transformer.CreateOutletRequestToModel(req)
outlet, err := s.outletProcessor.CreateOutlet(ctx, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OutletServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.OutletModelResponseToResponse(outlet)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OutletServiceImpl) UpdateOutlet(ctx context.Context, outletID uuid.UUID, req *contract.UpdateOutletRequest) *contract.Response {
modelReq := transformer.UpdateOutletRequestToModel(req)
outlet, err := s.outletProcessor.UpdateOutlet(ctx, outletID, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OutletServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.OutletModelResponseToResponse(outlet)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *OutletServiceImpl) DeleteOutlet(ctx context.Context, outletID uuid.UUID) *contract.Response {
err := s.outletProcessor.DeleteOutlet(ctx, outletID)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.OutletServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
return contract.BuildSuccessResponse(map[string]interface{}{
"message": "Outlet deleted successfully",
})
}
@@ -0,0 +1,52 @@
package service
import (
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/processor"
"context"
"github.com/google/uuid"
)
type OutletSettingService interface {
CreateSetting(ctx context.Context, req *models.CreateOutletSettingRequest) (*models.OutletSettingResponse, error)
UpdateSetting(ctx context.Context, outletID uuid.UUID, key string, req *models.UpdateOutletSettingRequest) (*models.OutletSettingResponse, error)
GetSetting(ctx context.Context, outletID uuid.UUID, key string) (*models.OutletSettingResponse, error)
GetPrinterSettings(ctx context.Context, outletID uuid.UUID) (*models.OutletPrinterSettings, error)
UpdatePrinterSettings(ctx context.Context, outletID uuid.UUID, req *models.UpdateOutletPrinterSettingsRequest) (*models.OutletPrinterSettings, error)
DeleteSetting(ctx context.Context, outletID uuid.UUID, key string) error
}
type OutletSettingServiceImpl struct {
outletSettingProcessor *processor.OutletSettingProcessorImpl
}
func NewOutletSettingService(outletSettingProcessor *processor.OutletSettingProcessorImpl) OutletSettingService {
return &OutletSettingServiceImpl{
outletSettingProcessor: outletSettingProcessor,
}
}
func (s *OutletSettingServiceImpl) CreateSetting(ctx context.Context, req *models.CreateOutletSettingRequest) (*models.OutletSettingResponse, error) {
return s.outletSettingProcessor.CreateSetting(ctx, req)
}
func (s *OutletSettingServiceImpl) UpdateSetting(ctx context.Context, outletID uuid.UUID, key string, req *models.UpdateOutletSettingRequest) (*models.OutletSettingResponse, error) {
return s.outletSettingProcessor.UpdateSetting(ctx, outletID, key, req)
}
func (s *OutletSettingServiceImpl) GetSetting(ctx context.Context, outletID uuid.UUID, key string) (*models.OutletSettingResponse, error) {
return s.outletSettingProcessor.GetSetting(ctx, outletID, key)
}
func (s *OutletSettingServiceImpl) GetPrinterSettings(ctx context.Context, outletID uuid.UUID) (*models.OutletPrinterSettings, error) {
return s.outletSettingProcessor.GetPrinterSettings(ctx, outletID)
}
func (s *OutletSettingServiceImpl) UpdatePrinterSettings(ctx context.Context, outletID uuid.UUID, req *models.UpdateOutletPrinterSettingsRequest) (*models.OutletPrinterSettings, error) {
return s.outletSettingProcessor.UpdatePrinterSettings(ctx, outletID, req)
}
func (s *OutletSettingServiceImpl) DeleteSetting(ctx context.Context, outletID uuid.UUID, key string) error {
return s.outletSettingProcessor.DeleteSetting(ctx, outletID, key)
}
+130
View File
@@ -0,0 +1,130 @@
package service
import (
"context"
"apskel-pos-be/internal/appcontext"
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/mappers"
"apskel-pos-be/internal/processor"
"github.com/google/uuid"
)
type PaymentMethodService interface {
CreatePaymentMethod(ctx context.Context, contextInfo *appcontext.ContextInfo, req *contract.CreatePaymentMethodRequest) *contract.Response
GetPaymentMethodByID(ctx context.Context, id uuid.UUID) *contract.Response
ListPaymentMethods(ctx context.Context, req *contract.ListPaymentMethodsRequest) *contract.Response
UpdatePaymentMethod(ctx context.Context, id uuid.UUID, req *contract.UpdatePaymentMethodRequest) *contract.Response
DeletePaymentMethod(ctx context.Context, id uuid.UUID) *contract.Response
GetActivePaymentMethodsByOrganization(ctx context.Context, organizationID uuid.UUID) *contract.Response
}
type PaymentMethodServiceImpl struct {
paymentMethodProcessor processor.PaymentMethodProcessor
}
func NewPaymentMethodService(paymentMethodProcessor processor.PaymentMethodProcessor) PaymentMethodService {
return &PaymentMethodServiceImpl{
paymentMethodProcessor: paymentMethodProcessor,
}
}
func (s *PaymentMethodServiceImpl) CreatePaymentMethod(ctx context.Context, contextInfo *appcontext.ContextInfo, req *contract.CreatePaymentMethodRequest) *contract.Response {
// Convert contract to model
modelReq := mappers.CreatePaymentMethodContractToModel(req)
// Set organization ID from context if not provided
if modelReq.OrganizationID == uuid.Nil && contextInfo != nil {
modelReq.OrganizationID = contextInfo.OrganizationID
}
// Process request
response, err := s.paymentMethodProcessor.CreatePaymentMethod(ctx, modelReq)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_CREATE_ERROR", "payment_method", err.Error()),
})
}
// Convert model to contract
contractResponse := mappers.PaymentMethodResponseToContract(response)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *PaymentMethodServiceImpl) GetPaymentMethodByID(ctx context.Context, id uuid.UUID) *contract.Response {
response, err := s.paymentMethodProcessor.GetPaymentMethodByID(ctx, id)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_NOT_FOUND", "payment_method", err.Error()),
})
}
contractResponse := mappers.PaymentMethodResponseToContract(response)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *PaymentMethodServiceImpl) ListPaymentMethods(ctx context.Context, req *contract.ListPaymentMethodsRequest) *contract.Response {
// Convert contract to model
modelReq := mappers.ListPaymentMethodsContractToModel(req)
// Process request
response, err := s.paymentMethodProcessor.ListPaymentMethods(ctx, modelReq)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_LIST_ERROR", "payment_method", err.Error()),
})
}
// Convert model to contract
contractResponse := mappers.ListPaymentMethodsResponseToContract(response)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *PaymentMethodServiceImpl) UpdatePaymentMethod(ctx context.Context, id uuid.UUID, req *contract.UpdatePaymentMethodRequest) *contract.Response {
// Convert contract to model
modelReq := mappers.UpdatePaymentMethodContractToModel(req)
// Process request
response, err := s.paymentMethodProcessor.UpdatePaymentMethod(ctx, id, modelReq)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_UPDATE_ERROR", "payment_method", err.Error()),
})
}
// Convert model to contract
contractResponse := mappers.PaymentMethodResponseToContract(response)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *PaymentMethodServiceImpl) DeletePaymentMethod(ctx context.Context, id uuid.UUID) *contract.Response {
err := s.paymentMethodProcessor.DeletePaymentMethod(ctx, id)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_DELETE_ERROR", "payment_method", err.Error()),
})
}
return contract.BuildSuccessResponse(map[string]string{"message": "Payment method deleted successfully"})
}
func (s *PaymentMethodServiceImpl) GetActivePaymentMethodsByOrganization(ctx context.Context, organizationID uuid.UUID) *contract.Response {
responses, err := s.paymentMethodProcessor.GetActivePaymentMethodsByOrganization(ctx, organizationID)
if err != nil {
return contract.BuildErrorResponse([]*contract.ResponseError{
contract.NewResponseError("PAYMENT_METHOD_LIST_ERROR", "payment_method", err.Error()),
})
}
// Convert models to contracts
contractResponses := make([]contract.PaymentMethodResponse, len(responses))
for i, response := range responses {
contractResponse := mappers.PaymentMethodResponseToContract(&response)
if contractResponse != nil {
contractResponses[i] = *contractResponse
}
}
return contract.BuildSuccessResponse(contractResponses)
}
+131
View File
@@ -0,0 +1,131 @@
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 ProductService interface {
CreateProduct(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductRequest) *contract.Response
UpdateProduct(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRequest) *contract.Response
DeleteProduct(ctx context.Context, id uuid.UUID) *contract.Response
GetProductByID(ctx context.Context, id uuid.UUID) *contract.Response
ListProducts(ctx context.Context, req *contract.ListProductsRequest) *contract.Response
}
type ProductServiceImpl struct {
productProcessor processor.ProductProcessor
}
func NewProductService(productProcessor processor.ProductProcessor) *ProductServiceImpl {
return &ProductServiceImpl{
productProcessor: productProcessor,
}
}
func (s *ProductServiceImpl) CreateProduct(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductRequest) *contract.Response {
modelReq := transformer.CreateProductRequestToModel(apctx, req)
productResponse, err := s.productProcessor.CreateProduct(ctx, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductModelResponseToResponse(productResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductServiceImpl) UpdateProduct(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRequest) *contract.Response {
modelReq := transformer.UpdateProductRequestToModel(req)
productResponse, err := s.productProcessor.UpdateProduct(ctx, id, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductModelResponseToResponse(productResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductServiceImpl) DeleteProduct(ctx context.Context, id uuid.UUID) *contract.Response {
err := s.productProcessor.DeleteProduct(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
return contract.BuildSuccessResponse(map[string]interface{}{
"message": "Product deleted successfully",
})
}
func (s *ProductServiceImpl) GetProductByID(ctx context.Context, id uuid.UUID) *contract.Response {
productResponse, err := s.productProcessor.GetProductByID(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductModelResponseToResponse(productResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductServiceImpl) ListProducts(ctx context.Context, req *contract.ListProductsRequest) *contract.Response {
// Build filters
filters := make(map[string]interface{})
if req.OrganizationID != nil {
filters["organization_id"] = *req.OrganizationID
}
if req.CategoryID != nil {
filters["category_id"] = *req.CategoryID
}
if req.BusinessType != "" {
filters["business_type"] = req.BusinessType
}
if req.IsActive != nil {
filters["is_active"] = *req.IsActive
}
if req.Search != "" {
filters["search"] = req.Search
}
if req.MinPrice != nil {
filters["price_min"] = *req.MinPrice
}
if req.MaxPrice != nil {
filters["price_max"] = *req.MaxPrice
}
products, totalCount, err := s.productProcessor.ListProducts(ctx, filters, req.Page, req.Limit)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
// Convert to contract responses
contractResponses := transformer.ProductsToResponses(products)
// Calculate total pages
totalPages := totalCount / req.Limit
if totalCount%req.Limit > 0 {
totalPages++
}
listResponse := &contract.ListProductsResponse{
Products: contractResponses,
TotalCount: totalCount,
Page: req.Page,
Limit: req.Limit,
TotalPages: totalPages,
}
return contract.BuildSuccessResponse(listResponse)
}
@@ -0,0 +1,91 @@
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 ProductVariantService interface {
CreateProductVariant(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductVariantRequest) *contract.Response
UpdateProductVariant(ctx context.Context, id uuid.UUID, req *contract.UpdateProductVariantRequest) *contract.Response
DeleteProductVariant(ctx context.Context, id uuid.UUID) *contract.Response
GetProductVariantByID(ctx context.Context, id uuid.UUID) *contract.Response
GetProductVariantsByProductID(ctx context.Context, productID uuid.UUID) *contract.Response
}
type ProductVariantServiceImpl struct {
productVariantProcessor processor.ProductVariantProcessor
}
func NewProductVariantService(productVariantProcessor processor.ProductVariantProcessor) *ProductVariantServiceImpl {
return &ProductVariantServiceImpl{
productVariantProcessor: productVariantProcessor,
}
}
func (s *ProductVariantServiceImpl) CreateProductVariant(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateProductVariantRequest) *contract.Response {
modelReq := transformer.CreateProductVariantRequestToModel(req)
variantResponse, err := s.productVariantProcessor.CreateProductVariant(ctx, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductVariantServiceImpl) UpdateProductVariant(ctx context.Context, id uuid.UUID, req *contract.UpdateProductVariantRequest) *contract.Response {
modelReq := transformer.UpdateProductVariantRequestToModel(req)
variantResponse, err := s.productVariantProcessor.UpdateProductVariant(ctx, id, modelReq)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductVariantServiceImpl) DeleteProductVariant(ctx context.Context, id uuid.UUID) *contract.Response {
err := s.productVariantProcessor.DeleteProductVariant(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
return contract.BuildSuccessResponse(map[string]interface{}{
"message": "Product variant deleted successfully",
})
}
func (s *ProductVariantServiceImpl) GetProductVariantByID(ctx context.Context, id uuid.UUID) *contract.Response {
variantResponse, err := s.productVariantProcessor.GetProductVariantByID(ctx, id)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponse := transformer.ProductVariantModelResponseToResponse(variantResponse)
return contract.BuildSuccessResponse(contractResponse)
}
func (s *ProductVariantServiceImpl) GetProductVariantsByProductID(ctx context.Context, productID uuid.UUID) *contract.Response {
variants, err := s.productVariantProcessor.GetProductVariantsByProductID(ctx, productID)
if err != nil {
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductVariantServiceEntity, err.Error())
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
}
contractResponses := transformer.ProductVariantsToResponses(variants)
return contract.BuildSuccessResponse(contractResponses)
}
+22
View File
@@ -0,0 +1,22 @@
package service
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
"context"
"github.com/google/uuid"
)
type UserProcessor interface {
UpdateUser(ctx context.Context, id uuid.UUID, req *models.UpdateUserRequest) (*models.UserResponse, error)
CreateUser(ctx context.Context, req *models.CreateUserRequest) (*models.UserResponse, error)
DeleteUser(ctx context.Context, id uuid.UUID) error
GetUserByID(ctx context.Context, id uuid.UUID) (*models.UserResponse, error)
GetUserByEmail(ctx context.Context, email string) (*models.UserResponse, error)
ListUsers(ctx context.Context, organizationID uuid.UUID, page, limit int) ([]models.UserResponse, int, error)
GetUserEntityByEmail(ctx context.Context, email string) (*entities.User, error)
ChangePassword(ctx context.Context, userID uuid.UUID, req *models.ChangePasswordRequest) error
ActivateUser(ctx context.Context, userID uuid.UUID) error
DeactivateUser(ctx context.Context, userID uuid.UUID) error
}
+101
View File
@@ -0,0 +1,101 @@
package service
import (
"context"
"apskel-pos-be/internal/contract"
"apskel-pos-be/internal/transformer"
"github.com/google/uuid"
)
type UserServiceImpl struct {
userProcessor UserProcessor
}
func NewUserService(userProcessor UserProcessor) *UserServiceImpl {
return &UserServiceImpl{
userProcessor: userProcessor,
}
}
func (s *UserServiceImpl) CreateUser(ctx context.Context, req *contract.CreateUserRequest) (*contract.UserResponse, error) {
modelReq := transformer.CreateUserRequestToModel(req)
userResponse, err := s.userProcessor.CreateUser(ctx, modelReq)
if err != nil {
return nil, err
}
contractResponse := transformer.UserModelResponseToResponse(userResponse)
return contractResponse, nil
}
func (s *UserServiceImpl) UpdateUser(ctx context.Context, id uuid.UUID, req *contract.UpdateUserRequest) (*contract.UserResponse, error) {
modelReq := transformer.UpdateUserRequestToModel(req)
userResponse, err := s.userProcessor.UpdateUser(ctx, id, modelReq)
if err != nil {
return nil, err
}
contractResponse := transformer.UserModelResponseToResponse(userResponse)
return contractResponse, nil
}
func (s *UserServiceImpl) DeleteUser(ctx context.Context, id uuid.UUID) error {
return s.userProcessor.DeleteUser(ctx, id)
}
func (s *UserServiceImpl) GetUserByID(ctx context.Context, id uuid.UUID) (*contract.UserResponse, error) {
userResponse, err := s.userProcessor.GetUserByID(ctx, id)
if err != nil {
return nil, err
}
contractResponse := transformer.UserModelResponseToResponse(userResponse)
return contractResponse, nil
}
func (s *UserServiceImpl) GetUserByEmail(ctx context.Context, email string) (*contract.UserResponse, error) {
userResponse, err := s.userProcessor.GetUserByEmail(ctx, email)
if err != nil {
return nil, err
}
contractResponse := transformer.UserModelResponseToResponse(userResponse)
return contractResponse, nil
}
func (s *UserServiceImpl) ListUsers(ctx context.Context, req *contract.ListUsersRequest) (*contract.ListUsersResponse, error) {
page, limit := transformer.PaginationToRequest(req.Page, req.Limit)
organizationID := uuid.New()
userResponses, totalCount, err := s.userProcessor.ListUsers(ctx, organizationID, page, limit)
if err != nil {
return nil, err
}
contractResponses := transformer.UserResponsesToResponses(userResponses)
response := transformer.CreateListUsersResponse(contractResponses, totalCount, page, limit)
return response, nil
}
func (s *UserServiceImpl) ChangePassword(ctx context.Context, userID uuid.UUID, req *contract.ChangePasswordRequest) error {
modelReq := transformer.ChangePasswordRequestToModel(req)
return s.userProcessor.ChangePassword(ctx, userID, modelReq)
}
func (s *UserServiceImpl) ActivateUser(ctx context.Context, userID uuid.UUID) error {
return s.userProcessor.ActivateUser(ctx, userID)
}
func (s *UserServiceImpl) DeactivateUser(ctx context.Context, userID uuid.UUID) error {
return s.userProcessor.DeactivateUser(ctx, userID)
}