Files
sam-docs/specs/database-schema.md

545 lines
16 KiB
Markdown
Raw Normal View History

# SAM 데이터베이스 스키마
**업데이트**: 2026-01-29
**데이터베이스**: samdb (MySQL 8.0.44)
**전체 테이블**: 219개
---
## Multi-tenant 데이터 아키텍처
### 데이터 격리 방식
- **방식**: `tenant_id` 컬럼 기반 격리
- **스코프**: BelongsToTenant global scope 자동 적용
- **모델**: `shared/Models/` 디렉토리의 공통 모델 사용
- **Soft Deletes**: 대부분의 엔티티에 적용
- **감사 컬럼**: `created_by`, `updated_by`, `deleted_by`
## 핵심 테이블 구조
### 인증 및 권한
#### users (24 컬럼) - Phase 4 완료
**용도**: 시스템 사용자 정보 (관리자, 일반 사용자)
주요 컬럼:
- `id` (PK), `user_id` (UK), `name`, `email` (UK), `password`
- `phone`, `role` (deprecated), `is_active`, `is_super_admin`
- `email_verified_at`, `last_login_at`
- 2FA: `two_factor_secret`, `two_factor_recovery_codes`, `two_factor_confirmed_at`
- `remember_token`, `current_team_id`, `profile_photo_path`
- `options` (JSON)
- Audit: `created_by`, `updated_by`, `deleted_by`
- Timestamps: `created_at`, `updated_at`, `deleted_at` (Soft Delete)
특징:
- Laravel Sanctum 인증
- Multi-tenant via `user_tenants` pivot
- 2FA 지원
- Soft Delete 지원
#### roles (11 컬럼) - Phase 4 완료, Spatie Permission
**용도**: 사용자 역할 정의
주요 컬럼:
- `id` (PK), `tenant_id`, `name`, `guard_name`, `description`
- Audit: `created_by`, `updated_by`, `deleted_by`
- Timestamps: `created_at`, `updated_at`, `deleted_at`
인덱스:
- `UNIQUE (tenant_id, name, guard_name)`
- `INDEX (tenant_id)`
특징:
- Spatie Laravel Permission 패키지
- Multi-tenant 지원
- Soft Delete 지원
#### permissions (8 컬럼) - Phase 4 완료, Spatie Permission
**용도**: 시스템 권한 정의
주요 컬럼:
- `id` (PK), `tenant_id` (nullable), `name`, `guard_name`
- Audit: `created_by`, `updated_by`
- Timestamps: `created_at`, `updated_at`
인덱스:
- `UNIQUE (name, guard_name, tenant_id)`
- `INDEX (tenant_id)`
특징:
- tenant_id nullable (마스터 권한 지원)
- Spatie Laravel Permission 패키지
#### model_has_roles (4 컬럼) - Spatie Permission
**용도**: 사용자-역할 연결 (Many-to-Many)
주요 컬럼:
- `role_id` (PK, FK), `model_type` (PK), `model_id` (PK), `tenant_id` (PK)
외래키:
- `role_id``roles.id` (ON DELETE CASCADE)
특징:
- Polymorphic 관계
- Multi-tenant 지원
#### role_has_permissions (2 컬럼) - Spatie Permission
**용도**: 역할-권한 연결 (Many-to-Many)
주요 컬럼:
- `permission_id` (PK, FK), `role_id` (PK, FK)
외래키:
- `permission_id``permissions.id` (ON DELETE CASCADE)
- `role_id``roles.id` (ON DELETE CASCADE)
#### user_tenants
- 사용자-테넌트 다대다 관계
- `active`, `default` 플래그
#### personal_access_tokens
- Sanctum 토큰 저장
#### api_keys
- API 키 관리
- `is_active` 상태 관리
#### permission_overrides
- 수동 권한 허용/거부
- 시간 기반 유효성
### 멀티테넌트 조직
#### tenants (32 컬럼) - Phase 4 완료
**용도**: 다중 회사/조직 관리 (Multi-tenant 핵심)
주요 컬럼:
- `id` (PK), `company_name`, `code` (UK)
- `email`, `phone`, `address`, `business_num`, `corp_reg_no`, `ceo_name`
- `homepage`, `fax`, `logo`, `admin_memo`, `options` (JSON)
- `tenant_st_code` (trial/active/none), `plan_id`, `subscription_id`
- `max_users`, `trial_ends_at`, `expires_at`, `last_paid_at`, `billing_tp_code`
- 저장소: `storage_limit`, `storage_used`, `storage_warning_sent_at`, `storage_grace_period_until`
- Audit: `created_by`, `updated_by`, `deleted_by`
- Timestamps: `created_at`, `updated_at`, `deleted_at`
인덱스:
- `UNIQUE (code)`
- `INDEX (storage_used)`
특징:
- Multi-tenant 시스템의 핵심 테이블
- 구독/결제 관리
- 저장소 용량 관리 (기본 10GB)
- Soft Delete 지원
#### departments (14 컬럼) - Phase 4 완료
**용도**: 조직 부서 정보 (계층 구조)
주요 컬럼:
- `id` (PK), `tenant_id`, `parent_id` (Self-referential)
- `code`, `name`, `description`
- `is_active`, `sort_order`
- Audit: `created_by`, `updated_by`, `deleted_by`
- Timestamps: `created_at`, `updated_at`, `deleted_at`
인덱스:
- `UNIQUE (tenant_id, code)`
- `INDEX (tenant_id, name)`
- `INDEX (tenant_id, is_active)`
- `INDEX (parent_id)`
특징:
- Self-referential 관계 (무제한 depth)
- 활성 상태 관리
- 정렬 순서 지원
- Soft Delete 지원
#### tenant_user_profiles
- 테넌트별 확장 사용자 프로필
#### department_user
- 사용자-부서 할당
- `primary` 부서 플래그
### 제품 관리
#### categories
- 계층적 제품 분류
- Soft Deletes 적용
#### category_fields
- 카테고리별 동적 필드 정의
#### category_templates
- 버전 관리된 카테고리 필드 스냅샷
#### products
- 제품 카탈로그
- 타입 분류: `PRODUCT`, `PART`, `SUBASSEMBLY`
#### product_components
- BOM 관계
- `MATERIAL` 또는 `PRODUCT` 참조
#### materials
- 자재 마스터
- 동적 속성 지원
#### classifications
- 그룹별 플랫 코드 테이블
- 예: `product_type`, `payment_method`
### 디자인 및 제조
#### models
- 디자인 모델 마스터
- 생명주기 상태 관리
#### model_versions
- 버전 관리된 모델 릴리스
- 상태: `DRAFT`, `RELEASED`
#### bom_templates
- 모델 버전에 연결된 BOM 템플릿
#### bom_template_items
- 템플릿 BOM 라인 항목
- 수량 및 낭비율 포함
### 주문 및 운영
#### orders
- 주문/견적 마스터
- 워크플로우 상태
#### order_items
- 주문 라인 항목
- 디자인 코드 포함
#### order_item_components
- 주문 항목별 필수 자재/제품
#### order_histories
- 주문 변경 추적 및 메모
#### clients
- 고객/벤더 마스터
### 재고 및 자재
#### material_receipts
- 입고 자재 수령
- 로트 추적
#### material_inspections
- 품질 검사 기록
#### material_inspection_items
- 검사 체크리스트 항목
#### lots
- 자재 로트 관리
#### lot_sales
- 로트 소비 추적
#### price_histories
- 시간 기반 유효성을 가진 가격 이력
### 시스템 및 설정
#### menus (17 컬럼) - Phase 4 완료
**용도**: 시스템 메뉴 트리 구조 (사이드바, 권한 연동)
주요 컬럼:
- `id` (PK), `tenant_id` (nullable), `parent_id` (Self-referential)
- `name`, `url`, `icon`
- `is_active`, `hidden`, `is_external`, `external_url`
- `sort_order`
- Audit: `created_by`, `updated_by`, `deleted_by`
- Timestamps: `created_at`, `updated_at`, `deleted_at`
인덱스:
- `INDEX (tenant_id)`
- `INDEX (parent_id)`
- `INDEX (sort_order)`
- `INDEX (tenant_id, is_active, hidden)`
- `INDEX (tenant_id, deleted_at)`
- `INDEX (deleted_at)`
특징:
- Self-referential 관계 (무제한 depth)
- tenant_id nullable (마스터 메뉴 지원)
- 활성/숨김 상태 토글
- 내부/외부 링크 지원
- Soft Delete 지원
#### common_codes
- 계층적 마스터 코드
- 테넌트 지원
#### files
- 다형성 파일 첨부
#### audit_logs
- 포괄적인 감사 추적
- 13개월 보관
#### setting_field_defs
- 전역 필드 정의
#### tenant_field_settings
- 테넌트별 필드 설정
#### tenant_option_groups / tenant_option_values
- 테넌트 관리 드롭다운 옵션
### 콘텐츠 관리
#### boards
- 설정 가능한 게시판 시스템
#### posts
- 커스텀 필드를 가진 게시판 게시물
#### board_settings
- 게시판별 동적 필드 정의
#### board_comments
- 계층적 댓글 시스템
## 주요 모델 관계
### 관계 구조
```
Tenant → Users (many-to-many via user_tenants)
Products ↔ Materials (via product_components with ref_type)
Models → Versions → BOM Templates (design workflow)
Orders → Items → Components (order breakdown)
Categories ↔ Fields ↔ Templates (dynamic forms with versioning)
Audit Logs (polymorphic tracking across all major entities)
```
## 공통 컬럼 패턴
### 필수 컬럼
모든 테이블에 포함되어야 하는 컬럼:
```php
Schema::create('products', function (Blueprint $table) {
$table->id()->comment('ID');
$table->foreignId('tenant_id')->comment('테넌트 ID');
// 비즈니스 컬럼...
$table->foreignId('created_by')->nullable()->comment('생성자 ID');
$table->foreignId('updated_by')->nullable()->comment('수정자 ID');
$table->foreignId('deleted_by')->nullable()->comment('삭제자 ID');
$table->timestamps();
$table->softDeletes();
});
```
### 컬럼 규칙
- **tenant_id**: 필수, 인덱스 권장
- **created_by, updated_by, deleted_by**: nullable, COMMENT 필수
- **deleted_at**: Soft Delete용
- **timestamps**: created_at, updated_at
## 인덱스 최적화
### 필수 인덱스
- `tenant_id` - 모든 테이블에 권장
- 검색/정렬에 사용되는 컬럼
- 복합 인덱스 고려
### 주요 유니크 제약
- `models(code)` - 모델 코드
- `model_versions(version_no)` - 버전 번호
- `bom_items(parent, order)` - BOM 항목 순서
## Foreign Key 제약조건
### 정책
- **개발 환경**: 설계 단계에서 제약조건 생성
- **운영 환경**: 최소화 또는 제거
### 이유
- 성능 최적화
- 유연한 데이터 관리
- 마이그레이션 복잡도 감소
## 감사 로그
### 테이블 구조
**audit_logs:**
- `tenant_id` - 테넌트 ID
- `target_type` - 대상 모델 타입 (polymorphic)
- `target_id` - 대상 ID
- `action` - 액션 타입
- `before` - 변경 전 데이터 (JSON)
- `after` - 변경 후 데이터 (JSON)
- `actor_id` - 수행자 ID
- `ip` - IP 주소
- `ua` - User Agent
- `created_at` - 생성 시간
### 보관 정책
- **기본 보관 기간**: 13개월
- **정리**: `audit:prune` 스케줄러 (매일 03:10)
- **실패 허용**: 감사 로그 실패 시 비즈니스 로직 계속 진행
## 데이터베이스 작업 시 주의사항
### 마이그레이션 작성
```
✓ 명확한 파일명 (YYYY_MM_DD_HHMMSS_action_table.php)
✓ up/down 메서드 모두 구현
✓ 롤백 테스트 완료
✓ COMMENT 추가 (tenant_id, created_by 등)
```
### 모델 작성
```
✓ BelongsToTenant scope 적용
✓ ModelTrait 사용
✓ SoftDeletes 적용
✓ tenant_id 필터링 확인
```
### 쿼리 작성
```
✓ tenant_id 필터링 필수
✓ Eager Loading 사용 (N+1 문제 방지)
✓ 인덱스 활용 고려
```
## 관련 문서
- [API 개발 규칙](./api_rules.md)
- [아키텍처](./architecture.md)
---
## Phase 4 구현 상세 (2025-11-24)
### 완료된 테이블 (8개)
1. **users** - 사용자 관리 (Sanctum 인증, 2FA)
2. **roles** - 역할 관리 (Spatie Permission)
3. **permissions** - 권한 관리 (Spatie Permission)
4. **model_has_roles** - 사용자-역할 연결
5. **role_has_permissions** - 역할-권한 연결
6. **departments** - 부서 관리 (계층 구조)
7. **menus** - 메뉴 관리 (트리 구조)
8. **tenants** - 테넌트 관리 (구독/저장소)
### Spatie Permission 통합
```php
// 역할 할당
$user->assignRole('admin');
// 권한 확인
$user->hasPermissionTo('users.view');
// 역할에 권한 할당
$role->syncPermissions(['users.view', 'users.create']);
```
### 공통 패턴
- **Soft Delete**: deleted_at, deleted_by
- **Audit**: created_by, updated_by, deleted_by
- **Multi-tenant**: tenant_id (nullable for master data)
- **Self-referential**: parent_id (departments, menus)
- **Active Status**: is_active
- **Sort Order**: sort_order
---
**최종 업데이트**: 2026-01-30
**Phase 4**: 완료 (8개 테이블 상세화)
**테이블 수 갱신**: samdb 219개 + sam_stat 20개 = 239개
---
## sam_stat 데이터베이스 (통계 전용)
> 별도 MySQL 데이터베이스. Laravel `sam_stat` 커넥션 사용. 마이그레이션 경로: `database/migrations/stats/`
### 메타/관리 테이블
| 테이블 | 설명 | 주요 컬럼 |
|--------|------|----------|
| `stat_definitions` | 통계 정의 마스터 | domain, stat_type, table_name, is_active |
| `stat_job_logs` | 집계 작업 로그 | tenant_id, job_type, target_date, status, records_processed, duration_ms |
### 차원 테이블
| 테이블 | 설명 | 주요 컬럼 |
|--------|------|----------|
| `dim_date` | 날짜 차원 (2020~2030) | date, year, quarter, month, day, day_of_week, is_weekend, is_holiday |
| `dim_client` | 고객 차원 (samdb 동기화) | tenant_id, source_client_id, client_name, group_name |
| `dim_product` | 제품 차원 (samdb 동기화) | tenant_id, source_product_id, product_name, product_type |
### 일간 팩트 테이블 (7개)
| 테이블 | 도메인 | UK | 주요 지표 |
|--------|--------|------|----------|
| `stat_sales_daily` | 매출/수주 | (tenant_id, stat_date) | order_count/amount, sales_count/amount, new/active_client_count, shipment_count/amount |
| `stat_finance_daily` | 재무/회계 | (tenant_id, stat_date) | deposit/withdrawal count/amount, net_cashflow, purchase_count/amount, bank_balance_total |
| `stat_production_daily` | 생산/작업 | (tenant_id, stat_date) | work_order_count, completed/in_progress_count, defect_count/rate, total_quantity |
| `stat_inventory_daily` | 재고 | (tenant_id, stat_date) | receipt_count/quantity, shipment_count/quantity, total_stock_value, low_stock_count |
| `stat_quote_pipeline_daily` | 견적/영업 | (tenant_id, stat_date) | new/sent/won/lost_quote_count, pipeline_value, conversion_rate, avg_quote_amount |
| `stat_hr_attendance_daily` | 인사/근태 | (tenant_id, stat_date) | total/present/absent/late/leave_count, overtime_hours, attendance_rate |
| `stat_system_daily` | 시스템/감사 | (tenant_id, stat_date) | api_request/error_count, active_user_count, audit_create/update/delete_count, fcm_sent/failed_count |
### 월간 요약 테이블 (4개)
| 테이블 | 도메인 | UK | 주요 지표 |
|--------|--------|------|----------|
| `stat_sales_monthly` | 매출/수주 | (tenant_id, stat_year, stat_month) | order/sales/shipment count/amount, unique_client_count, avg_order_amount, mom/yoy_growth_rate |
| `stat_finance_monthly` | 재무/회계 | (tenant_id, stat_year, stat_month) | deposit/withdrawal/purchase_total, net_cashflow, bank_balance_end, mom_cashflow_change |
| `stat_production_monthly` | 생산/작업 | (tenant_id, stat_year, stat_month) | total_work_orders, completed/in_progress_count, avg_defect_rate, total_production_quantity |
| `stat_project_monthly` | 건설/프로젝트 | (tenant_id, stat_year, stat_month) | active/completed_site_count, new_contract_count/amount, gross_profit/rate |
### KPI/알림/이벤트 테이블
| 테이블 | 설명 | 주요 컬럼 |
|--------|------|----------|
| `stat_kpi_targets` | KPI 목표값 | tenant_id, domain, metric_code, target_year/month, target_value, actual_value |
| `stat_alerts` | 통계 알림 | tenant_id, domain, alert_type, severity(enum: info/warning/critical), title, message, is_read, is_resolved |
| `stat_events` | 실시간 이벤트 로그 | tenant_id, domain, event_type, entity_type, entity_id, payload(JSON), occurred_at |
| `stat_snapshots` | 상태 스냅샷 | tenant_id, snapshot_date, domain, snapshot_type, data(JSON) |
### Artisan 커맨드
| 커맨드 | 설명 |
|--------|------|
| `stat:aggregate-daily` | 일간 통계 집계 (스케줄러: 매일 01:00) |
| `stat:aggregate-monthly` | 월간 통계 집계 (스케줄러: 매월 1일 02:00) |
| `stat:sync-dimensions` | 차원 테이블 동기화 (스케줄러: 매일 00:30) |
| `stat:backfill --from= --to=` | 과거 데이터 일괄 백필 |
| `stat:verify --date=` | 원본 DB vs sam_stat 정합성 검증 |
### API 엔드포인트
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/v1/stats/summary` | 대시보드 통계 요약 |
| GET | `/api/v1/stats/daily` | 도메인별 일간 통계 (domain, start_date, end_date) |
| GET | `/api/v1/stats/monthly` | 도메인별 월간 통계 (domain, year, month?) |
| GET | `/api/v1/stats/alerts` | 통계 알림 목록 (limit?, unread_only?) |