hrms-api-recruit/CLAUDE.md
Suphonchai Phoonsawat 0f1ec072ad
All checks were successful
Build & Deploy on Dev / build (push) Successful in 52s
change logic
2026-05-13 07:00:22 +07:00

76 lines
3.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Run
```bash
dotnet build BMA.EHR.Recruit.Service.sln
dotnet build BMA.EHR.Recruit.Service.sln -c Release
dotnet publish -c Release -o /app/publish /p:UseAppHost=false
```
No test projects exist in this solution.
## Architecture
**Stack:** ASP.NET Core 7.0 Web API / EF Core 7.0 / MySQL (Pomelo) / MinIO (S3) / Keycloak (JWT)
**Pattern:** Controllers → Services → EF Core DbContext (no repository layer for main data)
### Multiple DbContexts
Three separate MySQL databases, each with its own `DbContext`:
- `ApplicationDbContext` — Recruitment data (Recruits, Scores, Imports)
- `OrgDbContext` — Organization data
- `MetadataDbContext` — Metadata
All registered as `Transient` lifetime. Auto-migration runs on startup.
### Controllers
- `BaseController` provides standardized `Success()` / `Error()` response methods returning `ResponseObject` (Status, Message, Result)
- `RecruitController` is the sole business controller (route: `api/v{version}/recruit`)
- API versioning enabled via `Microsoft.AspNetCore.Mvc.Versioning`
### Background Import System
Excel file imports run asynchronously through a Channel-based queue:
- `ImportBackgroundService` (BackgroundService) — dequeues and processes jobs
- `ImportJobQueue` — bounded Channel (capacity 100)
- `ImportJobTracker` — in-memory ConcurrentDictionary tracking
Four import types: `CandidateFile`, `CandidateFileById`, `ScoreFile`, `ResultFile`
All imports use `EFCore.BulkExtensions.MySql` (v6.7.16) for bulk operations to handle 50,000+ rows without memory issues. Pattern:
1. Insert parent/history entities via `SaveChangesAsync` (small operations)
2. `ChangeTracker.Clear()` to release references
3. Collect entities into separate `List<T>` per table
4. `BulkInsertAsync` with `SetOutputIdentity = true` for parent entities
5. Assign generated Ids to child entities
6. `BulkInsertAsync` for each child entity table separately
7. Batch size: 500
### Entity Models
All entities inherit from `EntityBase` (Guid `Id` PK, audit fields: `CreatedAt`, `CreatedUserId`, `LastUpdatedAt`, etc.). Models are in `Models/` with subdirectories: `Recruits/`, `Documents/`, `HR/`, `MetaData/`, `Placement/`.
Key relationships use navigation properties without explicit FK properties (EF shadow properties). Configured via fluent API in `OnModelCreating`.
### External Services
- **Authentication:** Keycloak JWT Bearer (`hrmsbkk-id.case-collection.com/realms/hrms`)
- **File Storage:** MinIO via `MinIOService` (AWS S3 SDK)
- **Search/Logging:** Elasticsearch (NEST client)
- **Excel:** EPPlus for reading import files
## Key Files
- `Program.cs` — Service registration, middleware pipeline, auto-migration
- `Data/ApplicationDbContext.cs` — EF Core fluent API relationship configuration
- `Services/ImportBackgroundService.cs` — All bulk import logic (4 import methods)
- `Services/RecruitService.cs` — Core business logic
- `Controllers/BaseController.cs` — Standard response helpers
- `Responses/ResponseObject.cs` — Standard API response envelope
## Conventions
- Language: C# with nullable reference types enabled
- Naming: PascalCase properties, `_camelCase` parameters in service methods
- API responses: Always wrapped in `ResponseObject`
- Authorization: `[Authorize]` on controllers, user context from JWT claims