142 lines
6.0 KiB
PHP
142 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace Modules\Maintenance\Http\Controllers\Api\V1;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Modules\Maintenance\Models\Equipment;
|
|
use Modules\Maintenance\Models\EquipmentPart;
|
|
use Modules\Maintenance\Traits\ResolvesBusiness;
|
|
use Illuminate\Http\Request;
|
|
|
|
class EquipmentPartController extends Controller
|
|
{
|
|
use ResolvesBusiness;
|
|
|
|
private function partRules(bool $partial = false): array
|
|
{
|
|
$sometimes = $partial ? 'sometimes' : 'nullable';
|
|
|
|
return [
|
|
'parent_id' => [$sometimes, 'exists:maintenance_equipment_parts,id'],
|
|
'spare_part_id' => ['nullable', 'exists:maintenance_spare_parts,id'],
|
|
'part_catalog_id' => ['nullable', 'exists:maintenance_part_catalogs,id'],
|
|
'part_name' => [$partial ? 'sometimes' : 'required_without:spare_part_id', 'nullable', 'string', 'max:255'],
|
|
'part_code' => ['nullable', 'string', 'max:100'],
|
|
'quantity' => ['nullable', 'numeric', 'min:0'],
|
|
'unit' => ['nullable', 'string', 'max:50'],
|
|
'part_type' => ['sometimes', 'string', 'in:mechanical,electronic,consumable,hydraulic,pneumatic'],
|
|
'is_consumable' => ['sometimes', 'boolean'],
|
|
'is_critical' => ['sometimes', 'boolean'],
|
|
'responsibility' => ['sometimes', 'string', 'in:ours,vendor,shared'],
|
|
'responsibility_party_name' => ['nullable', 'string', 'max:255'],
|
|
'warranty_status' => ['sometimes', 'string', 'in:none,active,expired'],
|
|
'warranty_provider' => ['nullable', 'string', 'max:255'],
|
|
'warranty_expires_at' => ['nullable', 'date'],
|
|
'installed_by' => ['sometimes', 'string', 'in:ours,vendor,third_party'],
|
|
'installer_name' => ['nullable', 'string', 'max:255'],
|
|
'expected_replacement_date' => ['nullable', 'date'],
|
|
'replacement_interval_days' => ['nullable', 'integer', 'min:0'],
|
|
'last_replaced_at' => ['nullable', 'date'],
|
|
'replacement_quality_grade' => ['nullable', 'string', 'max:50'],
|
|
'damage_action' => ['nullable', 'string', 'in:replace,service,both'],
|
|
'damage_service_list' => ['nullable', 'array'],
|
|
'multi_year_service_plan' => ['nullable', 'array'],
|
|
'health_percentage' => ['nullable', 'numeric', 'min:0', 'max:100'],
|
|
'notes' => ['nullable', 'string'],
|
|
];
|
|
}
|
|
|
|
public function index(Request $request, Equipment $equipment)
|
|
{
|
|
if (! $this->ensureBusinessOwnership($request, $equipment->business_id)) {
|
|
return $this->jsonError('دسترسی ندارید.', 403);
|
|
}
|
|
|
|
$parts = EquipmentPart::where('equipment_id', $equipment->id)
|
|
->with(['sparePart:id,part_number,name,quantity,unit', 'partCatalog:id,catalog_code,name', 'children'])
|
|
->orderBy('part_name')
|
|
->get();
|
|
|
|
$tree = $this->buildTree($parts);
|
|
|
|
return $this->jsonSuccess(['items' => $parts, 'tree' => $tree]);
|
|
}
|
|
|
|
public function store(Request $request, Equipment $equipment)
|
|
{
|
|
if (! $this->ensureBusinessOwnership($request, $equipment->business_id)) {
|
|
return $this->jsonError('دسترسی ندارید.', 403);
|
|
}
|
|
|
|
$data = $request->validate($this->partRules());
|
|
|
|
if (! empty($data['spare_part_id'])) {
|
|
$spare = \Modules\Maintenance\Models\SparePart::find($data['spare_part_id']);
|
|
if ($spare) {
|
|
$data['part_name'] = $data['part_name'] ?? $spare->name;
|
|
$data['part_code'] = $data['part_code'] ?? $spare->part_number;
|
|
$data['unit'] = $data['unit'] ?? $spare->unit;
|
|
}
|
|
}
|
|
|
|
if (! empty($data['part_catalog_id'])) {
|
|
$catalog = \Modules\Maintenance\Models\PartCatalog::find($data['part_catalog_id']);
|
|
if ($catalog) {
|
|
$data['part_name'] = $data['part_name'] ?? $catalog->name;
|
|
$data['part_code'] = $data['part_code'] ?? $catalog->catalog_code;
|
|
$data['part_type'] = $data['part_type'] ?? $catalog->part_type;
|
|
$data['is_consumable'] = $data['is_consumable'] ?? $catalog->is_consumable;
|
|
}
|
|
}
|
|
|
|
$part = EquipmentPart::create(array_merge($data, [
|
|
'business_id' => $equipment->business_id,
|
|
'equipment_id' => $equipment->id,
|
|
'quantity' => $data['quantity'] ?? 1,
|
|
]));
|
|
|
|
return $this->jsonSuccess($part->load(['sparePart', 'partCatalog']), 'قطعه به تجهیز اضافه شد.', 201);
|
|
}
|
|
|
|
public function update(Request $request, Equipment $equipment, EquipmentPart $part)
|
|
{
|
|
if (! $this->ensureBusinessOwnership($request, $equipment->business_id) || $part->equipment_id !== $equipment->id) {
|
|
return $this->jsonError('دسترسی ندارید.', 403);
|
|
}
|
|
|
|
$data = $request->validate($this->partRules(true));
|
|
$part->update($data);
|
|
|
|
return $this->jsonSuccess($part->fresh()->load(['sparePart', 'partCatalog']), 'قطعه بهروزرسانی شد.');
|
|
}
|
|
|
|
public function destroy(Request $request, Equipment $equipment, EquipmentPart $part)
|
|
{
|
|
if (! $this->ensureBusinessOwnership($request, $equipment->business_id) || $part->equipment_id !== $equipment->id) {
|
|
return $this->jsonError('دسترسی ندارید.', 403);
|
|
}
|
|
|
|
$part->delete();
|
|
|
|
return $this->jsonSuccess(null, 'قطعه حذف شد.');
|
|
}
|
|
|
|
private function buildTree($parts, ?int $parentId = null): array
|
|
{
|
|
$branch = [];
|
|
foreach ($parts as $part) {
|
|
if ($part->parent_id === $parentId) {
|
|
$branch[] = [
|
|
'id' => $part->id,
|
|
'part_name' => $part->part_name,
|
|
'part_code' => $part->part_code,
|
|
'health_percentage' => $part->health_percentage,
|
|
'children' => $this->buildTree($parts, $part->id),
|
|
];
|
|
}
|
|
}
|
|
|
|
return $branch;
|
|
}
|
|
}
|