feat(work-order): 품목 상태 변경 및 작업지시 상태 자동 연동

- WorkOrderItem 모델에 status 컬럼 및 상수 추가 (waiting/in_progress/completed)
- 품목 상태 변경 API 엔드포인트 추가 (PATCH /work-orders/{id}/items/{itemId}/status)
- syncWorkOrderStatusFromItems() 메서드로 품목→작업지시 상태 자동 동기화
  - 품목 중 하나라도 in_progress → 작업지시 in_progress
  - 모든 품목 completed → 작업지시 completed
  - 모든 품목 waiting → 작업지시 waiting
- 감사 로그: item_status_changed, status_synced_from_items 액션 추가

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-13 16:00:47 +09:00
parent 84ad9e1fc4
commit 38d56aa564
5 changed files with 224 additions and 18 deletions

View File

@@ -58,6 +58,7 @@
// use App\Http\Controllers\Api\V1\MaterialController; // REMOVED: materials 테이블 삭제됨
use App\Http\Controllers\Api\V1\ItemsController;
use App\Http\Controllers\Api\V1\ItemsFileController;
use App\Http\Controllers\Api\V1\LaborController;
use App\Http\Controllers\Api\V1\LeaveController;
use App\Http\Controllers\Api\V1\LeavePolicyController;
use App\Http\Controllers\Api\V1\LoanController;
@@ -69,10 +70,9 @@
use App\Http\Controllers\Api\V1\PayrollController;
use App\Http\Controllers\Api\V1\PermissionController;
use App\Http\Controllers\Api\V1\PlanController;
use App\Http\Controllers\Api\V1\PopupController;
// use App\Http\Controllers\Api\V1\ProductBomItemController; // REMOVED: products 테이블 삭제됨
// use App\Http\Controllers\Api\V1\ProductController; // REMOVED: products 테이블 삭제됨
use App\Http\Controllers\Api\V1\LaborController;
use App\Http\Controllers\Api\V1\PopupController;
use App\Http\Controllers\Api\V1\PositionController;
use App\Http\Controllers\Api\V1\PostController;
use App\Http\Controllers\Api\V1\PricingController;
@@ -89,6 +89,7 @@
use App\Http\Controllers\Api\V1\SalaryController;
use App\Http\Controllers\Api\V1\SaleController;
use App\Http\Controllers\Api\V1\ShipmentController;
use App\Http\Controllers\Api\V1\SiteBriefingController;
use App\Http\Controllers\Api\V1\SiteController;
use App\Http\Controllers\Api\V1\StockController;
use App\Http\Controllers\Api\V1\SubscriptionController;
@@ -425,6 +426,17 @@
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 (계약관리)
@@ -1105,6 +1117,7 @@
// 견적 관리 API
Route::prefix('estimates')->group(function () {
Route::get('/', [EstimateController::class, 'index'])->name('v1.estimates.index'); // 견적 목록
Route::get('/stats', [EstimateController::class, 'stats'])->name('v1.estimates.stats'); // 견적 통계
Route::post('/', [EstimateController::class, 'store'])->name('v1.estimates.store'); // 견적 생성
Route::get('/{id}', [EstimateController::class, 'show'])->name('v1.estimates.show'); // 견적 상세
Route::put('/{id}', [EstimateController::class, 'update'])->name('v1.estimates.update'); // 견적 수정
@@ -1170,6 +1183,9 @@
// 이슈 관리
Route::post('/{id}/issues', [WorkOrderController::class, 'addIssue'])->whereNumber('id')->name('v1.work-orders.issues.store'); // 이슈 등록
Route::patch('/{id}/issues/{issueId}/resolve', [WorkOrderController::class, 'resolveIssue'])->whereNumber('id')->name('v1.work-orders.issues.resolve'); // 이슈 해결
// 품목 상태 변경
Route::patch('/{id}/items/{itemId}/status', [WorkOrderController::class, 'updateItemStatus'])->whereNumber('id')->whereNumber('itemId')->name('v1.work-orders.items.status');
});
// 작업실적 관리 API (Production)