Skip to content

Architecture Overview

Türkçe

Bu sayfa ICOSYS platformunun genel mimarisini, servis yapısını, katmanlarını ve portlarını açıklar. Yeni başlayanlar için büyük resmi anlamak açısından idealdir.

System Architecture

ICOSYS is a multi-service enterprise platform following a microservices-inspired architecture. Each business domain runs as an independent Spring Boot service with its own database schema, while a single React SPA serves as the unified frontend.

                    ┌──────────────────────────────────┐
                    │         React SPA (Vite)          │
                    │     http://localhost:5173          │
                    │                                    │
                    │  Zustand ─ React Router ─ Axios    │
                    └──────────┬──────────┬─────────────┘
                               │ REST/JWT │
                 ┌─────────────┼──────────┼──────────────┐
                 │             │          │              │
          ┌──────▼──────┐ ┌───▼────┐ ┌───▼────┐   ┌────▼────┐
          │   ICGLB     │ │  BPM   │ │  DMS   │   │ Future  │
          │  :8010      │ │ :8020  │ │ :8030  │   │ :80XX   │
          │  Core       │ │ Partner│ │ Docs   │   │         │
          └──────┬──────┘ └───┬────┘ └───┬────┘   └────┬────┘
                 │            │          │              │
          ┌──────▼────────────▼──────────▼──────────────▼────┐
          │                   MySQL 8                         │
          │    icglb2    │    icbpm    │    icdms    │  ...   │
          └──────────────────────────────────────────────────┘

Services

Service Registry

Service Port Context Path Database Description
ICGLB 8010 /icglb/services icglb2 Core platform — users, accounts, auth, countries, config
BPM 8020 /icbpm/services icbpm Business Partner Management — partners, branches, contracts, accruals
DMS 8030 /icdms/services icdms Document Management — file upload/download, metadata, sharing
React SPA 5173 / - Frontend (dev server)

Türkçe

Yeni modül eklerken port 80XX formatında sıradaki boş port seçilir. Context path her zaman /ic{module}/services kalıbını takip eder.

Service Responsibilities

ICGLB (Core Platform)

  • User authentication (login, JWT issuing)
  • Account and user management
  • CrProcess (tenant/process) management
  • Country, city, and reference data
  • System configuration
  • Health monitoring

BPM (Business Partner Management)

  • Business partner CRUD
  • Branch management
  • Contract lifecycle
  • Accrual period management
  • Partner-related workflows

DMS (Document Management)

  • File upload with magic-byte validation
  • Multi-provider storage (LOCAL, future: S3)
  • Signed URL generation for secure downloads
  • Share links with optional password protection
  • PDF/DOCX/XLSX text extraction
  • File metadata and tagging

Layered Architecture

Each service follows the same layered structure:

┌─────────────────────────────────────────────┐
│  Controller Layer (@RestController)          │  ← HTTP request/response
├─────────────────────────────────────────────┤
│  Service Layer (@Service + @Transactional)   │  ← Business logic
├─────────────────────────────────────────────┤
│  Repository Layer (JPA + Specification)      │  ← Data access
├─────────────────────────────────────────────┤
│  Entity Layer (@Entity)                      │  ← Domain model
└─────────────────────────────────────────────┘

Controller Layer

  • @RestController with @RequestMapping("/api/{entity}")
  • Constructor injection via @RequiredArgsConstructor
  • Returns ResponseEntity<T> for all endpoints
  • Standard CRUD: GET /{id}, POST /, PUT /{id}, DELETE /{id}, POST /list, GET /stats

Service Layer

  • Extends AbstractCrudService<Entity, ID, EditDto, ListDto, FilterDto>
  • Inherits full CRUD: findById, create, update, delete, findPaged, getStats
  • Lifecycle hooks: validateForCreate, beforeCreate, afterCreate, etc.
  • @Transactional on public methods only

Repository Layer

  • Extends ICrudRepository<Entity, ID> (which extends JpaRepository + JpaSpecificationExecutor)
  • Spring Data query derivation: findByCrProcess_Id(), existsBy*()
  • Specifications for dynamic filtering

Entity Layer

  • All entities extend AbstractICEntity6 (inherits audit fields, version, crProcess, xrefId)
  • @TableGenerator for ID generation per module
  • One schema per module: icglb2, icbpm, icdms

