- templates 엔드포인트에 cycle 필터 파라미터 추가 - getTemplatesByEquipment 서비스 메서드 신규 추가 - Controller에서 Request 주입하여 cycle 쿼리 파라미터 전달 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
386 lines
14 KiB
PHP
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();
|
|
}
|
|
}
|