- api.php를 13개 도메인별 파일로 분리 (1,479줄 → 61줄) - ApiVersionMiddleware 생성 (헤더/쿼리 기반 버전 선택) - v2 요청 시 v2 없으면 v1으로 자동 폴백 - 지원 헤더: Accept-Version, X-API-Version, api_version 쿼리 분리된 도메인: auth, admin, users, tenants, hr, finance, sales, inventory, production, design, files, boards, common Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
216 lines
15 KiB
PHP
216 lines
15 KiB
PHP
<?php
|
|
|
|
/**
|
|
* 인사 관리 API 라우트 (v1)
|
|
*
|
|
* - 부서/직급 관리
|
|
* - 직원 관리
|
|
* - 근태 관리
|
|
* - 휴가 관리
|
|
* - 전자결재
|
|
* - 현장 관리
|
|
* - 시공 관리
|
|
*/
|
|
|
|
use App\Http\Controllers\Api\V1\ApprovalController;
|
|
use App\Http\Controllers\Api\V1\ApprovalFormController;
|
|
use App\Http\Controllers\Api\V1\ApprovalLineController;
|
|
use App\Http\Controllers\Api\V1\AttendanceController;
|
|
use App\Http\Controllers\Api\V1\Construction\ContractController;
|
|
use App\Http\Controllers\Api\V1\Construction\HandoverReportController;
|
|
use App\Http\Controllers\Api\V1\Construction\StructureReviewController;
|
|
use App\Http\Controllers\Api\V1\DepartmentController;
|
|
use App\Http\Controllers\Api\V1\EmployeeController;
|
|
use App\Http\Controllers\Api\V1\LeaveController;
|
|
use App\Http\Controllers\Api\V1\LeavePolicyController;
|
|
use App\Http\Controllers\Api\V1\PositionController;
|
|
use App\Http\Controllers\Api\V1\SiteBriefingController;
|
|
use App\Http\Controllers\Api\V1\SiteController;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
// Department API
|
|
Route::prefix('departments')->group(function () {
|
|
Route::get('', [DepartmentController::class, 'index'])->name('v1.departments.index'); // 목록
|
|
Route::post('', [DepartmentController::class, 'store'])->name('v1.departments.store'); // 생성
|
|
Route::get('/tree', [DepartmentController::class, 'tree'])->name('v1.departments.tree'); // 트리
|
|
Route::get('/{id}', [DepartmentController::class, 'show'])->name('v1.departments.show'); // 단건
|
|
Route::patch('/{id}', [DepartmentController::class, 'update'])->name('v1.departments.update'); // 수정
|
|
Route::delete('/{id}', [DepartmentController::class, 'destroy'])->name('v1.departments.destroy'); // 삭제(soft)
|
|
|
|
// 부서-사용자
|
|
Route::get('/{id}/users', [DepartmentController::class, 'listUsers'])->name('v1.departments.users.index'); // 부서 사용자 목록
|
|
Route::post('/{id}/users', [DepartmentController::class, 'attachUser'])->name('v1.departments.users.attach'); // 사용자 배정(주/부서)
|
|
Route::delete('/{id}/users/{user}', [DepartmentController::class, 'detachUser'])->name('v1.departments.users.detach'); // 사용자 제거
|
|
Route::patch('/{id}/users/{user}/primary', [DepartmentController::class, 'setPrimary'])->name('v1.departments.users.primary'); // 주부서 설정/해제
|
|
|
|
// 부서-권한
|
|
Route::get('/{id}/permissions', [DepartmentController::class, 'listPermissions'])->name('v1.departments.permissions.index'); // 권한 목록
|
|
Route::post('/{id}/permissions', [DepartmentController::class, 'upsertPermissions'])->name('v1.departments.permissions.upsert'); // 권한 부여/차단(메뉴별 가능)
|
|
Route::delete('/{id}/permissions/{permission}', [DepartmentController::class, 'revokePermissions'])->name('v1.departments.permissions.revoke'); // 권한 제거(해당 메뉴 범위까지)
|
|
});
|
|
|
|
// Position API (직급/직책 통합 관리)
|
|
Route::prefix('positions')->group(function () {
|
|
Route::get('', [PositionController::class, 'index'])->name('v1.positions.index');
|
|
Route::post('', [PositionController::class, 'store'])->name('v1.positions.store');
|
|
Route::put('/reorder', [PositionController::class, 'reorder'])->name('v1.positions.reorder');
|
|
Route::get('/{id}', [PositionController::class, 'show'])->name('v1.positions.show');
|
|
Route::put('/{id}', [PositionController::class, 'update'])->name('v1.positions.update');
|
|
Route::delete('/{id}', [PositionController::class, 'destroy'])->name('v1.positions.destroy');
|
|
});
|
|
|
|
// Employee API (사원 관리)
|
|
Route::prefix('employees')->group(function () {
|
|
Route::get('', [EmployeeController::class, 'index'])->name('v1.employees.index');
|
|
Route::post('', [EmployeeController::class, 'store'])->name('v1.employees.store');
|
|
Route::get('/stats', [EmployeeController::class, 'stats'])->name('v1.employees.stats');
|
|
Route::get('/{id}', [EmployeeController::class, 'show'])->name('v1.employees.show');
|
|
Route::patch('/{id}', [EmployeeController::class, 'update'])->name('v1.employees.update');
|
|
Route::delete('/{id}', [EmployeeController::class, 'destroy'])->name('v1.employees.destroy');
|
|
Route::post('/bulk-delete', [EmployeeController::class, 'bulkDelete'])->name('v1.employees.bulkDelete');
|
|
Route::post('/{id}/create-account', [EmployeeController::class, 'createAccount'])->name('v1.employees.createAccount');
|
|
Route::post('/{id}/revoke-account', [EmployeeController::class, 'revokeAccount'])->name('v1.employees.revokeAccount');
|
|
});
|
|
|
|
// Attendance API (근태 관리)
|
|
Route::prefix('attendances')->group(function () {
|
|
Route::get('', [AttendanceController::class, 'index'])->name('v1.attendances.index');
|
|
Route::post('', [AttendanceController::class, 'store'])->name('v1.attendances.store');
|
|
Route::get('/monthly-stats', [AttendanceController::class, 'monthlyStats'])->name('v1.attendances.monthlyStats');
|
|
Route::get('/export', [AttendanceController::class, 'export'])->name('v1.attendances.export');
|
|
Route::post('/check-in', [AttendanceController::class, 'checkIn'])->name('v1.attendances.checkIn');
|
|
Route::post('/check-out', [AttendanceController::class, 'checkOut'])->name('v1.attendances.checkOut');
|
|
Route::get('/{id}', [AttendanceController::class, 'show'])->name('v1.attendances.show');
|
|
Route::patch('/{id}', [AttendanceController::class, 'update'])->name('v1.attendances.update');
|
|
Route::delete('/{id}', [AttendanceController::class, 'destroy'])->name('v1.attendances.destroy');
|
|
Route::post('/bulk-delete', [AttendanceController::class, 'bulkDelete'])->name('v1.attendances.bulkDelete');
|
|
});
|
|
|
|
// Leave API (휴가 관리)
|
|
Route::prefix('leaves')->group(function () {
|
|
Route::get('', [LeaveController::class, 'index'])->name('v1.leaves.index');
|
|
Route::post('', [LeaveController::class, 'store'])->name('v1.leaves.store');
|
|
Route::get('/balances', [LeaveController::class, 'balances'])->name('v1.leaves.balances');
|
|
Route::get('/balance', [LeaveController::class, 'balance'])->name('v1.leaves.balance');
|
|
Route::get('/balance/{userId}', [LeaveController::class, 'userBalance'])->name('v1.leaves.userBalance');
|
|
Route::put('/balance', [LeaveController::class, 'setBalance'])->name('v1.leaves.setBalance');
|
|
Route::get('/grants', [LeaveController::class, 'grants'])->name('v1.leaves.grants');
|
|
Route::post('/grants', [LeaveController::class, 'storeGrant'])->name('v1.leaves.grants.store');
|
|
Route::delete('/grants/{id}', [LeaveController::class, 'destroyGrant'])->name('v1.leaves.grants.destroy');
|
|
Route::get('/{id}', [LeaveController::class, 'show'])->name('v1.leaves.show');
|
|
Route::patch('/{id}', [LeaveController::class, 'update'])->name('v1.leaves.update');
|
|
Route::delete('/{id}', [LeaveController::class, 'destroy'])->name('v1.leaves.destroy');
|
|
Route::post('/{id}/approve', [LeaveController::class, 'approve'])->name('v1.leaves.approve');
|
|
Route::post('/{id}/reject', [LeaveController::class, 'reject'])->name('v1.leaves.reject');
|
|
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');
|
|
Route::post('', [ApprovalFormController::class, 'store'])->name('v1.approval-forms.store');
|
|
Route::get('/active', [ApprovalFormController::class, 'active'])->name('v1.approval-forms.active');
|
|
Route::get('/{id}', [ApprovalFormController::class, 'show'])->whereNumber('id')->name('v1.approval-forms.show');
|
|
Route::patch('/{id}', [ApprovalFormController::class, 'update'])->whereNumber('id')->name('v1.approval-forms.update');
|
|
Route::delete('/{id}', [ApprovalFormController::class, 'destroy'])->whereNumber('id')->name('v1.approval-forms.destroy');
|
|
});
|
|
|
|
// Approval Line API (결재선)
|
|
Route::prefix('approval-lines')->group(function () {
|
|
Route::get('', [ApprovalLineController::class, 'index'])->name('v1.approval-lines.index');
|
|
Route::post('', [ApprovalLineController::class, 'store'])->name('v1.approval-lines.store');
|
|
Route::get('/{id}', [ApprovalLineController::class, 'show'])->whereNumber('id')->name('v1.approval-lines.show');
|
|
Route::patch('/{id}', [ApprovalLineController::class, 'update'])->whereNumber('id')->name('v1.approval-lines.update');
|
|
Route::delete('/{id}', [ApprovalLineController::class, 'destroy'])->whereNumber('id')->name('v1.approval-lines.destroy');
|
|
});
|
|
|
|
// Approval API (전자결재)
|
|
Route::prefix('approvals')->group(function () {
|
|
// 기안함
|
|
Route::get('/drafts', [ApprovalController::class, 'drafts'])->name('v1.approvals.drafts');
|
|
Route::get('/drafts/summary', [ApprovalController::class, 'draftsSummary'])->name('v1.approvals.drafts.summary');
|
|
// 결재함
|
|
Route::get('/inbox', [ApprovalController::class, 'inbox'])->name('v1.approvals.inbox');
|
|
Route::get('/inbox/summary', [ApprovalController::class, 'inboxSummary'])->name('v1.approvals.inbox.summary');
|
|
// 참조함
|
|
Route::get('/reference', [ApprovalController::class, 'reference'])->name('v1.approvals.reference');
|
|
// CRUD
|
|
Route::post('', [ApprovalController::class, 'store'])->name('v1.approvals.store');
|
|
Route::get('/{id}', [ApprovalController::class, 'show'])->whereNumber('id')->name('v1.approvals.show');
|
|
Route::patch('/{id}', [ApprovalController::class, 'update'])->whereNumber('id')->name('v1.approvals.update');
|
|
Route::delete('/{id}', [ApprovalController::class, 'destroy'])->whereNumber('id')->name('v1.approvals.destroy');
|
|
// 액션
|
|
Route::post('/{id}/submit', [ApprovalController::class, 'submit'])->whereNumber('id')->name('v1.approvals.submit');
|
|
Route::post('/{id}/approve', [ApprovalController::class, 'approve'])->whereNumber('id')->name('v1.approvals.approve');
|
|
Route::post('/{id}/reject', [ApprovalController::class, 'reject'])->whereNumber('id')->name('v1.approvals.reject');
|
|
Route::post('/{id}/cancel', [ApprovalController::class, 'cancel'])->whereNumber('id')->name('v1.approvals.cancel');
|
|
// 참조 열람
|
|
Route::post('/{id}/read', [ApprovalController::class, 'markRead'])->whereNumber('id')->name('v1.approvals.read');
|
|
Route::post('/{id}/unread', [ApprovalController::class, 'markUnread'])->whereNumber('id')->name('v1.approvals.unread');
|
|
});
|
|
|
|
// Site API (현장 관리)
|
|
Route::prefix('sites')->group(function () {
|
|
Route::get('', [SiteController::class, 'index'])->name('v1.sites.index');
|
|
Route::post('', [SiteController::class, 'store'])->name('v1.sites.store');
|
|
Route::get('/stats', [SiteController::class, 'stats'])->name('v1.sites.stats');
|
|
Route::get('/active', [SiteController::class, 'active'])->name('v1.sites.active');
|
|
Route::delete('/bulk', [SiteController::class, 'bulkDestroy'])->name('v1.sites.bulk-destroy');
|
|
Route::get('/{id}', [SiteController::class, 'show'])->whereNumber('id')->name('v1.sites.show');
|
|
Route::put('/{id}', [SiteController::class, 'update'])->whereNumber('id')->name('v1.sites.update');
|
|
Route::delete('/{id}', [SiteController::class, 'destroy'])->whereNumber('id')->name('v1.sites.destroy');
|
|
});
|
|
|
|
// Site Briefing API (현장설명회 관리)
|
|
Route::prefix('site-briefings')->group(function () {
|
|
Route::get('', [SiteBriefingController::class, 'index'])->name('v1.site-briefings.index');
|
|
Route::post('', [SiteBriefingController::class, 'store'])->name('v1.site-briefings.store');
|
|
Route::get('/stats', [SiteBriefingController::class, 'stats'])->name('v1.site-briefings.stats');
|
|
Route::delete('/bulk', [SiteBriefingController::class, 'bulkDestroy'])->name('v1.site-briefings.bulk-destroy');
|
|
Route::get('/{id}', [SiteBriefingController::class, 'show'])->whereNumber('id')->name('v1.site-briefings.show');
|
|
Route::put('/{id}', [SiteBriefingController::class, 'update'])->whereNumber('id')->name('v1.site-briefings.update');
|
|
Route::delete('/{id}', [SiteBriefingController::class, 'destroy'])->whereNumber('id')->name('v1.site-briefings.destroy');
|
|
});
|
|
|
|
// Construction API (시공관리)
|
|
Route::prefix('construction')->group(function () {
|
|
// Contract API (계약관리)
|
|
Route::prefix('contracts')->group(function () {
|
|
Route::get('', [ContractController::class, 'index'])->name('v1.construction.contracts.index');
|
|
Route::post('', [ContractController::class, 'store'])->name('v1.construction.contracts.store');
|
|
Route::get('/stats', [ContractController::class, 'stats'])->name('v1.construction.contracts.stats');
|
|
Route::get('/stage-counts', [ContractController::class, 'stageCounts'])->name('v1.construction.contracts.stage-counts');
|
|
Route::delete('/bulk', [ContractController::class, 'bulkDestroy'])->name('v1.construction.contracts.bulk-destroy');
|
|
Route::post('/from-bidding/{biddingId}', [ContractController::class, 'storeFromBidding'])->whereNumber('biddingId')->name('v1.construction.contracts.store-from-bidding');
|
|
Route::get('/{id}', [ContractController::class, 'show'])->whereNumber('id')->name('v1.construction.contracts.show');
|
|
Route::put('/{id}', [ContractController::class, 'update'])->whereNumber('id')->name('v1.construction.contracts.update');
|
|
Route::delete('/{id}', [ContractController::class, 'destroy'])->whereNumber('id')->name('v1.construction.contracts.destroy');
|
|
});
|
|
|
|
// HandoverReport API (인수인계보고서관리)
|
|
Route::prefix('handover-reports')->group(function () {
|
|
Route::get('', [HandoverReportController::class, 'index'])->name('v1.construction.handover-reports.index');
|
|
Route::post('', [HandoverReportController::class, 'store'])->name('v1.construction.handover-reports.store');
|
|
Route::get('/stats', [HandoverReportController::class, 'stats'])->name('v1.construction.handover-reports.stats');
|
|
Route::delete('/bulk', [HandoverReportController::class, 'bulkDestroy'])->name('v1.construction.handover-reports.bulk-destroy');
|
|
Route::get('/{id}', [HandoverReportController::class, 'show'])->whereNumber('id')->name('v1.construction.handover-reports.show');
|
|
Route::put('/{id}', [HandoverReportController::class, 'update'])->whereNumber('id')->name('v1.construction.handover-reports.update');
|
|
Route::delete('/{id}', [HandoverReportController::class, 'destroy'])->whereNumber('id')->name('v1.construction.handover-reports.destroy');
|
|
});
|
|
|
|
// StructureReview API (구조검토관리)
|
|
Route::prefix('structure-reviews')->group(function () {
|
|
Route::get('', [StructureReviewController::class, 'index'])->name('v1.construction.structure-reviews.index');
|
|
Route::post('', [StructureReviewController::class, 'store'])->name('v1.construction.structure-reviews.store');
|
|
Route::get('/stats', [StructureReviewController::class, 'stats'])->name('v1.construction.structure-reviews.stats');
|
|
Route::delete('/bulk', [StructureReviewController::class, 'bulkDestroy'])->name('v1.construction.structure-reviews.bulk-destroy');
|
|
Route::get('/{id}', [StructureReviewController::class, 'show'])->whereNumber('id')->name('v1.construction.structure-reviews.show');
|
|
Route::put('/{id}', [StructureReviewController::class, 'update'])->whereNumber('id')->name('v1.construction.structure-reviews.update');
|
|
Route::delete('/{id}', [StructureReviewController::class, 'destroy'])->whereNumber('id')->name('v1.construction.structure-reviews.destroy');
|
|
});
|
|
});
|