2025-07-18 20:10:29 +07:00
package app
import (
"apskel-pos-be/internal/client"
2025-08-03 00:34:25 +07:00
"apskel-pos-be/internal/transformer"
2025-07-18 20:10:29 +07:00
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"apskel-pos-be/config"
"apskel-pos-be/internal/handler"
"apskel-pos-be/internal/middleware"
"apskel-pos-be/internal/processor"
"apskel-pos-be/internal/repository"
"apskel-pos-be/internal/router"
"apskel-pos-be/internal/service"
"apskel-pos-be/internal/validator"
"gorm.io/gorm"
)
type App struct {
server * http . Server
db * gorm . DB
router * router . Router
shutdown chan os . Signal
}
func NewApp ( db * gorm . DB ) * App {
return & App {
db : db ,
shutdown : make ( chan os . Signal , 1 ) ,
}
}
func ( a * App ) Initialize ( cfg * config . Config ) error {
repos := a . initRepositories ( )
processors := a . initProcessors ( cfg , repos )
2025-08-08 00:22:28 +07:00
services := a . initServices ( processors , repos , cfg )
2025-07-18 20:10:29 +07:00
validators := a . initValidators ( )
middleware := a . initMiddleware ( services )
healthHandler := handler . NewHealthHandler ( )
a . router = router . NewRouter (
cfg ,
healthHandler ,
services . authService ,
middleware . authMiddleware ,
services . userService ,
validators . userValidator ,
services . organizationService ,
validators . organizationValidator ,
services . outletService ,
validators . outletValidator ,
services . outletSettingService ,
services . categoryService ,
validators . categoryValidator ,
services . productService ,
validators . productValidator ,
services . productVariantService ,
validators . productVariantValidator ,
services . inventoryService ,
validators . inventoryValidator ,
services . orderService ,
validators . orderValidator ,
services . fileService ,
validators . fileValidator ,
services . customerService ,
validators . customerValidator ,
services . paymentMethodService ,
validators . paymentMethodValidator ,
services . analyticsService ,
2025-08-10 20:41:34 +07:00
services . reportService ,
2025-07-30 23:18:20 +07:00
services . tableService ,
2025-08-03 00:34:25 +07:00
validators . tableValidator ,
2025-08-03 23:55:51 +07:00
services . unitService ,
services . ingredientService ,
2025-08-10 21:46:44 +07:00
services . productRecipeService ,
2025-09-12 01:12:11 +07:00
services . vendorService ,
validators . vendorValidator ,
services . purchaseOrderService ,
validators . purchaseOrderValidator ,
services . unitConverterService ,
validators . unitConverterValidator ,
services . chartOfAccountTypeService ,
validators . chartOfAccountTypeValidator ,
services . chartOfAccountService ,
validators . chartOfAccountValidator ,
services . accountService ,
validators . accountValidator ,
2025-09-12 15:37:19 +07:00
* services . orderIngredientTransactionService ,
validators . orderIngredientTransactionValidator ,
2025-07-18 20:10:29 +07:00
)
return nil
}
func ( a * App ) Start ( port string ) error {
engine := a . router . Init ( )
a . server = & http . Server {
Addr : ":" + port ,
Handler : engine ,
ReadTimeout : 15 * time . Second ,
WriteTimeout : 15 * time . Second ,
IdleTimeout : 60 * time . Second ,
}
signal . Notify ( a . shutdown , os . Interrupt , syscall . SIGTERM )
go func ( ) {
log . Printf ( "Server starting on port %s" , port )
if err := a . server . ListenAndServe ( ) ; err != nil && err != http . ErrServerClosed {
log . Fatalf ( "Failed to start server: %v" , err )
}
} ( )
<- a . shutdown
log . Println ( "Shutting down server..." )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
if err := a . server . Shutdown ( ctx ) ; err != nil {
log . Printf ( "Server forced to shutdown: %v" , err )
return err
}
log . Println ( "Server exited gracefully" )
return nil
}
func ( a * App ) Shutdown ( ) {
close ( a . shutdown )
}
type repositories struct {
2025-09-12 15:37:19 +07:00
userRepo * repository . UserRepositoryImpl
organizationRepo * repository . OrganizationRepositoryImpl
outletRepo * repository . OutletRepositoryImpl
outletSettingRepo * repository . OutletSettingRepositoryImpl
categoryRepo * repository . CategoryRepositoryImpl
productRepo * repository . ProductRepositoryImpl
productVariantRepo * repository . ProductVariantRepositoryImpl
inventoryRepo * repository . InventoryRepositoryImpl
inventoryMovementRepo * repository . InventoryMovementRepositoryImpl
orderRepo * repository . OrderRepositoryImpl
orderItemRepo * repository . OrderItemRepositoryImpl
paymentRepo * repository . PaymentRepositoryImpl
paymentOrderItemRepo * repository . PaymentOrderItemRepositoryImpl
paymentMethodRepo * repository . PaymentMethodRepositoryImpl
fileRepo * repository . FileRepositoryImpl
customerRepo * repository . CustomerRepository
analyticsRepo * repository . AnalyticsRepositoryImpl
tableRepo * repository . TableRepository
unitRepo * repository . UnitRepository
ingredientRepo * repository . IngredientRepository
productRecipeRepo * repository . ProductRecipeRepository
vendorRepo * repository . VendorRepositoryImpl
purchaseOrderRepo * repository . PurchaseOrderRepositoryImpl
unitConverterRepo * repository . IngredientUnitConverterRepositoryImpl
chartOfAccountTypeRepo * repository . ChartOfAccountTypeRepositoryImpl
chartOfAccountRepo * repository . ChartOfAccountRepositoryImpl
accountRepo * repository . AccountRepositoryImpl
orderIngredientTransactionRepo * repository . OrderIngredientTransactionRepositoryImpl
txManager * repository . TxManager
2025-07-18 20:10:29 +07:00
}
func ( a * App ) initRepositories ( ) * repositories {
return & repositories {
2025-09-12 15:37:19 +07:00
userRepo : repository . NewUserRepository ( a . db ) ,
organizationRepo : repository . NewOrganizationRepositoryImpl ( a . db ) ,
outletRepo : repository . NewOutletRepositoryImpl ( a . db ) ,
outletSettingRepo : repository . NewOutletSettingRepositoryImpl ( a . db ) ,
categoryRepo : repository . NewCategoryRepositoryImpl ( a . db ) ,
productRepo : repository . NewProductRepositoryImpl ( a . db ) ,
productVariantRepo : repository . NewProductVariantRepositoryImpl ( a . db ) ,
inventoryRepo : repository . NewInventoryRepositoryImpl ( a . db ) ,
inventoryMovementRepo : repository . NewInventoryMovementRepositoryImpl ( a . db ) ,
orderRepo : repository . NewOrderRepositoryImpl ( a . db ) ,
orderItemRepo : repository . NewOrderItemRepositoryImpl ( a . db ) ,
paymentRepo : repository . NewPaymentRepositoryImpl ( a . db ) ,
paymentOrderItemRepo : repository . NewPaymentOrderItemRepositoryImpl ( a . db ) ,
paymentMethodRepo : repository . NewPaymentMethodRepositoryImpl ( a . db ) ,
fileRepo : repository . NewFileRepositoryImpl ( a . db ) ,
customerRepo : repository . NewCustomerRepository ( a . db ) ,
analyticsRepo : repository . NewAnalyticsRepositoryImpl ( a . db ) ,
tableRepo : repository . NewTableRepository ( a . db ) ,
unitRepo : repository . NewUnitRepository ( a . db ) ,
ingredientRepo : repository . NewIngredientRepository ( a . db ) ,
productRecipeRepo : repository . NewProductRecipeRepository ( a . db ) ,
vendorRepo : repository . NewVendorRepositoryImpl ( a . db ) ,
purchaseOrderRepo : repository . NewPurchaseOrderRepositoryImpl ( a . db ) ,
unitConverterRepo : repository . NewIngredientUnitConverterRepositoryImpl ( a . db ) . ( * repository . IngredientUnitConverterRepositoryImpl ) ,
chartOfAccountTypeRepo : repository . NewChartOfAccountTypeRepositoryImpl ( a . db ) ,
chartOfAccountRepo : repository . NewChartOfAccountRepositoryImpl ( a . db ) ,
accountRepo : repository . NewAccountRepositoryImpl ( a . db ) ,
orderIngredientTransactionRepo : repository . NewOrderIngredientTransactionRepositoryImpl ( a . db ) . ( * repository . OrderIngredientTransactionRepositoryImpl ) ,
txManager : repository . NewTxManager ( a . db ) ,
2025-07-18 20:10:29 +07:00
}
}
type processors struct {
2025-09-12 15:37:19 +07:00
userProcessor * processor . UserProcessorImpl
organizationProcessor processor . OrganizationProcessor
outletProcessor processor . OutletProcessor
outletSettingProcessor * processor . OutletSettingProcessorImpl
categoryProcessor processor . CategoryProcessor
productProcessor processor . ProductProcessor
productVariantProcessor processor . ProductVariantProcessor
inventoryProcessor processor . InventoryProcessor
orderProcessor processor . OrderProcessor
paymentMethodProcessor processor . PaymentMethodProcessor
fileProcessor processor . FileProcessor
customerProcessor * processor . CustomerProcessor
analyticsProcessor * processor . AnalyticsProcessorImpl
tableProcessor * processor . TableProcessor
unitProcessor * processor . UnitProcessorImpl
ingredientProcessor * processor . IngredientProcessorImpl
productRecipeProcessor * processor . ProductRecipeProcessorImpl
vendorProcessor * processor . VendorProcessorImpl
purchaseOrderProcessor * processor . PurchaseOrderProcessorImpl
unitConverterProcessor * processor . IngredientUnitConverterProcessorImpl
chartOfAccountTypeProcessor * processor . ChartOfAccountTypeProcessorImpl
chartOfAccountProcessor * processor . ChartOfAccountProcessorImpl
accountProcessor * processor . AccountProcessorImpl
orderIngredientTransactionProcessor * processor . OrderIngredientTransactionProcessorImpl
fileClient processor . FileClient
inventoryMovementService service . InventoryMovementService
2025-07-18 20:10:29 +07:00
}
func ( a * App ) initProcessors ( cfg * config . Config , repos * repositories ) * processors {
fileClient := client . NewFileClient ( cfg . S3Config )
2025-08-13 23:14:26 +07:00
inventoryMovementService := service . NewInventoryMovementService ( repos . inventoryMovementRepo , repos . ingredientRepo )
2025-07-18 20:10:29 +07:00
return & processors {
2025-09-12 15:37:19 +07:00
userProcessor : processor . NewUserProcessor ( repos . userRepo , repos . organizationRepo , repos . outletRepo ) ,
organizationProcessor : processor . NewOrganizationProcessorImpl ( repos . organizationRepo , repos . outletRepo , repos . userRepo ) ,
outletProcessor : processor . NewOutletProcessorImpl ( repos . outletRepo ) ,
outletSettingProcessor : processor . NewOutletSettingProcessorImpl ( repos . outletSettingRepo , repos . outletRepo ) ,
categoryProcessor : processor . NewCategoryProcessorImpl ( repos . categoryRepo ) ,
productProcessor : processor . NewProductProcessorImpl ( repos . productRepo , repos . categoryRepo , repos . productVariantRepo , repos . inventoryRepo , repos . outletRepo ) ,
productVariantProcessor : processor . NewProductVariantProcessorImpl ( repos . productVariantRepo , repos . productRepo ) ,
inventoryProcessor : processor . NewInventoryProcessorImpl ( repos . inventoryRepo , repos . productRepo , repos . outletRepo , repos . ingredientRepo , repos . inventoryMovementRepo ) ,
orderProcessor : processor . NewOrderProcessorImpl ( repos . orderRepo , repos . orderItemRepo , repos . paymentRepo , repos . paymentOrderItemRepo , repos . productRepo , repos . paymentMethodRepo , repos . inventoryRepo , repos . inventoryMovementRepo , repos . productVariantRepo , repos . outletRepo , repos . customerRepo , repos . txManager , repos . productRecipeRepo , repos . ingredientRepo , inventoryMovementService ) ,
paymentMethodProcessor : processor . NewPaymentMethodProcessorImpl ( repos . paymentMethodRepo ) ,
fileProcessor : processor . NewFileProcessorImpl ( repos . fileRepo , fileClient ) ,
customerProcessor : processor . NewCustomerProcessor ( repos . customerRepo ) ,
analyticsProcessor : processor . NewAnalyticsProcessorImpl ( repos . analyticsRepo ) ,
tableProcessor : processor . NewTableProcessor ( repos . tableRepo , repos . orderRepo ) ,
unitProcessor : processor . NewUnitProcessor ( repos . unitRepo ) ,
ingredientProcessor : processor . NewIngredientProcessor ( repos . ingredientRepo , repos . unitRepo ) ,
productRecipeProcessor : processor . NewProductRecipeProcessor ( repos . productRecipeRepo , repos . productRepo , repos . ingredientRepo ) ,
vendorProcessor : processor . NewVendorProcessorImpl ( repos . vendorRepo ) ,
purchaseOrderProcessor : processor . NewPurchaseOrderProcessorImpl ( repos . purchaseOrderRepo , repos . vendorRepo , repos . ingredientRepo , repos . unitRepo , repos . fileRepo , inventoryMovementService , repos . unitConverterRepo ) ,
unitConverterProcessor : processor . NewIngredientUnitConverterProcessorImpl ( repos . unitConverterRepo , repos . ingredientRepo , repos . unitRepo ) ,
chartOfAccountTypeProcessor : processor . NewChartOfAccountTypeProcessorImpl ( repos . chartOfAccountTypeRepo ) ,
chartOfAccountProcessor : processor . NewChartOfAccountProcessorImpl ( repos . chartOfAccountRepo , repos . chartOfAccountTypeRepo ) ,
accountProcessor : processor . NewAccountProcessorImpl ( repos . accountRepo , repos . chartOfAccountRepo ) ,
2025-09-13 02:17:51 +07:00
orderIngredientTransactionProcessor : processor . NewOrderIngredientTransactionProcessorImpl ( repos . orderIngredientTransactionRepo , repos . productRecipeRepo , repos . ingredientRepo , repos . unitRepo ) . ( * processor . OrderIngredientTransactionProcessorImpl ) ,
2025-09-12 15:37:19 +07:00
fileClient : fileClient ,
inventoryMovementService : inventoryMovementService ,
2025-07-18 20:10:29 +07:00
}
}
type services struct {
2025-09-12 15:37:19 +07:00
userService * service . UserServiceImpl
authService service . AuthService
organizationService service . OrganizationService
outletService service . OutletService
outletSettingService service . OutletSettingService
categoryService service . CategoryService
productService service . ProductService
productVariantService service . ProductVariantService
inventoryService service . InventoryService
orderService service . OrderService
paymentMethodService service . PaymentMethodService
fileService service . FileService
customerService service . CustomerService
analyticsService * service . AnalyticsServiceImpl
reportService service . ReportService
tableService * service . TableServiceImpl
unitService * service . UnitServiceImpl
ingredientService * service . IngredientServiceImpl
productRecipeService * service . ProductRecipeServiceImpl
vendorService * service . VendorServiceImpl
purchaseOrderService * service . PurchaseOrderServiceImpl
unitConverterService * service . IngredientUnitConverterServiceImpl
chartOfAccountTypeService service . ChartOfAccountTypeService
chartOfAccountService service . ChartOfAccountService
accountService service . AccountService
orderIngredientTransactionService * service . OrderIngredientTransactionService
2025-07-18 20:10:29 +07:00
}
2025-08-08 00:22:28 +07:00
func ( a * App ) initServices ( processors * processors , repos * repositories , cfg * config . Config ) * services {
2025-07-18 20:10:29 +07:00
authConfig := cfg . Auth ( )
jwtSecret := authConfig . AccessTokenSecret ( )
authService := service . NewAuthService ( processors . userProcessor , jwtSecret )
organizationService := service . NewOrganizationService ( processors . organizationProcessor )
outletService := service . NewOutletService ( processors . outletProcessor )
outletSettingService := service . NewOutletSettingService ( processors . outletSettingProcessor )
categoryService := service . NewCategoryService ( processors . categoryProcessor )
productService := service . NewProductService ( processors . productProcessor )
productVariantService := service . NewProductVariantService ( processors . productVariantProcessor )
inventoryService := service . NewInventoryService ( processors . inventoryProcessor )
2025-09-13 02:17:51 +07:00
orderService := service . NewOrderServiceImpl ( processors . orderProcessor , repos . tableRepo , nil , processors . orderIngredientTransactionProcessor , * repos . productRecipeRepo , repos . txManager ) // Will be updated after orderIngredientTransactionService is created
2025-07-18 20:10:29 +07:00
paymentMethodService := service . NewPaymentMethodService ( processors . paymentMethodProcessor )
fileService := service . NewFileServiceImpl ( processors . fileProcessor )
var customerService service . CustomerService = service . NewCustomerService ( processors . customerProcessor )
analyticsService := service . NewAnalyticsServiceImpl ( processors . analyticsProcessor )
2025-08-10 20:41:34 +07:00
reportService := service . NewReportService ( analyticsService , repos . organizationRepo , repos . outletRepo , processors . fileClient )
2025-07-30 23:18:20 +07:00
tableService := service . NewTableService ( processors . tableProcessor , transformer . NewTableTransformer ( ) )
2025-08-03 23:55:51 +07:00
unitService := service . NewUnitService ( processors . unitProcessor )
ingredientService := service . NewIngredientService ( processors . ingredientProcessor )
2025-08-10 21:46:44 +07:00
productRecipeService := service . NewProductRecipeService ( processors . productRecipeProcessor )
2025-09-12 01:12:11 +07:00
vendorService := service . NewVendorService ( processors . vendorProcessor )
purchaseOrderService := service . NewPurchaseOrderService ( processors . purchaseOrderProcessor )
unitConverterService := service . NewIngredientUnitConverterService ( processors . unitConverterProcessor )
chartOfAccountTypeService := service . NewChartOfAccountTypeService ( processors . chartOfAccountTypeProcessor )
chartOfAccountService := service . NewChartOfAccountService ( processors . chartOfAccountProcessor )
accountService := service . NewAccountService ( processors . accountProcessor )
2025-09-12 15:37:19 +07:00
orderIngredientTransactionService := service . NewOrderIngredientTransactionService ( processors . orderIngredientTransactionProcessor , repos . txManager )
// Update order service with order ingredient transaction service
2025-09-13 02:17:51 +07:00
orderService = service . NewOrderServiceImpl ( processors . orderProcessor , repos . tableRepo , orderIngredientTransactionService , processors . orderIngredientTransactionProcessor , * repos . productRecipeRepo , repos . txManager )
2025-07-18 20:10:29 +07:00
return & services {
2025-09-12 15:37:19 +07:00
userService : service . NewUserService ( processors . userProcessor ) ,
authService : authService ,
organizationService : organizationService ,
outletService : outletService ,
outletSettingService : outletSettingService ,
categoryService : categoryService ,
productService : productService ,
productVariantService : productVariantService ,
inventoryService : inventoryService ,
orderService : orderService ,
paymentMethodService : paymentMethodService ,
fileService : fileService ,
customerService : customerService ,
analyticsService : analyticsService ,
reportService : reportService ,
tableService : tableService ,
unitService : unitService ,
ingredientService : ingredientService ,
productRecipeService : productRecipeService ,
vendorService : vendorService ,
purchaseOrderService : purchaseOrderService ,
unitConverterService : unitConverterService ,
chartOfAccountTypeService : chartOfAccountTypeService ,
chartOfAccountService : chartOfAccountService ,
accountService : accountService ,
orderIngredientTransactionService : orderIngredientTransactionService ,
2025-07-18 20:10:29 +07:00
}
}
type middlewares struct {
authMiddleware * middleware . AuthMiddleware
}
func ( a * App ) initMiddleware ( services * services ) * middlewares {
return & middlewares {
authMiddleware : middleware . NewAuthMiddleware ( services . authService ) ,
}
}
type validators struct {
2025-09-12 15:37:19 +07:00
userValidator * validator . UserValidatorImpl
organizationValidator validator . OrganizationValidator
outletValidator validator . OutletValidator
categoryValidator validator . CategoryValidator
productValidator validator . ProductValidator
productVariantValidator validator . ProductVariantValidator
inventoryValidator validator . InventoryValidator
orderValidator validator . OrderValidator
paymentMethodValidator validator . PaymentMethodValidator
fileValidator validator . FileValidator
customerValidator validator . CustomerValidator
tableValidator * validator . TableValidator
vendorValidator * validator . VendorValidatorImpl
purchaseOrderValidator * validator . PurchaseOrderValidatorImpl
unitConverterValidator * validator . IngredientUnitConverterValidatorImpl
chartOfAccountTypeValidator * validator . ChartOfAccountTypeValidatorImpl
chartOfAccountValidator * validator . ChartOfAccountValidatorImpl
accountValidator * validator . AccountValidatorImpl
orderIngredientTransactionValidator * validator . OrderIngredientTransactionValidatorImpl
2025-07-18 20:10:29 +07:00
}
func ( a * App ) initValidators ( ) * validators {
return & validators {
2025-09-12 15:37:19 +07:00
userValidator : validator . NewUserValidator ( ) ,
organizationValidator : validator . NewOrganizationValidator ( ) ,
outletValidator : validator . NewOutletValidator ( ) ,
categoryValidator : validator . NewCategoryValidator ( ) ,
productValidator : validator . NewProductValidator ( ) ,
productVariantValidator : validator . NewProductVariantValidator ( ) ,
inventoryValidator : validator . NewInventoryValidator ( ) ,
orderValidator : validator . NewOrderValidator ( ) ,
paymentMethodValidator : validator . NewPaymentMethodValidator ( ) ,
fileValidator : validator . NewFileValidatorImpl ( ) ,
customerValidator : validator . NewCustomerValidator ( ) ,
tableValidator : validator . NewTableValidator ( ) ,
vendorValidator : validator . NewVendorValidator ( ) ,
purchaseOrderValidator : validator . NewPurchaseOrderValidator ( ) ,
unitConverterValidator : validator . NewIngredientUnitConverterValidator ( ) . ( * validator . IngredientUnitConverterValidatorImpl ) ,
chartOfAccountTypeValidator : validator . NewChartOfAccountTypeValidator ( ) . ( * validator . ChartOfAccountTypeValidatorImpl ) ,
chartOfAccountValidator : validator . NewChartOfAccountValidator ( ) . ( * validator . ChartOfAccountValidatorImpl ) ,
accountValidator : validator . NewAccountValidator ( ) . ( * validator . AccountValidatorImpl ) ,
orderIngredientTransactionValidator : validator . NewOrderIngredientTransactionValidator ( ) . ( * validator . OrderIngredientTransactionValidatorImpl ) ,
2025-07-18 20:10:29 +07:00
}
}