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
+242
View File
@@ -0,0 +1,242 @@
# Internal Architecture
This document describes the clean architecture implementation for the POS backend with complete separation of concerns between database entities, business models, and constants.
## πŸ“ Package Structure
### `/constants` - Business Constants
- **Purpose**: All business logic constants, enums, and validation helpers
- **Usage**: Used by models, services, and validation layers
- **Features**:
- Type-safe enums (UserRole, OrderStatus, PaymentStatus, etc.)
- Business validation functions (IsValidUserRole, etc.)
- Default values and limits
- No dependencies on database or frameworks
### `/entities` - Database Models
- **Purpose**: Database-specific models with GORM tags and hooks
- **Usage**: **ONLY** used by repository layer for database operations
- **Features**:
- GORM annotations (`gorm:` tags)
- Database relationships and constraints
- BeforeCreate/AfterCreate hooks
- Table name specifications
- SQL-specific data types
- **Never used in business logic**
### `/models` - Business Models
- **Purpose**: **Pure** business domain models without any framework dependencies
- **Usage**: Used by services, handlers, and business logic
- **Features**:
- Clean JSON serialization (`json:` tags)
- Validation rules (`validate:` tags)
- Request/Response DTOs
- **Zero GORM dependencies**
- **Zero database annotations**
- Uses constants package for type safety
- Pure business logic methods
### `/mappers` - Data Transformation
- **Purpose**: Convert between entities and business models
- **Usage**: Bridge between repository and service layers
- **Features**:
- Entity ↔ Model conversion functions
- Request DTO β†’ Entity conversion
- Entity β†’ Response DTO conversion
- Null-safe conversions
- Slice/collection conversions
- Type conversions between constants and entities
### `/repository` - Data Access Layer
- **Purpose**: Database operations using entities exclusively
- **Usage**: Only works with database entities
- **Features**:
- CRUD operations with entities
- Query methods with entities
- **Private repository implementations**
- Interface-based contracts
- **Never references business models**
## πŸ”„ Data Flow
```
API Request (JSON)
↓
Request DTO (models)
↓
Business Logic (services with models + constants)
↓
Entity (via mapper)
↓
Repository Layer (entities only)
↓
Database
↓
Entity (from database)
↓
Business Model (via mapper)
↓
Response DTO (models)
↓
API Response (JSON)
```
## 🎯 Key Design Principles
### βœ… **Clean Business Models**
```go
type User struct {
ID uuid.UUID `json:"id"`
Role constants.UserRole `json:"role"`
}
```
```go
type User struct {
ID uuid.UUID `gorm:"primaryKey" json:"id"`
Role string `gorm:"size:50" json:"role"`
}
```
### βœ… **Type-Safe Constants**
```go
type UserRole string
const (
RoleAdmin UserRole = "admin"
)
func IsValidUserRole(role UserRole) bool { /* ... */ }
```
```go
const AdminRole = "admin" ```
### βœ… **Repository Isolation**
```go
func (r *userRepository) Create(ctx context.Context, user *entities.User) error {
return r.db.Create(user).Error
}
```
```go
func (r *userRepository) Create(ctx context.Context, user *models.User) error {
}
```
## πŸ“Š Example Usage
### Service Layer (Business Logic)
```go
func (s *userService) CreateUser(req *models.UserCreateRequest) (*models.UserResponse, error) {
if !constants.IsValidUserRole(req.Role) {
return nil, errors.New("invalid role")
}
entity := mappers.UserCreateRequestToEntity(req, hashedPassword)
err := s.userRepo.Create(ctx, entity)
if err != nil {
return nil, err
}
return mappers.UserEntityToResponse(entity), nil
}
```
### Repository Layer (Data Access)
```go
func (r *userRepository) Create(ctx context.Context, user *entities.User) error {
return r.db.WithContext(ctx).Create(user).Error
}
```
### Handler Layer (API)
```go
func (h *userHandler) CreateUser(c *gin.Context) {
var req models.UserCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
resp, err := h.userService.CreateUser(&req)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(201, resp)
}
```
## πŸ—οΈ Architecture Benefits
1. **🎯 Single Responsibility**: Each package has one clear purpose
2. **πŸ”’ Zero Database Leakage**: Business logic never sees database concerns
3. **πŸ§ͺ Testability**: Easy to mock interfaces and test business logic
4. **πŸ”§ Maintainability**: Changes to database don't affect business models
5. **πŸš€ Flexibility**: Can change ORM without touching business logic
6. **πŸ“œ API Stability**: Business models provide stable contracts
7. **πŸ›‘οΈ Type Safety**: Constants package prevents invalid states
8. **🧹 Clean Code**: No mixed concerns anywhere in the codebase
## πŸ“‹ Development Guidelines
### Constants Package (`/constants`)
- βœ… Define all business enums and constants
- βœ… Provide validation helper functions
- βœ… Include default values and limits
- ❌ Never import database or framework packages
- ❌ No business logic, only constants and validation
### Models Package (`/models`)
- βœ… Pure business structs with JSON tags only
- βœ… Use constants package for type safety
- βœ… Include validation tags for input validation
- βœ… Separate Request/Response DTOs
- βœ… Add business logic methods (validation, calculations)
- ❌ **NEVER** include GORM tags or database annotations
- ❌ **NEVER** import database packages
- ❌ No database relationships or foreign keys
### Entities Package (`/entities`)
- βœ… Include GORM tags and database constraints
- βœ… Define relationships and foreign keys
- βœ… Add database hooks (BeforeCreate, etc.)
- βœ… Use database-specific types
- ❌ **NEVER** use in business logic or handlers
- ❌ **NEVER** add business validation rules
### Mappers Package (`/mappers`)
- βœ… Always check for nil inputs
- βœ… Handle type conversions between constants and strings
- βœ… Provide slice conversion helpers
- βœ… Keep conversions simple and direct
- ❌ No business logic in mappers
- ❌ No database operations
### Repository Package (`/repository`)
- βœ… Work exclusively with entities
- βœ… Use private repository implementations
- βœ… Provide clean interface contracts
- ❌ **NEVER** reference business models
- ❌ **NEVER** import models package
## πŸš€ Migration Complete
**All packages have been successfully reorganized:**
- βœ… **4 Constants files** - All business constants moved to type-safe enums
- βœ… **10 Clean Model files** - Zero GORM dependencies, pure business logic
- βœ… **11 Entity files** - Database-only models with GORM tags
- βœ… **11 Repository files** - Updated to use entities exclusively
- βœ… **2 Mapper files** - Handle conversions between layers
- βœ… **Complete separation** - No cross-layer dependencies
**The codebase now follows strict clean architecture principles with complete separation of database concerns from business logic!** πŸŽ‰