From 4764eeb9d46d74dfca9e7903c779d563b664795c Mon Sep 17 00:00:00 2001 From: kent Date: Tue, 13 Jan 2026 19:49:17 +0900 Subject: [PATCH] =?UTF-8?q?fix(API):=20FormRequest=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B2=80=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SendFcmRequest, PositionReorderRequest 수정 - TenantLogoUploadRequest, Salary Requests 수정 - StructureReview Requests 수정 - HandoverReport, SiteBriefing Requests 추가 Co-Authored-By: Claude --- app/Http/Requests/Admin/SendFcmRequest.php | 2 +- .../HandoverReportStoreRequest.php | 97 +++++++++++++++++++ .../HandoverReportUpdateRequest.php | 95 ++++++++++++++++++ .../StructureReviewStoreRequest.php | 2 +- .../StructureReviewUpdateRequest.php | 2 +- app/Http/Requests/PositionReorderRequest.php | 2 +- .../SiteBriefing/StoreSiteBriefingRequest.php | 86 ++++++++++++++++ .../UpdateSiteBriefingRequest.php | 84 ++++++++++++++++ .../Tenant/TenantLogoUploadRequest.php | 2 +- 9 files changed, 367 insertions(+), 5 deletions(-) create mode 100644 app/Http/Requests/Construction/HandoverReportStoreRequest.php create mode 100644 app/Http/Requests/Construction/HandoverReportUpdateRequest.php create mode 100644 app/Http/Requests/SiteBriefing/StoreSiteBriefingRequest.php create mode 100644 app/Http/Requests/SiteBriefing/UpdateSiteBriefingRequest.php diff --git a/app/Http/Requests/Admin/SendFcmRequest.php b/app/Http/Requests/Admin/SendFcmRequest.php index a430ad6..69af573 100644 --- a/app/Http/Requests/Admin/SendFcmRequest.php +++ b/app/Http/Requests/Admin/SendFcmRequest.php @@ -34,4 +34,4 @@ public function messages(): array 'platform.in' => __('validation.in', ['attribute' => '플랫폼']), ]; } -} \ No newline at end of file +} diff --git a/app/Http/Requests/Construction/HandoverReportStoreRequest.php b/app/Http/Requests/Construction/HandoverReportStoreRequest.php new file mode 100644 index 0000000..ff7d12b --- /dev/null +++ b/app/Http/Requests/Construction/HandoverReportStoreRequest.php @@ -0,0 +1,97 @@ + 'required|string|max:50', + 'contract_id' => 'nullable|integer', + 'site_name' => 'required|string|max:255', + + // 거래처 정보 + 'partner_id' => 'nullable|integer', + 'partner_name' => 'nullable|string|max:255', + + // 담당자 정보 + 'contract_manager_id' => 'nullable|integer', + 'contract_manager_name' => 'nullable|string|max:100', + 'construction_pm_id' => 'nullable|integer', + 'construction_pm_name' => 'nullable|string|max:100', + + // 계약 상세 + 'total_sites' => 'nullable|integer|min:0', + 'contract_amount' => 'nullable|numeric|min:0', + 'contract_date' => 'nullable|date', + 'contract_start_date' => 'nullable|date', + 'contract_end_date' => 'nullable|date|after_or_equal:contract_start_date', + 'completion_date' => 'nullable|date', + + // 상태 정보 + 'status' => [ + 'nullable', + Rule::in([HandoverReport::STATUS_PENDING, HandoverReport::STATUS_COMPLETED]), + ], + + // 2차 배관 + 'has_secondary_piping' => 'nullable|boolean', + 'secondary_piping_amount' => 'nullable|numeric|min:0', + 'secondary_piping_note' => 'nullable|string', + + // 도장 & 코킹 + 'has_coating' => 'nullable|boolean', + 'coating_amount' => 'nullable|numeric|min:0', + 'coating_note' => 'nullable|string', + + // 장비 외 실행금액 + 'external_equipment_cost' => 'nullable|array', + 'external_equipment_cost.shipping_cost' => 'nullable|numeric|min:0', + 'external_equipment_cost.high_altitude_work' => 'nullable|numeric|min:0', + 'external_equipment_cost.public_expense' => 'nullable|numeric|min:0', + + // 특이사항 + 'special_notes' => 'nullable|string', + + // 공사담당자 목록 + 'managers' => 'nullable|array', + 'managers.*.name' => 'required_with:managers|string|max:100', + 'managers.*.non_performance_reason' => 'nullable|string', + 'managers.*.signature' => 'nullable|string', + + // 계약 ITEM 목록 + 'items' => 'nullable|array', + 'items.*.item_no' => 'nullable|integer|min:0', + 'items.*.name' => 'required_with:items|string|max:255', + 'items.*.product' => 'nullable|string|max:255', + 'items.*.quantity' => 'nullable|integer|min:0', + 'items.*.remark' => 'nullable|string', + + // 기타 + 'is_active' => 'nullable|boolean', + ]; + } + + public function messages(): array + { + return [ + 'report_number.required' => __('validation.required', ['attribute' => '보고서번호']), + 'report_number.max' => __('validation.max.string', ['attribute' => '보고서번호', 'max' => 50]), + 'site_name.required' => __('validation.required', ['attribute' => '현장명']), + 'contract_end_date.after_or_equal' => __('validation.after_or_equal', ['attribute' => '계약종료일', 'date' => '계약시작일']), + 'managers.*.name.required_with' => __('validation.required', ['attribute' => '담당자명']), + 'items.*.name.required_with' => __('validation.required', ['attribute' => 'ITEM 명칭']), + ]; + } +} diff --git a/app/Http/Requests/Construction/HandoverReportUpdateRequest.php b/app/Http/Requests/Construction/HandoverReportUpdateRequest.php new file mode 100644 index 0000000..a05a65a --- /dev/null +++ b/app/Http/Requests/Construction/HandoverReportUpdateRequest.php @@ -0,0 +1,95 @@ + 'sometimes|string|max:50', + 'contract_id' => 'nullable|integer', + 'site_name' => 'sometimes|string|max:255', + + // 거래처 정보 + 'partner_id' => 'nullable|integer', + 'partner_name' => 'nullable|string|max:255', + + // 담당자 정보 + 'contract_manager_id' => 'nullable|integer', + 'contract_manager_name' => 'nullable|string|max:100', + 'construction_pm_id' => 'nullable|integer', + 'construction_pm_name' => 'nullable|string|max:100', + + // 계약 상세 + 'total_sites' => 'nullable|integer|min:0', + 'contract_amount' => 'nullable|numeric|min:0', + 'contract_date' => 'nullable|date', + 'contract_start_date' => 'nullable|date', + 'contract_end_date' => 'nullable|date|after_or_equal:contract_start_date', + 'completion_date' => 'nullable|date', + + // 상태 정보 + 'status' => [ + 'nullable', + Rule::in([HandoverReport::STATUS_PENDING, HandoverReport::STATUS_COMPLETED]), + ], + + // 2차 배관 + 'has_secondary_piping' => 'nullable|boolean', + 'secondary_piping_amount' => 'nullable|numeric|min:0', + 'secondary_piping_note' => 'nullable|string', + + // 도장 & 코킹 + 'has_coating' => 'nullable|boolean', + 'coating_amount' => 'nullable|numeric|min:0', + 'coating_note' => 'nullable|string', + + // 장비 외 실행금액 + 'external_equipment_cost' => 'nullable|array', + 'external_equipment_cost.shipping_cost' => 'nullable|numeric|min:0', + 'external_equipment_cost.high_altitude_work' => 'nullable|numeric|min:0', + 'external_equipment_cost.public_expense' => 'nullable|numeric|min:0', + + // 특이사항 + 'special_notes' => 'nullable|string', + + // 공사담당자 목록 + 'managers' => 'nullable|array', + 'managers.*.name' => 'required_with:managers|string|max:100', + 'managers.*.non_performance_reason' => 'nullable|string', + 'managers.*.signature' => 'nullable|string', + + // 계약 ITEM 목록 + 'items' => 'nullable|array', + 'items.*.item_no' => 'nullable|integer|min:0', + 'items.*.name' => 'required_with:items|string|max:255', + 'items.*.product' => 'nullable|string|max:255', + 'items.*.quantity' => 'nullable|integer|min:0', + 'items.*.remark' => 'nullable|string', + + // 기타 + 'is_active' => 'nullable|boolean', + ]; + } + + public function messages(): array + { + return [ + 'report_number.max' => __('validation.max.string', ['attribute' => '보고서번호', 'max' => 50]), + 'contract_end_date.after_or_equal' => __('validation.after_or_equal', ['attribute' => '계약종료일', 'date' => '계약시작일']), + 'managers.*.name.required_with' => __('validation.required', ['attribute' => '담당자명']), + 'items.*.name.required_with' => __('validation.required', ['attribute' => 'ITEM 명칭']), + ]; + } +} diff --git a/app/Http/Requests/Construction/StructureReviewStoreRequest.php b/app/Http/Requests/Construction/StructureReviewStoreRequest.php index f161f74..5964020 100644 --- a/app/Http/Requests/Construction/StructureReviewStoreRequest.php +++ b/app/Http/Requests/Construction/StructureReviewStoreRequest.php @@ -56,4 +56,4 @@ public function messages(): array 'completion_date.after_or_equal' => __('validation.after_or_equal', ['attribute' => '완료일', 'date' => '의뢰일']), ]; } -} \ No newline at end of file +} diff --git a/app/Http/Requests/Construction/StructureReviewUpdateRequest.php b/app/Http/Requests/Construction/StructureReviewUpdateRequest.php index d857531..1883aa8 100644 --- a/app/Http/Requests/Construction/StructureReviewUpdateRequest.php +++ b/app/Http/Requests/Construction/StructureReviewUpdateRequest.php @@ -56,4 +56,4 @@ public function messages(): array 'completion_date.after_or_equal' => __('validation.after_or_equal', ['attribute' => '완료일', 'date' => '의뢰일']), ]; } -} \ No newline at end of file +} diff --git a/app/Http/Requests/PositionReorderRequest.php b/app/Http/Requests/PositionReorderRequest.php index f88216c..32d42ff 100644 --- a/app/Http/Requests/PositionReorderRequest.php +++ b/app/Http/Requests/PositionReorderRequest.php @@ -29,4 +29,4 @@ public function messages(): array 'items.*.sort_order.required' => __('validation.required', ['attribute' => '정렬순서']), ]; } -} \ No newline at end of file +} diff --git a/app/Http/Requests/SiteBriefing/StoreSiteBriefingRequest.php b/app/Http/Requests/SiteBriefing/StoreSiteBriefingRequest.php new file mode 100644 index 0000000..f5985af --- /dev/null +++ b/app/Http/Requests/SiteBriefing/StoreSiteBriefingRequest.php @@ -0,0 +1,86 @@ + 'required|string|max:200', + 'description' => 'nullable|string|max:5000', + + // 거래처/현장 연결 + 'partner_id' => 'nullable|integer|exists:clients,id', + 'site_id' => 'nullable|integer|exists:sites,id', + + // 일정 정보 + 'briefing_date' => 'required|date', + 'briefing_time' => 'nullable|string|max:10', + 'briefing_type' => ['nullable', 'string', Rule::in(SiteBriefing::TYPES)], + 'location' => 'nullable|string|max:200', + 'address' => 'nullable|string|max:255', + + // 상태 정보 + 'status' => ['nullable', 'string', Rule::in(SiteBriefing::STATUSES)], + 'bid_status' => ['nullable', 'string', Rule::in(SiteBriefing::BID_STATUSES)], + 'bid_date' => 'nullable|date', + + // 참석자 정보 (JSON) + 'attendees' => 'nullable|array', + 'attendees.*.user_id' => 'nullable|integer|exists:users,id', + 'attendees.*.name' => 'required|string|max:50', + 'attendees.*.type' => 'required|string|in:internal,external', + 'attendees.*.company' => 'nullable|string|max:100', + 'attendees.*.phone' => 'nullable|string|max:20', + 'attendees.*.email' => 'nullable|email|max:100', + 'attendees.*.position' => 'nullable|string|max:50', + 'attendance_status' => ['nullable', 'string', Rule::in(SiteBriefing::ATTENDANCE_STATUSES)], + + // 공사 정보 + 'site_count' => 'nullable|integer|min:0', + 'construction_start_date' => 'nullable|date', + 'construction_end_date' => 'nullable|date|after_or_equal:construction_start_date', + 'vat_type' => ['nullable', 'string', Rule::in(SiteBriefing::VAT_TYPES)], + + // 프론트엔드 호환성을 위한 필드 매핑 + 'project_name' => 'nullable|string|max:200', // title로 매핑 + 'work_report' => 'nullable|string|max:5000', // description으로 매핑 + ]; + } + + /** + * 검증 데이터 준비 + */ + protected function prepareForValidation(): void + { + // project_name이 있고 title이 없으면 project_name을 title로 사용 + if ($this->filled('project_name') && ! $this->filled('title')) { + $this->merge(['title' => $this->project_name]); + } + + // work_report가 있고 description이 없으면 work_report를 description으로 사용 + if ($this->filled('work_report') && ! $this->filled('description')) { + $this->merge(['description' => $this->work_report]); + } + } + + public function messages(): array + { + return [ + 'title.required' => __('validation.required', ['attribute' => '현장설명회명']), + 'briefing_date.required' => __('validation.required', ['attribute' => '현장설명회 일자']), + 'construction_end_date.after_or_equal' => '공사 종료일은 시작일 이후여야 합니다.', + ]; + } +} diff --git a/app/Http/Requests/SiteBriefing/UpdateSiteBriefingRequest.php b/app/Http/Requests/SiteBriefing/UpdateSiteBriefingRequest.php new file mode 100644 index 0000000..0e26378 --- /dev/null +++ b/app/Http/Requests/SiteBriefing/UpdateSiteBriefingRequest.php @@ -0,0 +1,84 @@ + 'sometimes|string|max:200', + 'description' => 'nullable|string|max:5000', + + // 거래처/현장 연결 + 'partner_id' => 'nullable|integer|exists:clients,id', + 'site_id' => 'nullable|integer|exists:sites,id', + + // 일정 정보 + 'briefing_date' => 'sometimes|date', + 'briefing_time' => 'nullable|string|max:10', + 'briefing_type' => ['nullable', 'string', Rule::in(SiteBriefing::TYPES)], + 'location' => 'nullable|string|max:200', + 'address' => 'nullable|string|max:255', + + // 상태 정보 + 'status' => ['nullable', 'string', Rule::in(SiteBriefing::STATUSES)], + 'bid_status' => ['nullable', 'string', Rule::in(SiteBriefing::BID_STATUSES)], + 'bid_date' => 'nullable|date', + + // 참석자 정보 (JSON) + 'attendees' => 'nullable|array', + 'attendees.*.user_id' => 'nullable|integer|exists:users,id', + 'attendees.*.name' => 'required|string|max:50', + 'attendees.*.type' => 'required|string|in:internal,external', + 'attendees.*.company' => 'nullable|string|max:100', + 'attendees.*.phone' => 'nullable|string|max:20', + 'attendees.*.email' => 'nullable|email|max:100', + 'attendees.*.position' => 'nullable|string|max:50', + 'attendance_status' => ['nullable', 'string', Rule::in(SiteBriefing::ATTENDANCE_STATUSES)], + + // 공사 정보 + 'site_count' => 'nullable|integer|min:0', + 'construction_start_date' => 'nullable|date', + 'construction_end_date' => 'nullable|date|after_or_equal:construction_start_date', + 'vat_type' => ['nullable', 'string', Rule::in(SiteBriefing::VAT_TYPES)], + + // 프론트엔드 호환성을 위한 필드 매핑 + 'project_name' => 'nullable|string|max:200', + 'work_report' => 'nullable|string|max:5000', + ]; + } + + /** + * 검증 데이터 준비 + */ + protected function prepareForValidation(): void + { + // project_name이 있고 title이 없으면 project_name을 title로 사용 + if ($this->filled('project_name') && ! $this->filled('title')) { + $this->merge(['title' => $this->project_name]); + } + + // work_report가 있고 description이 없으면 work_report를 description으로 사용 + if ($this->filled('work_report') && ! $this->filled('description')) { + $this->merge(['description' => $this->work_report]); + } + } + + public function messages(): array + { + return [ + 'construction_end_date.after_or_equal' => '공사 종료일은 시작일 이후여야 합니다.', + ]; + } +} diff --git a/app/Http/Requests/Tenant/TenantLogoUploadRequest.php b/app/Http/Requests/Tenant/TenantLogoUploadRequest.php index e7e6c0d..c30cf83 100644 --- a/app/Http/Requests/Tenant/TenantLogoUploadRequest.php +++ b/app/Http/Requests/Tenant/TenantLogoUploadRequest.php @@ -27,4 +27,4 @@ public function messages(): array 'logo.max' => __('validation.max.file', ['attribute' => '로고', 'max' => '5MB']), ]; } -} \ No newline at end of file +}