feat: G-2 작업실적 관리 API 구현

- WorkResult 모델 생성 (Production 네임스페이스)
- WorkResultService 서비스 구현 (CRUD + 통계 + 토글)
- WorkResultController 컨트롤러 생성 (8개 엔드포인트)
- FormRequest 검증 클래스 (Store/Update)
- Swagger 문서 작성 (WorkResultApi.php)
- 라우트 추가 (/api/v1/work-results)
- i18n 메시지 추가 (work_result 키)

API Endpoints:
- GET /work-results - 목록 조회 (페이징, 필터링)
- GET /work-results/stats - 통계 조회
- GET /work-results/{id} - 상세 조회
- POST /work-results - 등록
- PUT /work-results/{id} - 수정
- DELETE /work-results/{id} - 삭제
- PATCH /work-results/{id}/inspection - 검사 상태 토글
- PATCH /work-results/{id}/packaging - 포장 상태 토글

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-26 15:18:08 +09:00
parent dd0f79b947
commit 84cce6742e
9 changed files with 1154 additions and 0 deletions

View File

@@ -38,6 +38,9 @@
use App\Http\Controllers\Api\V1\VendorLedgerController;
use App\Http\Controllers\Api\V1\BankTransactionController;
use App\Http\Controllers\Api\V1\CardTransactionController;
use App\Http\Controllers\Api\V1\ReceivablesController;
use App\Http\Controllers\Api\V1\DailyReportController;
use App\Http\Controllers\Api\V1\ComprehensiveAnalysisController;
use App\Http\Controllers\Api\V1\EstimateController;
use App\Http\Controllers\Api\V1\FileStorageController;
use App\Http\Controllers\Api\V1\FolderController;
@@ -56,6 +59,7 @@
use App\Http\Controllers\Api\V1\ItemsController;
use App\Http\Controllers\Api\V1\ItemsFileController;
use App\Http\Controllers\Api\V1\LeaveController;
use App\Http\Controllers\Api\V1\LeavePolicyController;
use App\Http\Controllers\Api\V1\LoanController;
use App\Http\Controllers\Api\V1\MenuController;
use App\Http\Controllers\Api\V1\ModelSetController;
@@ -96,6 +100,7 @@
use App\Http\Controllers\Api\V1\UserRoleController;
use App\Http\Controllers\Api\V1\WithdrawalController;
use App\Http\Controllers\Api\V1\WorkOrderController;
use App\Http\Controllers\Api\V1\WorkResultController;
use App\Http\Controllers\Api\V1\WorkSettingController;
use Illuminate\Support\Facades\Route;
@@ -328,6 +333,10 @@
Route::post('/{id}/cancel', [LeaveController::class, 'cancel'])->name('v1.leaves.cancel');
});
// Leave Policy API (휴가 정책)
Route::get('/leave-policy', [LeavePolicyController::class, 'show'])->name('v1.leave-policy.show');
Route::put('/leave-policy', [LeavePolicyController::class, 'update'])->name('v1.leave-policy.update');
// Approval Form API (결재 양식)
Route::prefix('approval-forms')->group(function () {
Route::get('', [ApprovalFormController::class, 'index'])->name('v1.approval-forms.index');
@@ -499,6 +508,22 @@
Route::get('/accounts', [BankTransactionController::class, 'accounts'])->name('v1.bank-transactions.accounts');
});
// Receivables API (채권 현황)
Route::prefix('receivables')->group(function () {
Route::get('', [ReceivablesController::class, 'index'])->name('v1.receivables.index');
Route::get('/summary', [ReceivablesController::class, 'summary'])->name('v1.receivables.summary');
});
// Daily Report API (일일 보고서)
Route::prefix('daily-report')->group(function () {
Route::get('/note-receivables', [DailyReportController::class, 'noteReceivables'])->name('v1.daily-report.note-receivables');
Route::get('/daily-accounts', [DailyReportController::class, 'dailyAccounts'])->name('v1.daily-report.daily-accounts');
Route::get('/summary', [DailyReportController::class, 'summary'])->name('v1.daily-report.summary');
});
// Comprehensive Analysis API (종합 분석 보고서)
Route::get('/comprehensive-analysis', [ComprehensiveAnalysisController::class, 'index'])->name('v1.comprehensive-analysis.index');
// Plan API (요금제 관리)
Route::prefix('plans')->group(function () {
Route::get('', [PlanController::class, 'index'])->name('v1.plans.index');
@@ -1008,6 +1033,21 @@
Route::patch('/{id}/issues/{issueId}/resolve', [WorkOrderController::class, 'resolveIssue'])->whereNumber('id')->name('v1.work-orders.issues.resolve'); // 이슈 해결
});
// 작업실적 관리 API (Production)
Route::prefix('work-results')->group(function () {
// 기본 CRUD
Route::get('', [WorkResultController::class, 'index'])->name('v1.work-results.index'); // 목록
Route::get('/stats', [WorkResultController::class, 'stats'])->name('v1.work-results.stats'); // 통계
Route::post('', [WorkResultController::class, 'store'])->name('v1.work-results.store'); // 생성
Route::get('/{id}', [WorkResultController::class, 'show'])->whereNumber('id')->name('v1.work-results.show'); // 상세
Route::put('/{id}', [WorkResultController::class, 'update'])->whereNumber('id')->name('v1.work-results.update'); // 수정
Route::delete('/{id}', [WorkResultController::class, 'destroy'])->whereNumber('id')->name('v1.work-results.destroy'); // 삭제
// 상태 토글
Route::patch('/{id}/inspection', [WorkResultController::class, 'toggleInspection'])->whereNumber('id')->name('v1.work-results.inspection'); // 검사 상태 토글
Route::patch('/{id}/packaging', [WorkResultController::class, 'togglePackaging'])->whereNumber('id')->name('v1.work-results.packaging'); // 포장 상태 토글
});
// 파일 저장소 API
Route::prefix('files')->group(function () {
Route::post('/upload', [FileStorageController::class, 'upload'])->name('v1.files.upload'); // 파일 업로드 (임시)