feat: [equipment] 점검 데이터 초기화 기능 추가
- 개별 설비 초기화: 장비명 하단 초기화 아이콘 클릭 → 확인 → 해당 월 점검 삭제 - 전체 초기화: 조회 버튼 옆 '전체 초기화' 버튼 → 확인 → 전체 설비 점검 삭제 - DELETE /inspections/reset (개별), /inspections/reset-all (전체) API - canInspect 권한 체크 적용 (개별 초기화) - SweetAlert 확인 모달로 실수 방지
This commit is contained in:
@@ -148,6 +148,62 @@ public function updateNotes(Request $request): JsonResponse
|
||||
}
|
||||
}
|
||||
|
||||
public function resetInspection(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'equipment_id' => 'required|integer',
|
||||
'cycle' => 'required|string',
|
||||
'period' => 'required|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
$deleted = $this->inspectionService->resetEquipmentInspection(
|
||||
$request->input('equipment_id'),
|
||||
$request->input('cycle'),
|
||||
$request->input('period')
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "점검 데이터 {$deleted}건이 초기화되었습니다.",
|
||||
'data' => ['deleted' => $deleted],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$status = $e->getMessage() === '점검 권한이 없습니다.' ? 403 : 400;
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], $status);
|
||||
}
|
||||
}
|
||||
|
||||
public function resetAllInspections(Request $request): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'cycle' => 'required|string',
|
||||
'period' => 'required|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
$deleted = $this->inspectionService->resetAllInspections(
|
||||
$request->input('cycle'),
|
||||
$request->input('period')
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "전체 점검 데이터 {$deleted}건이 초기화되었습니다.",
|
||||
'data' => ['deleted' => $deleted],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], 400);
|
||||
}
|
||||
}
|
||||
|
||||
public function storeTemplate(Request $request, int $equipmentId): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
|
||||
@@ -224,6 +224,71 @@ public function updateInspectionNotes(int $equipmentId, string $yearMonth, array
|
||||
return $inspection->fresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 개별 설비 점검 데이터 초기화 (해당 주기/기간)
|
||||
*/
|
||||
public function resetEquipmentInspection(int $equipmentId, string $cycle, string $period): int
|
||||
{
|
||||
$equipment = Equipment::findOrFail($equipmentId);
|
||||
if (! $equipment->canInspect()) {
|
||||
throw new \Exception('점검 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$tenantId = session('selected_tenant_id', 1);
|
||||
|
||||
$inspection = EquipmentInspection::where('tenant_id', $tenantId)
|
||||
->where('equipment_id', $equipmentId)
|
||||
->where('inspection_cycle', $cycle)
|
||||
->where('year_month', $period)
|
||||
->first();
|
||||
|
||||
if (! $inspection) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$deleted = EquipmentInspectionDetail::where('inspection_id', $inspection->id)->delete();
|
||||
$inspection->update([
|
||||
'overall_judgment' => null,
|
||||
'repair_note' => null,
|
||||
'issue_note' => null,
|
||||
'inspector_id' => null,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 점검 데이터 초기화 (해당 주기/기간의 모든 설비)
|
||||
*/
|
||||
public function resetAllInspections(string $cycle, string $period): int
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', 1);
|
||||
|
||||
$inspections = EquipmentInspection::where('tenant_id', $tenantId)
|
||||
->where('inspection_cycle', $cycle)
|
||||
->where('year_month', $period)
|
||||
->get();
|
||||
|
||||
if ($inspections->isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$totalDeleted = 0;
|
||||
foreach ($inspections as $inspection) {
|
||||
$totalDeleted += EquipmentInspectionDetail::where('inspection_id', $inspection->id)->delete();
|
||||
$inspection->update([
|
||||
'overall_judgment' => null,
|
||||
'repair_note' => null,
|
||||
'issue_note' => null,
|
||||
'inspector_id' => null,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $totalDeleted;
|
||||
}
|
||||
|
||||
public function getMonthlyStats(string $yearMonth): array
|
||||
{
|
||||
$totalEquipments = Equipment::where('is_active', true)
|
||||
|
||||
@@ -62,10 +62,13 @@ class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none foc
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="self-end">
|
||||
<div class="self-end flex gap-2">
|
||||
<button type="submit" class="bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-lg transition">
|
||||
조회
|
||||
</button>
|
||||
<button type="button" onclick="resetAllInspections()" class="bg-red-50 hover:bg-red-100 text-red-600 border border-red-200 px-4 py-2 rounded-lg transition text-sm font-medium">
|
||||
전체 초기화
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</x-filter-collapsible>
|
||||
@@ -127,6 +130,77 @@ function updatePeriodValue() {
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentPeriod() {
|
||||
if (currentCycle === 'daily') {
|
||||
return document.getElementById('periodMonth').value;
|
||||
}
|
||||
return document.getElementById('periodYear').value;
|
||||
}
|
||||
|
||||
function resetEquipment(equipmentId, equipmentName) {
|
||||
const period = getCurrentPeriod();
|
||||
showConfirm(
|
||||
`<strong>${equipmentName}</strong>의 <strong>${period}</strong> 점검 데이터를 모두 초기화하시겠습니까?<br><span class="text-sm text-gray-500">이 작업은 되돌릴 수 없습니다.</span>`,
|
||||
function() {
|
||||
fetch('/api/admin/equipment/inspections/reset', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
equipment_id: equipmentId,
|
||||
cycle: currentCycle,
|
||||
period: period,
|
||||
})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showToast(data.message, 'success');
|
||||
htmx.trigger('#inspection-grid', 'filterSubmit');
|
||||
} else {
|
||||
showToast(data.message || '초기화에 실패했습니다.', 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
{ title: '점검 초기화', icon: 'warning', confirmText: '초기화', cancelText: '취소' }
|
||||
);
|
||||
}
|
||||
|
||||
function resetAllInspections() {
|
||||
const period = getCurrentPeriod();
|
||||
const cycleLabel = document.querySelector('.cycle-tab.bg-white')?.textContent?.trim() || currentCycle;
|
||||
showConfirm(
|
||||
`<strong>${period}</strong> ${cycleLabel} 점검의 <span class="text-red-600 font-bold">전체 데이터</span>를 초기화하시겠습니까?<br><span class="text-sm text-gray-500">모든 설비의 점검 기록이 삭제됩니다. 이 작업은 되돌릴 수 없습니다.</span>`,
|
||||
function() {
|
||||
fetch('/api/admin/equipment/inspections/reset-all', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
cycle: currentCycle,
|
||||
period: period,
|
||||
})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showToast(data.message, 'success');
|
||||
htmx.trigger('#inspection-grid', 'filterSubmit');
|
||||
} else {
|
||||
showToast(data.message || '초기화에 실패했습니다.', 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
{ title: '전체 점검 초기화', icon: 'warning', confirmText: '전체 초기화', cancelText: '취소' }
|
||||
);
|
||||
}
|
||||
|
||||
function toggleCell(equipmentId, templateItemId, checkDate, cell) {
|
||||
fetch('/api/admin/equipment/inspections/detail', {
|
||||
method: 'PATCH',
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
rowspan="{{ $rowCount }}" style="min-width: 80px;">
|
||||
<div class="text-xs text-blue-600">{{ $equipment->equipment_code }}</div>
|
||||
<div class="text-xs">{{ Str::limit($equipment->name, 8) }}</div>
|
||||
@if($canInspect)
|
||||
<button type="button" onclick="resetEquipment({{ $equipment->id }}, '{{ addslashes($equipment->equipment_code . ' ' . $equipment->name) }}')"
|
||||
class="mt-1 text-gray-400 hover:text-red-500 transition" title="점검 초기화">
|
||||
<svg class="w-3.5 h-3.5 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
|
||||
</button>
|
||||
@endif
|
||||
</td>
|
||||
@endif
|
||||
<td class="border border-gray-300 px-2 py-1 whitespace-nowrap sticky bg-white z-10" style="left: 80px; min-width: 80px;">
|
||||
|
||||
@@ -1030,6 +1030,8 @@
|
||||
Route::patch('/inspections/detail', [\App\Http\Controllers\Api\Admin\EquipmentInspectionController::class, 'toggleDetail'])->name('inspections.toggle');
|
||||
Route::patch('/inspections/notes', [\App\Http\Controllers\Api\Admin\EquipmentInspectionController::class, 'updateNotes'])->name('inspections.notes');
|
||||
Route::patch('/inspections/set-result', [\App\Http\Controllers\Api\Admin\EquipmentInspectionController::class, 'setResult'])->name('inspections.set-result');
|
||||
Route::delete('/inspections/reset', [\App\Http\Controllers\Api\Admin\EquipmentInspectionController::class, 'resetInspection'])->name('inspections.reset');
|
||||
Route::delete('/inspections/reset-all', [\App\Http\Controllers\Api\Admin\EquipmentInspectionController::class, 'resetAllInspections'])->name('inspections.reset-all');
|
||||
|
||||
// 수리이력
|
||||
Route::get('/repairs', [\App\Http\Controllers\Api\Admin\EquipmentRepairController::class, 'index'])->name('repairs.index');
|
||||
|
||||
Reference in New Issue
Block a user