# SAM API 개발 규칙 **업데이트**: 2025-11-10 --- ## 1. Architecture Philosophy - **Service First**: All business logic must be written in Service classes (public functions) - **Controller**: Only responsible for DI injection of Services and calling them. Use ApiResponse::handle() for responses - **Exception Flow**: Errors are thrown → converted to JSON by global handler - **Context Enforcement**: Base Service requires tenantId(), apiUserId(). Throws exception if not set --- ## 2. Multi-tenancy & Models - BelongsToTenant global scope applied - ModelTrait for is_active, date handling - SoftDeletes by default - Common columns: tenant_id, created_by, updated_by, deleted_by (COMMENT required) - FK constraints: Created during design, minimal in production ### 2.1 ModelTrait 사용 가이드 `ModelTrait`는 모든 모델에서 공통으로 사용하는 기능을 제공합니다. **위치**: `app/Traits/ModelTrait.php` **제공 기능**: ```php // 1. 날짜 직렬화 포맷 (Y-m-d H:i:s) protected function serializeDate(DateTimeInterface $date) // 2. Active 상태 조회 Scope public function scopeActive($query) // 사용: Model::active()->get() // SQL: WHERE is_active = 1 ``` **⚠️ 필수 요구사항**: `scopeActive()` 메서드 사용 시 테이블에 `is_active` 컬럼이 **반드시 존재해야 함** ```sql -- 마이그레이션 예시 $table->boolean('is_active') ->default(true) ->comment('활성화 여부 (ModelTrait::scopeActive() 사용)'); ``` **모델 설정**: ```php class YourModel extends Model { use BelongsToTenant, ModelTrait, SoftDeletes; protected $fillable = [ // ... 'is_active', // 반드시 추가 ]; protected $casts = [ 'is_active' => 'boolean', // 반드시 추가 ]; } ``` **is_active 컬럼 적용 테이블** (2025-12-05 기준): | 테이블 | is_active | 비고 | |--------|-----------|------| | materials | ✅ 있음 | | | products | ✅ 있음 | | | item_pages | ✅ 있음 | | | item_fields | ✅ 있음 | 2025-12-05 추가 | | item_sections | ❌ 없음 | 필요시 마이그레이션 추가 | --- ## 3. Middleware Stack - ApiKeyMiddleware, CheckSwaggerAuth, CorsMiddleware, CheckPermission, PermMapper - Default route group: auth.apikey (some with auth:sanctum) --- ## 4. Routing (v1) - Auth, Common codes, Files, Tenants, Users (me/tenants/switch), Menus+Permissions, Roles/Permissions, Departments, Field settings, Options, Categories, Classifications, Products, BOM - REST conventions: index/show/store/update/destroy + extensions (toggle, bulkUpsert, reorder) --- ## 5. Controller/Service Rules - **Controller**: FormRequest type-hint → only pass $request->validated() to Service - **Service**: extends Service, tenantId()/apiUserId() required - **Lists**: Pagination, explicit search parameters - **Responses**: {success, message, data}, message must be i18n key only --- ## 6. i18n & Response Messages - Messages: lang/{locale}/message.php - Errors: lang/{locale}/error.php - **Rule**: No direct strings, must use __('message.xxx'), __('error.xxx') - Common keys: message.fetched/created/updated/deleted/bulk_upsert/reordered - Resource-specific keys allowed: message.product.created, message.bom.bulk_upsert --- ## 7. Validation (FormRequest) - **No direct validate() calls**. Separate all into FormRequest classes - **Reuse common Requests**: PaginateRequest, BomItemsRequest, DateRangeRequest - **Boundary validation** (effective_from ≤ effective_to) in Request --- ## 8. Audit Logging - **Table**: audit_logs (tenant_id, target_type, target_id, action, before/after(json), actor_id, ip, ua, created_at) - **Actions**: created, updated, deleted, released, cloned, items_replaced, diff_viewed - **Retention**: 13 months default, audit:prune scheduler cleanup - **Failure tolerance**: Log failures don't block business operations --- ## 9. Domain Rules - **Status**: Strings (DRAFT/RELEASED/ARCHIVED) - **Unique/Indexes**: models(code), model_versions(version_no), bom_items(parent, order) - **BOM**: Supports summary/validate/bulkUpsert/reorder --- ## 개발 시 필수 체크 ``` ✓ Service-First 패턴 (Controller는 단순) ✓ BelongsToTenant scope 적용 ✓ ModelTrait 사용 ✓ SoftDeletes 적용 ✓ FormRequest 검증 ✓ i18n 키 사용 (__('message.xxx')) ✓ 감사 로그 고려 ✓ tenant_id 필터링 확인 ```