id(); LegacyForeignKeys::business($table); LegacyForeignKeys::project($table); $table->string('code'); $table->string('name'); $table->text('description')->nullable(); $table->string('location')->nullable(); $table->string('status')->default('active'); $table->timestamps(); $table->softDeletes(); $table->unique(['business_id', 'code'], 'mnt_line_biz_code_uq'); $table->index(['business_id', 'project_id'], 'mnt_line_biz_proj_idx'); }); Schema::create('maintenance_part_catalogs', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->string('catalog_code'); $table->string('name'); $table->string('manufacturer')->nullable(); $table->string('manufacturer_part_number')->nullable(); $table->string('part_type')->default('mechanical'); // mechanical, electronic, consumable, hydraulic, pneumatic $table->boolean('is_consumable')->default(false); $table->text('description')->nullable(); $table->json('specifications')->nullable(); $table->unsignedInteger('default_replacement_interval_days')->nullable(); $table->boolean('is_oem')->default(true); $table->json('equivalent_parts')->nullable(); $table->string('status')->default('active'); $table->timestamps(); $table->softDeletes(); $table->unique(['business_id', 'catalog_code'], 'mnt_cat_biz_code_uq'); }); Schema::create('maintenance_service_providers', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->string('name'); $table->string('provider_type')->default('external'); // internal, external $table->string('capability')->default('both'); // repair, commissioning, both $table->json('specialties')->nullable(); $table->string('phone')->nullable(); $table->string('email')->nullable(); LegacyForeignKeys::user($table, 'linked_user_id'); $table->text('notes')->nullable(); $table->boolean('is_active')->default(true); $table->timestamps(); $table->softDeletes(); }); Schema::table('maintenance_equipment', function (Blueprint $table) { if (! Schema::hasColumn('maintenance_equipment', 'production_line_id')) { $table->foreignId('production_line_id')->nullable()->after('category_id') ->constrained('maintenance_production_lines')->nullOnDelete(); } }); Schema::table('maintenance_equipment_parts', function (Blueprint $table) { if (! Schema::hasColumn('maintenance_equipment_parts', 'parent_id')) { $table->foreignId('parent_id')->nullable()->after('equipment_id') ->constrained('maintenance_equipment_parts')->nullOnDelete(); } if (! Schema::hasColumn('maintenance_equipment_parts', 'part_catalog_id')) { $table->foreignId('part_catalog_id')->nullable()->after('spare_part_id') ->constrained('maintenance_part_catalogs')->nullOnDelete(); } $cols = [ 'part_type' => fn ($t) => $t->string('part_type')->default('mechanical')->after('unit'), 'is_consumable' => fn ($t) => $t->boolean('is_consumable')->default(false)->after('part_type'), 'responsibility' => fn ($t) => $t->string('responsibility')->default('ours')->after('is_consumable'), 'responsibility_party_name' => fn ($t) => $t->string('responsibility_party_name')->nullable()->after('responsibility'), 'warranty_status' => fn ($t) => $t->string('warranty_status')->default('none')->after('responsibility_party_name'), 'warranty_provider' => fn ($t) => $t->string('warranty_provider')->nullable()->after('warranty_status'), 'warranty_expires_at' => fn ($t) => $t->date('warranty_expires_at')->nullable()->after('warranty_provider'), 'installed_by' => fn ($t) => $t->string('installed_by')->nullable()->after('warranty_expires_at'), 'installer_name' => fn ($t) => $t->string('installer_name')->nullable()->after('installed_by'), 'expected_replacement_date' => fn ($t) => $t->date('expected_replacement_date')->nullable()->after('installer_name'), 'replacement_interval_days' => fn ($t) => $t->unsignedInteger('replacement_interval_days')->nullable()->after('expected_replacement_date'), 'last_replaced_at' => fn ($t) => $t->date('last_replaced_at')->nullable()->after('replacement_interval_days'), 'replacement_quality_grade' => fn ($t) => $t->string('replacement_quality_grade')->nullable()->after('last_replaced_at'), 'damage_action' => fn ($t) => $t->string('damage_action')->nullable()->after('replacement_quality_grade'), 'damage_service_list' => fn ($t) => $t->json('damage_service_list')->nullable()->after('damage_action'), 'multi_year_service_plan' => fn ($t) => $t->json('multi_year_service_plan')->nullable()->after('damage_service_list'), 'health_percentage' => fn ($t) => $t->decimal('health_percentage', 5, 2)->nullable()->after('multi_year_service_plan'), ]; foreach ($cols as $col => $callback) { if (! Schema::hasColumn('maintenance_equipment_parts', $col)) { Schema::table('maintenance_equipment_parts', $callback); } } }); Schema::create('maintenance_asset_documents', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->string('documentable_type'); $table->unsignedBigInteger('documentable_id'); $table->string('doc_type'); // datasheet, catalog, installation_manual, etc. $table->string('title'); $table->string('file_path')->nullable(); $table->string('file_url')->nullable(); $table->string('mime_type')->nullable(); $table->string('language')->default('fa'); $table->string('version')->nullable(); $table->date('effective_date')->nullable(); LegacyForeignKeys::user($table, 'uploaded_by'); $table->text('notes')->nullable(); $table->unsignedInteger('sort_order')->default(0); $table->timestamps(); $table->index(['documentable_type', 'documentable_id'], 'mnt_doc_morph_idx'); $table->index(['business_id', 'doc_type'], 'mnt_doc_biz_type_idx'); }); Schema::create('maintenance_approvals', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->string('approvable_type'); $table->unsignedBigInteger('approvable_id'); $table->string('approval_type'); // signature_canvas, signature_photo, stamp_photo $table->longText('signature_data')->nullable(); $table->string('photo_path')->nullable(); LegacyForeignKeys::user($table, 'approver_id'); $table->string('approver_name')->nullable(); $table->string('approver_role')->nullable(); $table->timestamp('approved_at')->nullable(); $table->text('notes')->nullable(); $table->timestamps(); $table->index(['approvable_type', 'approvable_id'], 'mnt_appr_morph_idx'); }); Schema::create('maintenance_inspection_visits', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->foreignId('equipment_id')->constrained('maintenance_equipment')->cascadeOnDelete(); $table->foreignId('production_line_id')->nullable()->constrained('maintenance_production_lines')->nullOnDelete(); $table->timestamp('visit_date'); $table->decimal('health_percentage', 5, 2)->nullable(); $table->decimal('working_hours_at_visit', 12, 2)->nullable(); $table->string('visit_type')->default('routine'); $table->foreignId('checklist_response_id')->nullable()->constrained('maintenance_checklist_responses')->nullOnDelete(); LegacyForeignKeys::user($table, 'inspector_id'); $table->foreignId('service_provider_id')->nullable()->constrained('maintenance_service_providers')->nullOnDelete(); $table->text('summary')->nullable(); $table->json('attachments')->nullable(); $table->foreignId('approval_id')->nullable()->constrained('maintenance_approvals')->nullOnDelete(); $table->string('status')->default('draft'); // draft, completed, approved $table->timestamps(); $table->index(['business_id', 'equipment_id'], 'mnt_insp_biz_eq_idx'); }); Schema::create('maintenance_inspection_visit_items', function (Blueprint $table) { $table->id(); $table->foreignId('inspection_visit_id')->constrained('maintenance_inspection_visits')->cascadeOnDelete(); $table->foreignId('equipment_part_id')->nullable()->constrained('maintenance_equipment_parts')->nullOnDelete(); $table->string('part_label'); $table->decimal('health_percentage', 5, 2)->nullable(); $table->string('condition')->nullable(); // good, fair, poor, critical $table->text('notes')->nullable(); $table->json('photos')->nullable(); $table->boolean('needs_replacement')->default(false); $table->date('expected_replacement_date')->nullable(); $table->timestamps(); }); Schema::create('maintenance_service_records', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->foreignId('equipment_id')->constrained('maintenance_equipment')->cascadeOnDelete(); $table->foreignId('work_order_id')->nullable()->constrained('maintenance_work_orders')->nullOnDelete(); $table->foreignId('overhaul_id')->nullable()->constrained('maintenance_overhauls')->nullOnDelete(); $table->string('service_type'); // minor, major, overhaul $table->string('title'); $table->text('description')->nullable(); $table->timestamp('started_at')->nullable(); $table->timestamp('completed_at')->nullable(); $table->decimal('labor_hours', 8, 2)->nullable(); $table->unsignedBigInteger('cost')->default(0); LegacyForeignKeys::user($table, 'performed_by'); $table->foreignId('repair_provider_id')->nullable()->constrained('maintenance_service_providers')->nullOnDelete(); $table->foreignId('commissioning_provider_id')->nullable()->constrained('maintenance_service_providers')->nullOnDelete(); $table->decimal('health_before', 5, 2)->nullable(); $table->decimal('health_after', 5, 2)->nullable(); $table->foreignId('approval_id')->nullable()->constrained('maintenance_approvals')->nullOnDelete(); $table->string('status')->default('draft'); $table->timestamps(); $table->index(['business_id', 'equipment_id'], 'mnt_svc_biz_eq_idx'); }); Schema::create('maintenance_service_record_items', function (Blueprint $table) { $table->id(); $table->foreignId('service_record_id')->constrained('maintenance_service_records')->cascadeOnDelete(); $table->foreignId('equipment_part_id')->nullable()->constrained('maintenance_equipment_parts')->nullOnDelete(); $table->string('part_label')->nullable(); $table->string('action'); // replaced, repaired, adjusted, cleaned, inspected $table->decimal('quantity', 12, 3)->default(1); $table->string('replacement_quality_grade')->nullable(); $table->text('notes')->nullable(); $table->timestamps(); }); Schema::create('maintenance_part_replacements', function (Blueprint $table) { $table->id(); LegacyForeignKeys::business($table); $table->foreignId('equipment_id')->constrained('maintenance_equipment')->cascadeOnDelete(); $table->foreignId('equipment_part_id')->nullable()->constrained('maintenance_equipment_parts')->nullOnDelete(); $table->foreignId('spare_part_id')->nullable()->constrained('maintenance_spare_parts')->nullOnDelete(); $table->date('replaced_at'); $table->decimal('quantity', 12, 3)->default(1); $table->string('action')->default('replaced'); $table->decimal('health_before', 5, 2)->nullable(); $table->decimal('health_after', 5, 2)->nullable(); $table->string('replacement_quality_grade')->nullable(); LegacyForeignKeys::user($table, 'performed_by'); $table->foreignId('service_record_id')->nullable()->constrained('maintenance_service_records')->nullOnDelete(); $table->foreignId('approval_id')->nullable()->constrained('maintenance_approvals')->nullOnDelete(); $table->text('notes')->nullable(); $table->timestamps(); $table->index(['equipment_id', 'equipment_part_id'], 'mnt_repl_eq_part_idx'); }); } public function down(): void { Schema::dropIfExists('maintenance_part_replacements'); Schema::dropIfExists('maintenance_service_record_items'); Schema::dropIfExists('maintenance_service_records'); Schema::dropIfExists('maintenance_inspection_visit_items'); Schema::dropIfExists('maintenance_inspection_visits'); Schema::dropIfExists('maintenance_approvals'); Schema::dropIfExists('maintenance_asset_documents'); Schema::table('maintenance_equipment_parts', function (Blueprint $table) { foreach (['parent_id', 'part_catalog_id', 'part_type', 'is_consumable', 'responsibility', 'responsibility_party_name', 'warranty_status', 'warranty_provider', 'warranty_expires_at', 'installed_by', 'installer_name', 'expected_replacement_date', 'replacement_interval_days', 'last_replaced_at', 'replacement_quality_grade', 'damage_action', 'damage_service_list', 'multi_year_service_plan', 'health_percentage'] as $col) { if (Schema::hasColumn('maintenance_equipment_parts', $col)) { if (in_array($col, ['parent_id', 'part_catalog_id'])) { $table->dropConstrainedForeignId($col); } else { $table->dropColumn($col); } } } }); Schema::table('maintenance_equipment', function (Blueprint $table) { if (Schema::hasColumn('maintenance_equipment', 'production_line_id')) { $table->dropConstrainedForeignId('production_line_id'); } }); Schema::dropIfExists('maintenance_service_providers'); Schema::dropIfExists('maintenance_asset_documents'); Schema::dropIfExists('maintenance_part_catalogs'); Schema::dropIfExists('maintenance_production_lines'); } };