212 lines
7.6 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|