ultimatepos/Modules/AssetExchange/Services/AssetExchangeCmmsBridgeService.php

212 lines
7.6 KiB
PHP

<?php
namespace Modules\AssetExchange\Services;
use App\Business;
use App\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\AssetExchange\Models\Appraisal;
use Modules\AssetExchange\Models\AppraisalLine;
use Modules\AssetExchange\Models\Deal;
use Modules\AssetExchange\Models\Listing;
class AssetExchangeCmmsBridgeService
{
public function createEquipmentFromListing(Business $business, Listing $listing, ?User $user = null): ?object
{
if (! class_exists(\Modules\Maintenance\Models\Equipment::class)) {
throw new \RuntimeException('ماژول نگهداری و تعمیرات (CMMS) نصب نیست.');
}
if (! Schema::hasTable('maintenance_equipment')) {
throw new \RuntimeException('جدول تجهیزات CMMS موجود نیست.');
}
if ($listing->maintenance_equipment_id) {
return \Modules\Maintenance\Models\Equipment::find($listing->maintenance_equipment_id);
}
$code = 'AEX-EQ-'.$listing->listing_code;
$equipment = \Modules\Maintenance\Models\Equipment::create([
'business_id' => $business->id,
'customer_id' => $listing->seller_contact_id,
'code' => $code,
'name' => $listing->title,
'manufacturer' => null,
'model' => null,
'serial_number' => null,
'location' => $listing->location_text,
'status' => 'inactive',
'notes' => 'ایجاد از عرضه AssetExchange #'.$listing->listing_code,
'created_by' => $user?->id,
]);
$listing->update(['maintenance_equipment_id' => $equipment->id]);
return $equipment;
}
public function startRebuildFromDeal(Business $business, Deal $deal, ?User $user = null): ?object
{
if (! class_exists(\Modules\Maintenance\Services\RebuildProcessService::class)) {
throw new \RuntimeException('سرویس بازسازی CMMS در دسترس نیست.');
}
if (! Schema::hasTable('maintenance_rebuild_projects')) {
throw new \RuntimeException('جدول پروژه‌های بازسازی موجود نیست.');
}
$deal->loadMissing('listing', 'appraisal');
$listing = $deal->listing;
if (! $listing) {
throw new \RuntimeException('عرضه مرتبط با معامله یافت نشد.');
}
$equipmentId = $deal->maintenance_equipment_id ?: $listing->maintenance_equipment_id;
if (! $equipmentId) {
$equipment = $this->createEquipmentFromListing($business, $listing, $user);
$equipmentId = $equipment?->id;
}
if (! $equipmentId) {
throw new \RuntimeException('تجهیز CMMS برای شروع بازسازی یافت نشد.');
}
$rebuildService = app(\Modules\Maintenance\Services\RebuildProcessService::class);
$project = $rebuildService->createProject($business, [
'business_id' => $business->id,
'title' => 'بازسازی — '.$listing->title,
'description' => 'ایجاد از معامله AssetExchange '.$deal->deal_code,
'scope_type' => 'equipment',
'equipment_id' => $equipmentId,
'estimated_cost' => $deal->appraisal?->renovation_cost_estimate ?? 0,
'supervisor_id' => $user?->id,
], [$equipmentId], $user);
$deal->update([
'maintenance_rebuild_id' => $project->id,
'maintenance_equipment_id' => $equipmentId,
'status' => 'in_progress',
]);
if ($deal->appraisal) {
try {
$this->populateMaterialListFromAppraisal($business, $project, $deal->appraisal, $user);
} catch (\Throwable) {
}
}
return $project;
}
public function populateMaterialListFromAppraisal(Business $business, object $rebuildProject, Appraisal $appraisal, ?User $user = null): int
{
if (! class_exists(\Modules\Maintenance\Services\MaterialListService::class)) {
return 0;
}
$materialService = app(\Modules\Maintenance\Services\MaterialListService::class);
$list = $materialService->getOrCreateList($business, 'rebuild', $rebuildProject->id, $user);
$lines = AppraisalLine::where('appraisal_id', $appraisal->id)
->where('renovation_need', '!=', 'none')
->orderBy('sort_order')
->get();
$added = 0;
foreach ($lines as $line) {
$materialService->addLine($list, [
'part_name' => $line->name,
'quantity' => 1,
'notes' => trim(($line->condition_notes ?? '').' [AEX renovation: '.$line->renovation_need.']'),
]);
$added++;
}
return $added;
}
public function importEquipmentPartsToAppraisal(Appraisal $appraisal, ?int $equipmentId = null, bool $replaceExisting = false): int
{
if (! class_exists(\Modules\Maintenance\Models\EquipmentPart::class)) {
throw new \RuntimeException('ماژول CMMS نصب نیست.');
}
if (! Schema::hasTable('maintenance_equipment_parts')) {
throw new \RuntimeException('جدول قطعات تجهیز موجود نیست.');
}
$appraisal->loadMissing('listing');
$equipmentId = $equipmentId
?: $appraisal->listing?->maintenance_equipment_id;
if (! $equipmentId) {
throw new \RuntimeException('شناسه تجهیز CMMS برای واردسازی مشخص نشده است.');
}
$parts = \Modules\Maintenance\Models\EquipmentPart::where('business_id', $appraisal->business_id)
->where('equipment_id', $equipmentId)
->orderBy('id')
->get();
if ($parts->isEmpty()) {
throw new \RuntimeException('قطعه‌ای برای این تجهیز در CMMS ثبت نشده است.');
}
if ($replaceExisting) {
AppraisalLine::where('appraisal_id', $appraisal->id)->delete();
}
return DB::transaction(function () use ($appraisal, $parts) {
$partMap = [];
$sort = 0;
$created = 0;
$roots = $parts->whereNull('parent_id');
$this->importPartTree($appraisal, $parts, $roots, null, $partMap, $sort, $created);
return $created;
});
}
protected function importPartTree(
Appraisal $appraisal,
$allParts,
$nodes,
?int $parentLineId,
array &$partMap,
int &$sort,
int &$created
): void {
foreach ($nodes as $part) {
$line = AppraisalLine::create([
'business_id' => $appraisal->business_id,
'appraisal_id' => $appraisal->id,
'parent_line_id' => $parentLineId,
'line_kind' => $part->is_consumable ? 'consumable' : 'part',
'name' => $part->part_name,
'maintenance_equipment_part_id' => $part->id,
'health_percentage' => $part->health_percentage ?? 100,
'condition_notes' => $part->notes,
'renovation_need' => 'none',
'replacement_cost' => 0,
'keep_in_line' => true,
'sort_order' => $sort++,
]);
$partMap[$part->id] = $line->id;
$created++;
$children = $allParts->where('parent_id', $part->id);
if ($children->isNotEmpty()) {
$this->importPartTree($appraisal, $allParts, $children, $line->id, $partMap, $sort, $created);
}
}
}
}