*/ public static function entities(): array { return [ // ── Master Data ────────────────────────────────────────────── 'manufacturer' => [ 'table' => 'ie_manufacturers', 'model' => \Modules\IndustrialEngineering\Models\Manufacturer::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => true, 'description' => 'Approved manufacturer / OEM catalog entry.', ], 'supplier' => [ 'table' => 'ie_suppliers', 'model' => \Modules\IndustrialEngineering\Models\Supplier::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => true, 'description' => 'Approved vendor; may link to contacts or intercompany business.', ], 'item_master' => [ 'table' => 'ie_item_masters', 'model' => \Modules\IndustrialEngineering\Models\ItemMaster::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => true, 'description' => 'Canonical industrial item (part, assembly, device, etc.).', ], 'item_revision' => [ 'table' => 'ie_item_revisions', 'model' => \Modules\IndustrialEngineering\Models\ItemRevision::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => false, 'description' => 'Versioned engineering definition of an item master.', ], 'supplier_part_number' => [ 'table' => 'ie_supplier_part_numbers', 'model' => \Modules\IndustrialEngineering\Models\SupplierPartNumber::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => false, 'description' => 'AVL/AML supplier part number and commercial terms.', ], 'part_equivalent' => [ 'table' => 'ie_part_equivalents', 'model' => \Modules\IndustrialEngineering\Models\PartEquivalent::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => false, 'description' => 'Approved alternate items (form-fit-function, functional, upgrade).', ], 'item_classification' => [ 'table' => 'ie_item_classifications', 'model' => \Modules\IndustrialEngineering\Models\ItemClassification::class, 'context' => BoundedContext::MASTER_DATA, 'aggregate_root' => false, 'description' => 'Taxonomy mapping to industrial category seeders.', ], // ── BOM & Configuration ────────────────────────────────────── 'product_platform' => [ 'table' => 'ie_product_platforms', 'model' => \Modules\IndustrialEngineering\Models\ProductPlatform::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => true, 'description' => 'Product / production-line family.', ], 'line_template' => [ 'table' => 'ie_line_templates', 'model' => \Modules\IndustrialEngineering\Models\LineTemplate::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => false, 'description' => 'Configurable line or machine template within a platform.', ], 'line_revision' => [ 'table' => 'ie_line_revisions', 'model' => \Modules\IndustrialEngineering\Models\LineRevision::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => true, 'description' => 'Official approved/released version of a line template.', ], 'bom' => [ 'table' => 'ie_boms', 'model' => \Modules\IndustrialEngineering\Models\Bom::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => true, 'description' => 'EBOM, MBOM, or SBOM header (distinct but linked by line revision).', ], 'bom_line' => [ 'table' => 'ie_bom_lines', 'model' => \Modules\IndustrialEngineering\Models\BomLine::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => false, 'description' => 'Multi-level BOM line with alternates, costing, and routing refs.', ], 'bom_line_alternate' => [ 'table' => 'ie_bom_line_alternates', 'model' => \Modules\IndustrialEngineering\Models\BomLineAlternate::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => false, 'description' => 'Approved substitute within an alternate group.', ], 'bom_change_request' => [ 'table' => 'ie_bom_change_requests', 'model' => \Modules\IndustrialEngineering\Models\BomChangeRequest::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => true, 'description' => 'ECR – engineering change request.', ], 'bom_change_order' => [ 'table' => 'ie_bom_change_orders', 'model' => \Modules\IndustrialEngineering\Models\BomChangeOrder::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => true, 'description' => 'ECO – approved implementation of a change request.', ], 'bom_effectivity' => [ 'table' => 'ie_bom_effectivities', 'model' => \Modules\IndustrialEngineering\Models\BomEffectivity::class, 'context' => BoundedContext::BOM_CONFIGURATION, 'aggregate_root' => false, 'description' => 'Effectivity rules (date, serial, customer, project, revision).', ], // ── Costing & Release ──────────────────────────────────────── 'work_center' => [ 'table' => 'ie_work_centers', 'model' => \Modules\IndustrialEngineering\Models\WorkCenter::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => true, 'description' => 'Machine/labor/overhead rates for routing.', ], 'routing_operation' => [ 'table' => 'ie_routing_operations', 'model' => \Modules\IndustrialEngineering\Models\RoutingOperation::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => false, 'description' => 'Sequence of operations for a line revision.', ], 'cost_scenario' => [ 'table' => 'ie_cost_scenarios', 'model' => \Modules\IndustrialEngineering\Models\CostScenario::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => true, 'description' => 'What-if or baseline cost rollup for a BOM/line revision.', ], 'cost_scenario_line' => [ 'table' => 'ie_cost_scenario_lines', 'model' => \Modules\IndustrialEngineering\Models\CostScenarioLine::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => false, 'description' => 'Per-line cost with optional alternate selection.', ], 'release_package' => [ 'table' => 'ie_release_packages', 'model' => \Modules\IndustrialEngineering\Models\ReleasePackage::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => true, 'description' => 'Locked MBOM/routing/cost snapshot approved for production.', ], 'release_signoff' => [ 'table' => 'ie_release_signoffs', 'model' => \Modules\IndustrialEngineering\Models\ReleaseSignoff::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => false, 'description' => 'Multi-discipline approval on a release package.', ], 'manufacturing_work_order' => [ 'table' => 'ie_manufacturing_work_orders', 'model' => \Modules\IndustrialEngineering\Models\ManufacturingWorkOrder::class, 'context' => BoundedContext::COSTING_RELEASE, 'aggregate_root' => true, 'description' => 'Shop-floor work order with frozen BOM/routing snapshot.', ], // ── Serialization & As-Built ───────────────────────────────── 'serial_registry' => [ 'table' => 'ie_serial_registry', 'model' => \Modules\IndustrialEngineering\Models\SerialRegistry::class, 'context' => BoundedContext::SERIALIZATION, 'aggregate_root' => true, 'description' => 'Global serial/lot registry for units and components.', ], 'serialized_unit' => [ 'table' => 'ie_serialized_units', 'model' => \Modules\IndustrialEngineering\Models\SerializedUnit::class, 'context' => BoundedContext::SERIALIZATION, 'aggregate_root' => true, 'description' => 'As-built unit built from a release package / work order.', ], 'serialized_unit_component' => [ 'table' => 'ie_serialized_unit_components', 'model' => \Modules\IndustrialEngineering\Models\SerializedUnitComponent::class, 'context' => BoundedContext::SERIALIZATION, 'aggregate_root' => false, 'description' => 'Installed component genealogy (serial, brand, warranty).', ], 'build_genealogy_event' => [ 'table' => 'ie_build_genealogy_events', 'model' => \Modules\IndustrialEngineering\Models\BuildGenealogyEvent::class, 'context' => BoundedContext::SERIALIZATION, 'aggregate_root' => false, 'description' => 'Immutable audit event during build or QC.', ], // ── Installed Base ─────────────────────────────────────────── 'customer_installed_asset' => [ 'table' => 'ie_customer_installed_assets', 'model' => \Modules\IndustrialEngineering\Models\CustomerInstalledAsset::class, 'context' => BoundedContext::INSTALLED_BASE, 'aggregate_root' => true, 'description' => 'As-sold / as-installed customer line or device.', ], 'customer_asset_warranty' => [ 'table' => 'ie_customer_asset_warranties', 'model' => \Modules\IndustrialEngineering\Models\CustomerAssetWarranty::class, 'context' => BoundedContext::INSTALLED_BASE, 'aggregate_root' => false, 'description' => 'Warranty coverage at asset or component level.', ], 'commissioning_record' => [ 'table' => 'ie_commissioning_records', 'model' => \Modules\IndustrialEngineering\Models\CommissioningRecord::class, 'context' => BoundedContext::INSTALLED_BASE, 'aggregate_root' => true, 'description' => 'Commissioning checklist and handover documents.', ], 'installation_task' => [ 'table' => 'ie_installation_tasks', 'model' => \Modules\IndustrialEngineering\Models\InstallationTask::class, 'context' => BoundedContext::INSTALLED_BASE, 'aggregate_root' => false, 'description' => 'Install/commission/training task on an installed asset.', ], // ── Sourcing ───────────────────────────────────────────────── 'intercompany_stock_visibility' => [ 'table' => 'ie_intercompany_stock_visibility', 'model' => \Modules\IndustrialEngineering\Models\IntercompanyStockVisibility::class, 'context' => BoundedContext::SOURCING, 'aggregate_root' => false, 'description' => 'Cached cross-company stock availability for an item.', ], 'intercompany_transfer_request' => [ 'table' => 'ie_intercompany_transfer_requests', 'model' => \Modules\IndustrialEngineering\Models\IntercompanyTransferRequest::class, 'context' => BoundedContext::SOURCING, 'aggregate_root' => true, 'description' => 'Internal transfer request between holding companies.', ], 'supplier_sourcing_case' => [ 'table' => 'ie_supplier_sourcing_cases', 'model' => \Modules\IndustrialEngineering\Models\SupplierSourcingCase::class, 'context' => BoundedContext::SOURCING, 'aggregate_root' => true, 'description' => 'Sourcing case when part not available in holding.', ], 'vendor_quote_comparison' => [ 'table' => 'ie_vendor_quote_comparisons', 'model' => \Modules\IndustrialEngineering\Models\VendorQuoteComparison::class, 'context' => BoundedContext::SOURCING, 'aggregate_root' => false, 'description' => 'Vendor quotes ranked for a sourcing case.', ], 'procurement_task' => [ 'table' => 'ie_procurement_tasks', 'model' => \Modules\IndustrialEngineering\Models\ProcurementTask::class, 'context' => BoundedContext::SOURCING, 'aggregate_root' => false, 'description' => 'Actionable procurement step (quote, PR, PO, transfer).', ], // ── Competitive Research ───────────────────────────────────── 'research_project' => [ 'table' => 'ie_research_projects', 'model' => \Modules\IndustrialEngineering\Models\ResearchProject::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => true, 'description' => 'R&D or competitive intelligence project.', ], 'competitive_product' => [ 'table' => 'ie_competitive_products', 'model' => \Modules\IndustrialEngineering\Models\CompetitiveProduct::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => true, 'description' => 'Competitor product under study.', ], 'competitive_product_structure' => [ 'table' => 'ie_competitive_product_structures', 'model' => \Modules\IndustrialEngineering\Models\CompetitiveProductStructure::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => false, 'description' => 'Multi-level teardown structure of a competitor product.', ], 'competitive_benchmark' => [ 'table' => 'ie_competitive_benchmarks', 'model' => \Modules\IndustrialEngineering\Models\CompetitiveBenchmark::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => false, 'description' => 'Metric comparison (cost, quality, lead time) vs our line.', ], 'engineering_finding' => [ 'table' => 'ie_engineering_findings', 'model' => \Modules\IndustrialEngineering\Models\EngineeringFinding::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => false, 'description' => 'Finding linked to research, ECR, or cost scenario.', ], 'lessons_learned' => [ 'table' => 'ie_lessons_learned', 'model' => \Modules\IndustrialEngineering\Models\LessonsLearned::class, 'context' => BoundedContext::COMPETITIVE_RESEARCH, 'aggregate_root' => false, 'description' => 'Captured lesson from research or field installation.', ], ]; } /** * External tables owned by other modules; IE must not duplicate their data. * * @return array * }> */ public static function externalBoundaries(): array { return [ 'erp_product' => [ 'module' => 'Core', 'table' => 'products', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => null, 'fk_columns' => ['ie_item_masters.product_id' => 'products.id'], ], 'erp_variation' => [ 'module' => 'Core', 'table' => 'variations', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => null, 'fk_columns' => ['ie_item_masters.variation_id' => 'variations.id'], ], 'erp_contact' => [ 'module' => 'Core', 'table' => 'contacts', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => null, 'fk_columns' => [ 'ie_suppliers.contact_id' => 'contacts.id', 'ie_customer_installed_assets.customer_id' => 'contacts.id', 'ie_bom_effectivities.customer_id' => 'contacts.id', ], ], 'erp_transaction' => [ 'module' => 'Core', 'table' => 'transactions', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => 'IntegrationBridgeService::linkSaleToInstalledAsset', 'fk_columns' => [ 'ie_manufacturing_work_orders.production_transaction_id' => 'transactions.id', 'ie_serialized_units.production_transaction_id' => 'transactions.id', 'ie_customer_installed_assets.sell_transaction_id' => 'transactions.id', 'ie_procurement_tasks.purchase_requisition_id' => 'transactions.id', ], ], 'erp_sell_line' => [ 'module' => 'Core', 'table' => 'transaction_sell_lines', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => 'IntegrationBridgeService::linkSaleToInstalledAsset', 'fk_columns' => [ 'ie_customer_installed_assets.sell_line_id' => 'transaction_sell_lines.id', ], ], 'erp_project' => [ 'module' => 'Project', 'table' => 'pjt_projects', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => null, 'fk_columns' => [ 'ie_customer_installed_assets.project_id' => 'pjt_projects.id', 'ie_research_projects.project_id' => 'pjt_projects.id', 'ie_bom_effectivities.project_id' => 'pjt_projects.id', ], ], 'maintenance_equipment' => [ 'module' => 'Maintenance', 'table' => 'maintenance_equipment', 'mode' => IntegrationMode::WRITE_THROUGH_BRIDGE, 'bridge' => 'IntegrationBridgeService::syncToMaintenanceEquipment', 'fk_columns' => [ 'ie_customer_installed_assets.maintenance_equipment_id' => 'maintenance_equipment.id', ], ], 'maintenance_equipment_parts' => [ 'module' => 'Maintenance', 'table' => 'maintenance_equipment_parts', 'mode' => IntegrationMode::WRITE_THROUGH_BRIDGE, 'bridge' => 'IntegrationBridgeService::syncComponentsToEquipmentParts', 'fk_columns' => [], ], 'maintenance_part_catalogs' => [ 'module' => 'Maintenance', 'table' => 'maintenance_part_catalogs', 'mode' => IntegrationMode::WRITE_THROUGH_BRIDGE, 'bridge' => 'IntegrationBridgeService::syncComponentsToEquipmentParts', 'fk_columns' => [], ], 'mfg_recipe' => [ 'module' => 'Manufacturing', 'table' => 'mfg_recipes', 'mode' => IntegrationMode::IMPORT_BRIDGE, 'bridge' => 'IntegrationBridgeService::importMfgRecipeToMbom', 'fk_columns' => [], ], 'asset_exchange_listing' => [ 'module' => 'AssetExchange', 'table' => 'aex_listings', 'mode' => IntegrationMode::READ_REFERENCE, 'bridge' => 'AssetExchangeIeBridgeService::resolveBomForListing', 'fk_columns' => [ 'aex_listings.ie_line_template_id' => 'ie_line_templates.id', 'aex_listings.ie_line_revision_id' => 'ie_line_revisions.id', 'aex_listings.ie_bom_id' => 'ie_boms.id', 'aex_listings.ie_installed_asset_id' => 'ie_customer_installed_assets.id', 'aex_listings.maintenance_equipment_id' => 'maintenance_equipment.id', ], ], ]; } /** * Digital-thread flow: which contexts feed the next stage. * * @return array> */ public static function contextFlow(): array { return [ BoundedContext::MASTER_DATA => [BoundedContext::BOM_CONFIGURATION], BoundedContext::BOM_CONFIGURATION => [BoundedContext::COSTING_RELEASE], BoundedContext::COSTING_RELEASE => [BoundedContext::SERIALIZATION], BoundedContext::SERIALIZATION => [BoundedContext::INSTALLED_BASE], BoundedContext::INSTALLED_BASE => [BoundedContext::SOURCING], BoundedContext::COMPETITIVE_RESEARCH => [ BoundedContext::BOM_CONFIGURATION, BoundedContext::COSTING_RELEASE, ], ]; } public static function tablePrefix(): string { return 'ie_'; } public static function moduleName(): string { return 'IndustrialEngineering'; } /** * @return array */ public static function tablesForContext(string $context): array { return array_values(array_map( fn (array $entity) => $entity['table'], array_filter(self::entities(), fn (array $e) => $e['context'] === $context) )); } public static function entityForTable(string $table): ?array { foreach (self::entities() as $key => $entity) { if ($entity['table'] === $table) { return array_merge(['key' => $key], $entity); } } return null; } /** * @return array */ public static function allTables(): array { return array_values(array_map(fn (array $e) => $e['table'], self::entities())); } /** * @return array */ public static function allModelClasses(): array { return array_values(array_filter( array_map(fn (array $e) => $e['model'], self::entities()) )); } }