feat: [pmis] 출면일보 CRUD 구현
- 일별 출면일보 마스터 + 인원/장비 3테이블 마이그레이션 - 캘린더 스트립 (1~31일) 날짜 선택 및 상태 닷 표시 - 인원/장비 탭 CRUD (추가/수정/삭제/번개 랜덤데이터) - 검토자 확인 모달 (조직도 + 검색 + 검토라인) - 양식보기 모달 (출면일보/장비일보 인쇄 양식) - 날씨/특이사항/상태 업데이트 API
This commit is contained in:
212
app/Http/Controllers/Juil/PmisDailyAttendanceController.php
Normal file
212
app/Http/Controllers/Juil/PmisDailyAttendanceController.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Juil;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Juil\PmisAttendanceEquipment;
|
||||
use App\Models\Juil\PmisAttendanceWorker;
|
||||
use App\Models\Juil\PmisDailyAttendance;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PmisDailyAttendanceController extends Controller
|
||||
{
|
||||
private function tenantId(): int
|
||||
{
|
||||
return (int) session('current_tenant_id', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 해당 날짜의 출면일보 조회 (없으면 생성)
|
||||
*/
|
||||
public function show(Request $request): JsonResponse
|
||||
{
|
||||
$date = $request->input('date', now()->toDateString());
|
||||
$company = $request->input('company', '');
|
||||
|
||||
$attendance = PmisDailyAttendance::tenant($this->tenantId())
|
||||
->where('date', $date)
|
||||
->when($company, fn ($q) => $q->where('company_name', $company))
|
||||
->first();
|
||||
|
||||
if (! $attendance) {
|
||||
$attendance = PmisDailyAttendance::create([
|
||||
'tenant_id' => $this->tenantId(),
|
||||
'date' => $date,
|
||||
'company_name' => $company,
|
||||
'weather' => '맑음',
|
||||
'status' => 'draft',
|
||||
]);
|
||||
}
|
||||
|
||||
$attendance->load(['workers', 'equipments']);
|
||||
|
||||
return response()->json($attendance);
|
||||
}
|
||||
|
||||
/**
|
||||
* 해당 월의 일별 상태 조회 (캘린더 닷 표시용)
|
||||
*/
|
||||
public function monthStatus(Request $request): JsonResponse
|
||||
{
|
||||
$year = $request->integer('year', now()->year);
|
||||
$month = $request->integer('month', now()->month);
|
||||
$company = $request->input('company', '');
|
||||
|
||||
$attendances = PmisDailyAttendance::tenant($this->tenantId())
|
||||
->whereYear('date', $year)
|
||||
->whereMonth('date', $month)
|
||||
->when($company, fn ($q) => $q->where('company_name', $company))
|
||||
->withCount(['workers', 'equipments'])
|
||||
->get();
|
||||
|
||||
$result = [];
|
||||
foreach ($attendances as $att) {
|
||||
$day = (int) $att->date->format('d');
|
||||
if ($att->workers_count > 0 || $att->equipments_count > 0) {
|
||||
$result[$day] = $att->status;
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 출면일보 메타 업데이트 (날씨, 특이사항, 상태)
|
||||
*/
|
||||
public function update(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$attendance = PmisDailyAttendance::tenant($this->tenantId())->findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'weather' => 'sometimes|string|max:50',
|
||||
'notes' => 'sometimes|nullable|string',
|
||||
'status' => 'sometimes|in:draft,review,approved',
|
||||
'options' => 'sometimes|nullable|array',
|
||||
]);
|
||||
|
||||
$attendance->update($validated);
|
||||
|
||||
return response()->json($attendance);
|
||||
}
|
||||
|
||||
/**
|
||||
* 검토자 저장
|
||||
*/
|
||||
public function saveReviewers(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$attendance = PmisDailyAttendance::tenant($this->tenantId())->findOrFail($id);
|
||||
|
||||
$reviewers = $request->input('reviewers', []);
|
||||
$options = $attendance->options ?? [];
|
||||
$options['reviewers'] = $reviewers;
|
||||
$attendance->update(['options' => $options]);
|
||||
|
||||
return response()->json(['message' => '검토자가 저장되었습니다.']);
|
||||
}
|
||||
|
||||
// ─── 인원(Worker) CRUD ───
|
||||
|
||||
public function workerStore(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'attendance_id' => 'required|integer|exists:pmis_daily_attendances,id',
|
||||
'work_type' => 'required|string|max:200',
|
||||
'job_type' => 'required|string|max:200',
|
||||
'name' => 'required|string|max:100',
|
||||
'man_days' => 'nullable|numeric|min:0',
|
||||
'amount' => 'nullable|numeric|min:0',
|
||||
'work_content' => 'nullable|string|max:500',
|
||||
]);
|
||||
|
||||
$validated['tenant_id'] = $this->tenantId();
|
||||
$validated['man_days'] = $validated['man_days'] ?? 1.0;
|
||||
$validated['amount'] = $validated['amount'] ?? 0;
|
||||
$validated['work_content'] = $validated['work_content'] ?? '';
|
||||
|
||||
$maxSort = PmisAttendanceWorker::where('attendance_id', $validated['attendance_id'])->max('sort_order') ?? 0;
|
||||
$validated['sort_order'] = $maxSort + 1;
|
||||
|
||||
$worker = PmisAttendanceWorker::create($validated);
|
||||
|
||||
return response()->json($worker, 201);
|
||||
}
|
||||
|
||||
public function workerUpdate(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$worker = PmisAttendanceWorker::where('tenant_id', $this->tenantId())->findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'work_type' => 'sometimes|string|max:200',
|
||||
'job_type' => 'sometimes|string|max:200',
|
||||
'name' => 'sometimes|string|max:100',
|
||||
'man_days' => 'nullable|numeric|min:0',
|
||||
'amount' => 'nullable|numeric|min:0',
|
||||
'work_content' => 'nullable|string|max:500',
|
||||
]);
|
||||
|
||||
$worker->update($validated);
|
||||
|
||||
return response()->json($worker);
|
||||
}
|
||||
|
||||
public function workerDestroy(int $id): JsonResponse
|
||||
{
|
||||
$worker = PmisAttendanceWorker::where('tenant_id', $this->tenantId())->findOrFail($id);
|
||||
$worker->delete();
|
||||
|
||||
return response()->json(['message' => '삭제되었습니다.']);
|
||||
}
|
||||
|
||||
// ─── 장비(Equipment) CRUD ───
|
||||
|
||||
public function equipmentStore(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'attendance_id' => 'required|integer|exists:pmis_daily_attendances,id',
|
||||
'equipment_name' => 'required|string|max:200',
|
||||
'specification' => 'nullable|string|max:300',
|
||||
'equipment_number' => 'nullable|string|max:100',
|
||||
'operator' => 'nullable|string|max:100',
|
||||
'man_days' => 'nullable|numeric|min:0',
|
||||
'work_content' => 'nullable|string|max:500',
|
||||
]);
|
||||
|
||||
$validated['tenant_id'] = $this->tenantId();
|
||||
$validated['man_days'] = $validated['man_days'] ?? 1.0;
|
||||
$validated['work_content'] = $validated['work_content'] ?? '';
|
||||
|
||||
$maxSort = PmisAttendanceEquipment::where('attendance_id', $validated['attendance_id'])->max('sort_order') ?? 0;
|
||||
$validated['sort_order'] = $maxSort + 1;
|
||||
|
||||
$equipment = PmisAttendanceEquipment::create($validated);
|
||||
|
||||
return response()->json($equipment, 201);
|
||||
}
|
||||
|
||||
public function equipmentUpdate(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$equipment = PmisAttendanceEquipment::where('tenant_id', $this->tenantId())->findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'equipment_name' => 'sometimes|string|max:200',
|
||||
'specification' => 'nullable|string|max:300',
|
||||
'equipment_number' => 'nullable|string|max:100',
|
||||
'operator' => 'nullable|string|max:100',
|
||||
'man_days' => 'nullable|numeric|min:0',
|
||||
'work_content' => 'nullable|string|max:500',
|
||||
]);
|
||||
|
||||
$equipment->update($validated);
|
||||
|
||||
return response()->json($equipment);
|
||||
}
|
||||
|
||||
public function equipmentDestroy(int $id): JsonResponse
|
||||
{
|
||||
$equipment = PmisAttendanceEquipment::where('tenant_id', $this->tenantId())->findOrFail($id);
|
||||
$equipment->delete();
|
||||
|
||||
return response()->json(['message' => '삭제되었습니다.']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user