ultimatepos/Modules/Maintenance/Services/MaintenanceHealthService.php

123 lines
4.1 KiB
PHP

<?php
namespace Modules\Maintenance\Services;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
class MaintenanceHealthService
{
/** @var array<int, string> */
protected array $requiredTables = [
'maintenance_equipment',
'maintenance_equipment_categories',
'maintenance_equipment_parts',
'maintenance_work_orders',
'maintenance_preventive_schedules',
'maintenance_spare_parts',
'maintenance_work_order_parts',
'maintenance_spare_part_consumptions',
'maintenance_failure_reports',
'maintenance_activity_logs',
'maintenance_notifications',
'maintenance_inspection_visits',
'maintenance_service_records',
'maintenance_part_replacements',
'maintenance_history_entries',
'maintenance_asset_documents',
'maintenance_checklist_templates',
'maintenance_production_lines',
'maintenance_part_catalogs',
'maintenance_service_providers',
];
/** @var array<int, string> */
protected array $ensureMigrations = [
'2026_07_07_170000_ensure_missing_cmms_tables',
'2026_07_07_160000_ensure_maintenance_lifecycle_tables',
'2026_07_07_150000_ensure_maintenance_asset_documents_table',
'2026_07_07_180000_fix_spare_parts_and_service_contracts',
'2026_06_30_200005_fix_maintenance_morph_types',
'2026_06_30_200006_inspection_visit_project_scope',
'2026_06_30_200007_maintenance_client_and_scope',
'2026_07_07_190000_fix_equipment_scope_columns',
];
public function assess(): array
{
$missing = [];
$present = [];
foreach ($this->requiredTables as $table) {
if (Schema::hasTable($table)) {
$present[] = $table;
} else {
$missing[] = $table;
}
}
$score = count($this->requiredTables) > 0
? (int) round((count($present) / count($this->requiredTables)) * 100)
: 100;
return [
'healthy' => empty($missing),
'score' => $score,
'present_count' => count($present),
'required_count' => count($this->requiredTables),
'missing_tables' => $missing,
'present_tables' => $present,
'integrations' => $this->assessIntegrations(),
];
}
public function repair(): array
{
$before = $this->assess();
$ran = [];
$errors = [];
foreach ($this->ensureMigrations as $migration) {
$path = "Modules/Maintenance/Database/Migrations/{$migration}.php";
if (! file_exists(base_path($path))) {
continue;
}
try {
Artisan::call('migrate', [
'--path' => $path,
'--force' => true,
]);
$ran[] = $migration;
} catch (\Throwable $e) {
$errors[] = $migration.': '.$e->getMessage();
}
}
Artisan::call('optimize:clear');
$after = $this->assess();
return [
'before' => $before,
'after' => $after,
'migrations_ran' => $ran,
'errors' => $errors,
'repaired' => $after['healthy'] || $after['score'] > $before['score'],
];
}
protected function assessIntegrations(): array
{
return [
'industrial_engineering' => class_exists(\Modules\IndustrialEngineering\Models\LineTemplate::class),
'asset_management' => class_exists(\Modules\AssetManagement\Entities\Asset::class),
'accounting' => class_exists(\Modules\Accounting\Entities\AccountingAccTransMapping::class),
'manufacturing' => class_exists(\Modules\Manufacturing\Entities\MfgRecipe::class)
|| class_exists(\Modules\Manufacturing\Http\Controllers\ProductionController::class),
'project' => Schema::hasTable('pjt_projects'),
'erp_products' => Schema::hasTable('products'),
];
}
}