# 생산실적신고 (Performance Reports)

> **작성일**: 2026-03-09
> **상태**: 운영 중
> **URL**: `/quality/performance-reports`

---

## 1. 개요

### 1.1 목적

건설기술진흥법에 따라 방화문 제품검사 완료 건에 대해 **분기별 실적신고**를 관리한다.
건기원(한국건설기술연구원) 온라인 시스템에 제출할 데이터를 자동 수집하고, 필수정보 검증 후 확정 처리한다.

### 1.2 비즈니스 배경

- **법적 의무**: 방화문은 건축자재 품질관리 대상으로, 제품검사 후 실적을 건기원에 신고해야 함
- **신고 주기**: 분기별 (Q1: 1~3월, Q2: 4~6월, Q3: 7~9월, Q4: 10~12월)
- **신고 내용**: 품질관리서 번호, 현장정보, LOT, 규격, 검사결과
- **제출 방식**: 건기원 온라인 시스템 수기 입력 또는 엑셀 업로드

### 1.3 SAM에서의 역할

```
제품검사 완료 → 실적신고 자동생성 → 필수정보 검증 → 확정 → 건기원 제출
                (SAM 자동)          (SAM 자동)      (담당자)   (수동/향후 자동)
```

---

## 2. 상태 흐름

### 2.1 상태 정의

| 상태 | 코드 | 설명 |
|------|------|------|
| 미확정 | `unconfirmed` | 자동생성 직후, 필수정보 미완료 가능 |
| 확정 | `confirmed` | 필수정보 완료 후 담당자가 확정 |
| 신고완료 | `reported` | 건기원에 신고 완료 (미구현) |

### 2.2 상태 전이

```
                  confirm()
unconfirmed ─────────────────→ confirmed
     ↑                              │
     │         unconfirm()          │
     └──────────────────────────────┘
                                    │
                              distribute()
                                    ↓
                               reported (미구현)
```

### 2.3 확정 조건

확정(`confirm`) 시 **필수정보 4개 섹션** 검증:

```
✅ 건축공사장: name, land_location, lot_no
✅ 자재유통업자: company, address, ceo, tel
✅ 공사시공자: company, address, name, phone
✅ 공사감리자: office, address, name, phone
```

하나라도 누락되면 확정 불가 → `cannotConfirmWithMissingInfo` 에러 반환

---

## 3. 자동 생성 로직

### 3.1 트리거

`QualityDocumentService::complete()` 호출 시:

```php
PerformanceReport::firstOrCreate(
    [
        'tenant_id' => $tenantId,
        'quality_document_id' => $qualityDocument->id,
    ],
    [
        'year' => now()->year,           // 현재 연도
        'quarter' => ceil(now()->month / 3), // 현재 분기
        'confirmation_status' => 'unconfirmed',
        'created_by' => $userId,
    ]
);
```

### 3.2 특징

- `firstOrCreate`: 동일 품질관리서에 대해 중복 생성 방지
- 검사완료 시점의 연도/분기로 자동 배정
- Unique 제약: `(tenant_id, quality_document_id)`

---

## 4. 화면 구성

### 4.1 탭 구조

| 탭 | 내용 |
|----|------|
| **분기별 실적신고** | 기본 탭. 연도/분기별 실적 목록 |
| **누락체크** | 출고완료 수주 중 품질관리서 미등록 건 |

### 4.2 통계 카드

```
┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│  전체     │  │  확정     │  │  미확정   │  │  총 개소  │
│  12건     │  │  8건      │  │  4건      │  │  48개소   │
└──────────┘  └──────────┘  └──────────┘  └──────────┘
```

### 4.3 테이블 컬럼 (분기별 실적신고)

| 컬럼 | 설명 |
|------|------|
| 선택 | 체크박스 (일괄 처리용) |
| 번호 | 순번 |
| 품질관리서번호 | KD-QD-YYYYMM-NNNN |
| 작성일 | 품질관리서 접수일 |
| 현장명 | 시공 현장명 |
| 수주처 | 거래처 |
| 개소 | 검사 개소 수 |
| 필수정보 | "완료" 또는 "N건 누락" |
| 확정상태 | 미확정/확정/신고완료 |
| 확정일 | 확정 처리일 |
| 메모 | 메모 내용 |

### 4.4 액션 버튼

