Files
sam-api/app/Services/Equipment/EquipmentInspectionService.php
유병철 0d9a840358 feat: [equipment-inspection] 설비별 점검 템플릿 조회 API 개선
- templates 엔드포인트에 cycle 필터 파라미터 추가
- getTemplatesByEquipment 서비스 메서드 신규 추가
- Controller에서 Request 주입하여 cycle 쿼리 파라미터 전달

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 19:21:38 +09:00

386 lines
14 KiB
PHP

<?php
namespace App\Services\Equipment;
use App\Enums\InspectionCycle;
use App\Models\Equipment\Equipment;
use App\Models\Equipment\EquipmentInspection;
use App\Models\Equipment\EquipmentInspectionDetail;
use App\Models\Equipment\EquipmentInspectionTemplate;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class EquipmentInspectionService extends Service
{
public function getInspections(string $cycle, string $period, ?string $productionLine = null, ?int $equipmentId = null): array
{
$equipmentQuery = Equipment::active()
->where('status', '!=', 'disposed')
->with(['manager', 'subManager']);
if ($productionLine) {
$equipmentQuery->byLine($productionLine);
}
if ($equipmentId) {
$equipmentQuery->where('id', $equipmentId);
}
$equipments = $equipmentQuery->orderBy('sort_order')->orderBy('name')->get();
$labels = InspectionCycle::columnLabels($cycle, $period);
$userId = $this->apiUserId();
$result = [];
foreach ($equipments as $equipment) {
$templates = EquipmentInspectionTemplate::where('equipment_id', $equipment->id)
->byCycle($cycle)
->active()
->orderBy('sort_order')
->get();
if ($templates->isEmpty()) {
continue;
}
$inspection = EquipmentInspection::where('equipment_id', $equipment->id)
->where('inspection_cycle', $cycle)
->where('year_month', $period)
->first();
$details = [];
if ($inspection) {
$details = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
->get()
->groupBy(function ($d) {
return $d->template_item_id.'_'.$d->check_date->format('Y-m-d');
});
}
$result[] = [
'equipment' => $equipment,
'templates' => $templates,
'inspection' => $inspection,
'details' => $details,
'labels' => $labels,
'can_inspect' => $equipment->canInspect($userId),
];
}
return $result;
}
public function toggleDetail(int $equipmentId, int $templateItemId, string $checkDate, string $cycle = 'daily'): array
{
return DB::transaction(function () use ($equipmentId, $templateItemId, $checkDate, $cycle) {
$equipment = Equipment::find($equipmentId);
if (! $equipment) {
throw new NotFoundHttpException(__('error.equipment.not_found'));
}
$userId = $this->apiUserId();
if (! $equipment->canInspect($userId)) {
throw new AccessDeniedHttpException(__('error.equipment.no_inspect_permission'));
}
$period = InspectionCycle::resolvePeriod($cycle, $checkDate);
if ($cycle === InspectionCycle::DAILY) {
$tenantId = $this->tenantId();
$holidayDates = InspectionCycle::getHolidayDates($cycle, $period, $tenantId);
if (InspectionCycle::isNonWorkingDay($checkDate, $holidayDates)) {
throw new BadRequestHttpException(__('error.equipment.non_working_day'));
}
}
$tenantId = $this->tenantId();
$inspection = EquipmentInspection::firstOrCreate(
[
'tenant_id' => $tenantId,
'equipment_id' => $equipmentId,
'inspection_cycle' => $cycle,
'year_month' => $period,
],
[
'created_by' => $userId,
]
);
$detail = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
->where('template_item_id', $templateItemId)
->where('check_date', $checkDate)
->first();
if ($detail) {
$nextResult = EquipmentInspectionDetail::getNextResult($detail->result);
if ($nextResult === null) {
$detail->delete();
return ['result' => null, 'symbol' => ''];
}
$detail->update(['result' => $nextResult]);
} else {
$detail = EquipmentInspectionDetail::create([
'inspection_id' => $inspection->id,
'template_item_id' => $templateItemId,
'check_date' => $checkDate,
'result' => 'good',
]);
$nextResult = 'good';
}
return [
'result' => $nextResult,
'symbol' => EquipmentInspectionDetail::getResultSymbol($nextResult),
];
});
}
public function setResult(int $equipmentId, int $templateItemId, string $checkDate, string $cycle, ?string $result): array
{
return DB::transaction(function () use ($equipmentId, $templateItemId, $checkDate, $cycle, $result) {
$equipment = Equipment::find($equipmentId);
if (! $equipment) {
throw new NotFoundHttpException(__('error.equipment.not_found'));
}
$userId = $this->apiUserId();
if (! $equipment->canInspect($userId)) {
throw new AccessDeniedHttpException(__('error.equipment.no_inspect_permission'));
}
$period = InspectionCycle::resolvePeriod($cycle, $checkDate);
if ($cycle === InspectionCycle::DAILY) {
$tenantId = $this->tenantId();
$holidayDates = InspectionCycle::getHolidayDates($cycle, $period, $tenantId);
if (InspectionCycle::isNonWorkingDay($checkDate, $holidayDates)) {
throw new BadRequestHttpException(__('error.equipment.non_working_day'));
}
}
$tenantId = $this->tenantId();
$inspection = EquipmentInspection::firstOrCreate(
[
'tenant_id' => $tenantId,
'equipment_id' => $equipmentId,
'inspection_cycle' => $cycle,
'year_month' => $period,
],
[
'created_by' => $userId,
]
);
$detail = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
->where('template_item_id', $templateItemId)
->where('check_date', $checkDate)
->first();
if ($result === null) {
if ($detail) {
$detail->delete();
}
return ['result' => null, 'symbol' => ''];
}
if ($detail) {
$detail->update(['result' => $result]);
} else {
$detail = EquipmentInspectionDetail::create([
'inspection_id' => $inspection->id,
'template_item_id' => $templateItemId,
'check_date' => $checkDate,
'result' => $result,
]);
}
return [
'result' => $result,
'symbol' => EquipmentInspectionDetail::getResultSymbol($result),
];
});
}
public function updateNotes(int $equipmentId, string $yearMonth, array $data, string $cycle = 'daily'): EquipmentInspection
{
return DB::transaction(function () use ($equipmentId, $yearMonth, $data, $cycle) {
$tenantId = $this->tenantId();
$userId = $this->apiUserId();
$inspection = EquipmentInspection::firstOrCreate(
[
'tenant_id' => $tenantId,
'equipment_id' => $equipmentId,
'inspection_cycle' => $cycle,
'year_month' => $yearMonth,
],
[
'created_by' => $userId,
]
);
$inspection->update($data);
return $inspection->fresh();
});
}
public function resetInspection(int $equipmentId, string $cycle, string $period): int
{
return DB::transaction(function () use ($equipmentId, $cycle, $period) {
$equipment = Equipment::find($equipmentId);
if (! $equipment) {
throw new NotFoundHttpException(__('error.equipment.not_found'));
}
$userId = $this->apiUserId();
if (! $equipment->canInspect($userId)) {
throw new AccessDeniedHttpException(__('error.equipment.no_inspect_permission'));
}
$tenantId = $this->tenantId();
$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,
]);
return $deleted;
});
}
public function saveTemplate(int $equipmentId, array $data): EquipmentInspectionTemplate
{
return DB::transaction(function () use ($equipmentId, $data) {
$tenantId = $this->tenantId();
return EquipmentInspectionTemplate::create(array_merge($data, [
'tenant_id' => $tenantId,
'equipment_id' => $equipmentId,
]));
});
}
public function updateTemplate(int $id, array $data): EquipmentInspectionTemplate
{
return DB::transaction(function () use ($id, $data) {
$template = EquipmentInspectionTemplate::find($id);
if (! $template) {
throw new NotFoundHttpException(__('error.equipment.template_not_found'));
}
$template->update($data);
return $template->fresh();
});
}
public function deleteTemplate(int $id): bool
{
return DB::transaction(function () use ($id) {
$template = EquipmentInspectionTemplate::find($id);
if (! $template) {
throw new NotFoundHttpException(__('error.equipment.template_not_found'));
}
return $template->delete();
});
}
public function copyTemplates(int $equipmentId, string $sourceCycle, array $targetCycles): array
{
return DB::transaction(function () use ($equipmentId, $sourceCycle, $targetCycles) {
$tenantId = $this->tenantId();
$sourceTemplates = EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
->byCycle($sourceCycle)
->active()
->orderBy('sort_order')
->get();
if ($sourceTemplates->isEmpty()) {
throw new BadRequestHttpException(__('error.equipment.no_source_templates'));
}
$copiedCount = 0;
$skippedCount = 0;
foreach ($targetCycles as $targetCycle) {
foreach ($sourceTemplates as $template) {
$exists = EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
->where('inspection_cycle', $targetCycle)
->where('item_no', $template->item_no)
->exists();
if ($exists) {
$skippedCount++;
continue;
}
EquipmentInspectionTemplate::create([
'tenant_id' => $tenantId,
'equipment_id' => $equipmentId,
'inspection_cycle' => $targetCycle,
'item_no' => $template->item_no,
'check_point' => $template->check_point,
'check_item' => $template->check_item,
'check_timing' => $template->check_timing,
'check_frequency' => $template->check_frequency,
'check_method' => $template->check_method,
'sort_order' => $template->sort_order,
'is_active' => true,
]);
$copiedCount++;
}
}
return [
'copied' => $copiedCount,
'skipped' => $skippedCount,
'source_count' => $sourceTemplates->count(),
'target_cycles' => $targetCycles,
];
});
}
public function getTemplatesByEquipment(int $equipmentId, ?string $cycle = null): \Illuminate\Database\Eloquent\Collection
{
return EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
->when($cycle, fn ($q) => $q->byCycle($cycle))
->active()
->orderBy('sort_order')
->get();
}
public function getActiveCycles(int $equipmentId): array
{
return EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
->active()
->distinct()
->pluck('inspection_cycle')
->toArray();
}
}