Cross-Cutting Concerns

Authentication Flow

Client                    ICGLB (:8010)              BPM/DMS (:8020/8030)
  │                          │                            │
  ├── POST /api/auth/login ──►                            │
  │                          ├── Validate credentials     │
  │  ◄── JWT token ──────────┤                            │
  │                          │                            │
  ├── GET /api/branch/1 ─────┼────── Authorization: Bearer JWT ──►
  │                          │                            ├── Validate JWT
  │                          │                            ├── Extract roles
  │  ◄───────────────────────┼──── Response ──────────────┤

Türkçe

JWT token ICGLB servisi tarafından üretilir. Diğer servisler (BPM, DMS) aynı JWT secret ile token'ı doğrular — merkezi bir auth gateway yoktur, her servis kendi doğrulamasını yapar.

Security Layers

Layer Technology Description
Rate Limiting Bucket4j Per-endpoint: 60 (public), 100 (API key), 200 (JWT) req/min
IP Filtering Custom filter Whitelist mode — only allowed IPs can access
Authentication JWT (JJWT 0.12.5) 8-hour token expiry
Authorization Spring Security Role-based (@Secured) + owner/admin bypass
CORS Spring Security Per-environment allowed origins
Input Validation Jakarta Validation @NotNull, @Size, @Pattern
File Validation Magic bytes DMS validates actual file content, not just extension

Tenant Isolation

Every entity belongs to a CrProcess (tenant). This is enforced at multiple levels:

  1. Entity level: AbstractICEntity6.crProcess — mandatory @ManyToOne
  2. Specification level: First predicate is always crProcess.id = ?
  3. Service level: beforeCreate() hook sets crProcess from DTO
  4. Frontend level: crProcessId sent in every filter request

Türkçe

crProcessId filtrelenmeden yapılan sorgular tüm tenant verilerini döndürür! Specification'da ilk predicate HER ZAMAN crProcess.id filtresi olmalıdır.

Error Handling

Exception thrown in Service
GlobalExceptionHandler (@ControllerAdvice)
    ├── Generate unique refId (UUID)
    ├── Log to database (exception_log table)
    ├── Log to file (fallback if DB fails)
    └── Return standardized error response:
        {
          "errorCode": "IC-BPM-2008",
          "message": "Accrual period already exists",
          "refId": "a1b2c3d4-...",
          "httpStatus": 409
        }

Error code format: IC-{MODULE}-{CATEGORY}{NUMBER}

Category Range Description
Auth 1xxx Authentication/authorization failures
Validation 2xxx Input validation errors
API 3xxx API/network errors
Data 4xxx CRUD/data access errors
File 5xxx File/upload errors
Config 6xxx Configuration/system errors

Logging

Setting Value
Framework SLF4J + Logback
Pattern %d{yyyy-MM-dd HH:mm:ss} %-5level [%logger{36}] [%thread] - %msg%n
File rotation 10 MB per file, 7 days retention
Log directory C:/server/ICOSYS/log/{module}/

Shared Libraries

These projects provide shared functionality used by all service modules:

Project Purpose
ICOM-Api-4.0 Core interfaces (ICrudRepository, base entities)
ICOM-Services-Api-1.0 CrudService interface, ServiceException
ICOM-Micro-Services-Api-1.0 AbstractCrudService, GlobalExceptionHandler, ErrorCodes, JWT filters, rate limiting
Icglb-Entities-1.0 Core JPA entities (CrProcess, AbstractICEntity4/5/6)
Icglb-Entities-Dto-1.0 Core DTOs (ICEntity6Dto, ICEntity6FilterDto, PageRequest/Response)

Environment Configuration

Each service has 4 properties files:

File Purpose
application.properties Common settings (context-path, JPA, jackson, actuator)
application-dev.properties Development (ports, DB, secrets with fallbacks, CORS: *)
application-test.properties Test (restricted CORS, test overrides)
application-prod.properties Production (restricted CORS, no secret fallbacks)

Türkçe

Ortam değişkenleri ${ENV_VAR:fallback} kalıbıyla tanımlanır. Production'da fallback değeri OLMAMALIDIR — tüm secret'lar environment variable olarak verilmelidir.