| 버튼 | 조건 | 설명 |
|------|------|------|
| 선택 확정 | 미확정 건 선택 시 | 필수정보 완료된 건만 일괄 확정 |
| 확정 해제 | 확정 건 선택 시 | 확정 → 미확정 되돌리기 |
| 배포 | 확정 건 선택 시 | 건기원 신고 (미구현) |
| 메모 | 건 선택 시 | 메모 일괄 작성 |

---

## 5. 누락체크 (슬라이드 18)

### 5.1 목적

실적신고 기간이 지났지만 확정이 안된 목록을 확인한다.
출고(배송)가 완료되었지만 품질관리서가 등록되지 않은 수주를 탐지한다.

### 5.2 누락 발생 원인

| 원인 | 설명 |
|------|------|
| 품질관리서 발행일 기준 분기 불일치 | 품질관리서가 해당 분기에 포함되어야 하나, 공사 미완료로 다음 분기로 이월 |
| 수주 중복 등록 | 수주통 시 다른 현장명으로 등록되어 제품검사 발행 시 누락 |
| 납품 후 미등록 | 납품 후 제품검사 등록이 누락된 경우 |

### 5.3 누락체크 목록 표시

| 컬럼 | 설명 |
|------|------|
| 품질관리서 번호 | 관련 품질관리서 (있는 경우) |
| 현장명 | 수주 현장명 |
| 수주처 | 거래처 |
| 개소 | 수주 개소 수 |
| 제품검사완료일 | 검사 완료 일자 |
| 메모 | 누락 사유 메모 |

### 5.4 로직

```sql
-- 출고완료 수주 중 quality_document_orders에 미등록된 건
SELECT orders.*
FROM orders
WHERE delivery_status = 'completed'
  AND NOT EXISTS (
    SELECT 1 FROM quality_document_orders
    WHERE order_id = orders.id
  )
```

---

## 6. API

### 6.1 엔드포인트

| Method | Path | 설명 |
|--------|------|------|
| GET | `/quality/performance-reports` | 목록 (year, quarter, status 필터) |
| GET | `/quality/performance-reports/stats` | 확정/미확정 통계 |
| GET | `/quality/performance-reports/missing` | 누락체크 |
| PATCH | `/quality/performance-reports/confirm` | 일괄 확정 |
| PATCH | `/quality/performance-reports/unconfirm` | 확정 해제 |
| PATCH | `/quality/performance-reports/memo` | 메모 일괄 업데이트 |

### 6.2 요청/응답 예시

**목록 조회**:
```
GET /quality/performance-reports?year=2026&quarter=1&status=unconfirmed
```

**일괄 확정**:
```json
PATCH /quality/performance-reports/confirm
{
  "ids": [1, 2, 3]
}
```

**응답**:
```json
{
  "success": true,
  "message": "message.performance_report.confirmed",
  "data": {
    "confirmed_count": 2,
    "skipped_count": 1,
    "skipped_ids": [3]
  }
}
```

---

## 7. 소스 파일

### 7.1 Backend

| 파일 | 역할 |
|------|------|
| `api/app/Models/Qualitys/PerformanceReport.php` | 모델 |
| `api/app/Services/PerformanceReportService.php` | 서비스 (280줄) |
| `api/app/Http/Controllers/Api/V1/PerformanceReportController.php` | 컨트롤러 |
| `api/routes/api/v1/quality.php` | 라우트 |

### 7.2 Frontend

| 파일 | 역할 |
|------|------|
| `react/src/app/[locale]/(protected)/quality/performance-reports/page.tsx` | 페이지 |
| `react/src/components/quality/PerformanceReportManagement/PerformanceReportList.tsx` | 목록 컴포넌트 |
| `react/src/components/quality/PerformanceReportManagement/MemoModal.tsx` | 메모 모달 |
| `react/src/components/quality/PerformanceReportManagement/actions.ts` | Server Actions |

---

## 8. 미구현 기능

| 기능 | 설명 | 우선순위 |
|------|------|---------|
| 배포(distribute) API | 건기원 시스템 연동 자동 신고 | 중 |
| 엑셀 다운로드 | 확정건 건기원 양식 엑셀 내보내기 | 높음 |
| 분기 마감 알림 | 분기 종료 전 미확정건 알림 | 낮음 |

---

## 관련 문서

- [품질관리 시스템 개요](./README.md)
- [제품검사 관리](./inspection-management.md)

---

**최종 업데이트**: 2026-03-09
