'TEST_TENANT'], [ 'name' => 'Test Tenant for Parametric BOM', 'description' => 'Tenant for testing parametric BOM system', 'is_active' => true ] ); // Create test user $user = User::firstOrCreate( ['email' => 'test@parametric-bom.com'], [ 'name' => 'Parametric BOM Test User', 'password' => Hash::make('password'), 'email_verified_at' => now() ] ); // Associate user with tenant if (!$user->tenants()->where('tenant_id', $tenant->id)->exists()) { $user->tenants()->attach($tenant->id, [ 'is_active' => true, 'is_default' => true ]); } // Create categories $screenCategory = Category::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => 'SCREEN_SYSTEMS' ], [ 'name' => 'Screen Door Systems', 'description' => 'Automatic screen door systems', 'is_active' => true ] ); $materialsCategory = Category::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => 'MATERIALS' ], [ 'name' => 'Raw Materials', 'description' => 'Raw materials and components', 'is_active' => true ] ); $componentsCategory = Category::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => 'COMPONENTS' ], [ 'name' => 'Components', 'description' => 'Manufactured components and parts', 'is_active' => true ] ); // Create test products $this->createTestProducts($tenant, $componentsCategory); // Create test materials $this->createTestMaterials($tenant, $materialsCategory); // Create design models $this->createDesignModels($tenant, $screenCategory); $this->command->info('Parametric BOM test data seeded successfully!'); } /** * Create test products */ private function createTestProducts(Tenant $tenant, Category $category): void { $products = [ [ 'code' => 'BRACKET_WALL_STD', 'name' => 'Standard Wall Bracket', 'description' => 'Standard mounting bracket for wall installation', 'unit' => 'EA', 'weight' => 0.5, 'color' => 'WHITE' ], [ 'code' => 'BRACKET_CEILING_STD', 'name' => 'Standard Ceiling Bracket', 'description' => 'Standard mounting bracket for ceiling installation', 'unit' => 'EA', 'weight' => 0.7, 'color' => 'WHITE' ], [ 'code' => 'MOTOR_DC_12V', 'name' => 'DC Motor 12V', 'description' => 'DC motor for screen operation, 12V', 'unit' => 'EA', 'weight' => 2.5, 'color' => 'BLACK' ], [ 'code' => 'MOTOR_DC_24V', 'name' => 'DC Motor 24V', 'description' => 'DC motor for screen operation, 24V (for larger screens)', 'unit' => 'EA', 'weight' => 3.2, 'color' => 'BLACK' ], [ 'code' => 'CONTROLLER_BASIC', 'name' => 'Basic Controller', 'description' => 'Basic remote controller for screen operation', 'unit' => 'EA', 'weight' => 0.2, 'color' => 'WHITE' ], [ 'code' => 'CONTROLLER_SMART', 'name' => 'Smart Controller', 'description' => 'Smart controller with app connectivity', 'unit' => 'EA', 'weight' => 0.3, 'color' => 'BLACK' ], [ 'code' => 'CASE_ALUMINUM', 'name' => 'Aluminum Case', 'description' => 'Aluminum housing case for screen mechanism', 'unit' => 'EA', 'weight' => 1.8, 'color' => 'SILVER' ], [ 'code' => 'CASE_PLASTIC', 'name' => 'Plastic Case', 'description' => 'Plastic housing case for screen mechanism', 'unit' => 'EA', 'weight' => 1.2, 'color' => 'WHITE' ] ]; foreach ($products as $productData) { Product::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => $productData['code'] ], array_merge($productData, [ 'category_id' => $category->id, 'is_active' => true, 'created_by' => 1 ]) ); } } /** * Create test materials */ private function createTestMaterials(Tenant $tenant, Category $category): void { $materials = [ [ 'code' => 'FABRIC_SCREEN_STD', 'name' => 'Standard Screen Fabric', 'description' => 'Standard fabric material for screen doors', 'unit' => 'M2', 'density' => 0.3, // kg/m2 'color' => 'GRAY' ], [ 'code' => 'FABRIC_SCREEN_PREMIUM', 'name' => 'Premium Screen Fabric', 'description' => 'Premium fabric material with enhanced durability', 'unit' => 'M2', 'density' => 0.4, 'color' => 'CHARCOAL' ], [ 'code' => 'STEEL_MESH_FINE', 'name' => 'Fine Steel Mesh', 'description' => 'Fine steel mesh for security screens', 'unit' => 'M2', 'density' => 2.5, 'color' => 'SILVER' ], [ 'code' => 'STEEL_MESH_COARSE', 'name' => 'Coarse Steel Mesh', 'description' => 'Coarse steel mesh for ventilation screens', 'unit' => 'M2', 'density' => 2.0, 'color' => 'SILVER' ], [ 'code' => 'RAIL_GUIDE_ALU', 'name' => 'Aluminum Guide Rail', 'description' => 'Aluminum guide rail for screen movement', 'unit' => 'M', 'density' => 0.8, // kg/m 'color' => 'SILVER' ], [ 'code' => 'RAIL_GUIDE_PLASTIC', 'name' => 'Plastic Guide Rail', 'description' => 'Plastic guide rail for lightweight screens', 'unit' => 'M', 'density' => 0.3, 'color' => 'WHITE' ], [ 'code' => 'CABLE_STEEL', 'name' => 'Steel Cable', 'description' => 'Steel cable for screen lifting mechanism', 'unit' => 'M', 'density' => 0.1, 'color' => 'SILVER' ], [ 'code' => 'SPRING_TENSION', 'name' => 'Tension Spring', 'description' => 'Spring for screen tension adjustment', 'unit' => 'EA', 'weight' => 0.05, 'color' => 'SILVER' ] ]; foreach ($materials as $materialData) { Material::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => $materialData['code'] ], array_merge($materialData, [ 'category_id' => $category->id, 'is_active' => true, 'created_by' => 1 ]) ); } } /** * Create design models with parameters, formulas, and rules */ private function createDesignModels(Tenant $tenant, Category $category): void { // Create basic screen door model $basicModel = DesignModel::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => 'BSD01' ], [ 'name' => 'Basic Screen Door', 'category_id' => $category->id, 'lifecycle' => 'ACTIVE', 'description' => 'Basic parametric screen door model for testing', 'is_active' => true ] ); $this->createModelParameters($tenant, $basicModel); $this->createModelFormulas($tenant, $basicModel); $this->createBomConditionRules($tenant, $basicModel); $this->createBomTemplate($tenant, $basicModel); // Create advanced screen door model $advancedModel = DesignModel::firstOrCreate( [ 'tenant_id' => $tenant->id, 'code' => 'ASD01' ], [ 'name' => 'Advanced Screen Door', 'category_id' => $category->id, 'lifecycle' => 'ACTIVE', 'description' => 'Advanced parametric screen door model with more features', 'is_active' => true ] ); $this->createAdvancedModelParameters($tenant, $advancedModel); $this->createAdvancedModelFormulas($tenant, $advancedModel); $this->createAdvancedBomConditionRules($tenant, $advancedModel); } /** * Create basic model parameters */ private function createModelParameters(Tenant $tenant, DesignModel $model): void { $parameters = [ [ 'parameter_name' => 'width', 'parameter_type' => 'NUMBER', 'is_required' => true, 'default_value' => '1000', 'min_value' => 500, 'max_value' => 3000, 'unit' => 'mm', 'description' => 'Screen width', 'sort_order' => 1 ], [ 'parameter_name' => 'height', 'parameter_type' => 'NUMBER', 'is_required' => true, 'default_value' => '2000', 'min_value' => 1000, 'max_value' => 3000, 'unit' => 'mm', 'description' => 'Screen height', 'sort_order' => 2 ], [ 'parameter_name' => 'screen_type', 'parameter_type' => 'SELECT', 'is_required' => true, 'default_value' => 'FABRIC', 'options' => ['FABRIC', 'STEEL_FINE', 'STEEL_COARSE'], 'description' => 'Type of screen material', 'sort_order' => 3 ], [ 'parameter_name' => 'installation_type', 'parameter_type' => 'SELECT', 'is_required' => true, 'default_value' => 'WALL', 'options' => ['WALL', 'CEILING', 'RECESSED'], 'description' => 'Installation method', 'sort_order' => 4 ], [ 'parameter_name' => 'motor_power', 'parameter_type' => 'SELECT', 'is_required' => false, 'default_value' => 'AUTO', 'options' => ['AUTO', '12V', '24V'], 'description' => 'Motor power selection (AUTO = based on size)', 'sort_order' => 5 ] ]; foreach ($parameters as $paramData) { ModelParameter::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'parameter_name' => $paramData['parameter_name'] ], $paramData ); } } /** * Create basic model formulas */ private function createModelFormulas(Tenant $tenant, DesignModel $model): void { $formulas = [ [ 'formula_name' => 'outer_width', 'expression' => 'width + 100', 'description' => 'Outer width including frame', 'sort_order' => 1 ], [ 'formula_name' => 'outer_height', 'expression' => 'height + 150', 'description' => 'Outer height including frame', 'sort_order' => 2 ], [ 'formula_name' => 'screen_area', 'expression' => '(width * height) / 1000000', 'description' => 'Screen area in square meters', 'sort_order' => 3 ], [ 'formula_name' => 'frame_perimeter', 'expression' => '(outer_width + outer_height) * 2 / 1000', 'description' => 'Frame perimeter in meters', 'sort_order' => 4 ], [ 'formula_name' => 'total_weight', 'expression' => 'screen_area * 0.5 + frame_perimeter * 0.8', 'description' => 'Estimated total weight in kg', 'sort_order' => 5 ] ]; foreach ($formulas as $formulaData) { ModelFormula::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'formula_name' => $formulaData['formula_name'] ], $formulaData ); } } /** * Create BOM condition rules for basic model */ private function createBomConditionRules(Tenant $tenant, DesignModel $model): void { $rules = [ // Motor selection based on size [ 'rule_name' => 'Large Screen Motor', 'condition_expression' => 'screen_area > 4.0 OR motor_power == "24V"', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'MOTOR_DC_24V')->first()->id, 'quantity_multiplier' => 1, 'description' => 'Use 24V motor for large screens', 'sort_order' => 1 ], [ 'rule_name' => 'Standard Screen Motor', 'condition_expression' => 'screen_area <= 4.0 AND motor_power != "24V"', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'MOTOR_DC_12V')->first()->id, 'quantity_multiplier' => 1, 'description' => 'Use 12V motor for standard screens', 'sort_order' => 2 ], // Screen material selection [ 'rule_name' => 'Fabric Screen Material', 'condition_expression' => 'screen_type == "FABRIC"', 'action_type' => 'INCLUDE', 'target_type' => 'MATERIAL', 'target_id' => Material::where('tenant_id', $tenant->id)->where('code', 'FABRIC_SCREEN_STD')->first()->id, 'quantity_multiplier' => 1.1, // 10% waste 'description' => 'Standard fabric screen material', 'sort_order' => 3 ], [ 'rule_name' => 'Fine Steel Screen Material', 'condition_expression' => 'screen_type == "STEEL_FINE"', 'action_type' => 'INCLUDE', 'target_type' => 'MATERIAL', 'target_id' => Material::where('tenant_id', $tenant->id)->where('code', 'STEEL_MESH_FINE')->first()->id, 'quantity_multiplier' => 1.05, // 5% waste 'description' => 'Fine steel mesh material', 'sort_order' => 4 ], // Bracket selection based on installation [ 'rule_name' => 'Wall Brackets', 'condition_expression' => 'installation_type == "WALL"', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'BRACKET_WALL_STD')->first()->id, 'quantity_multiplier' => 2, // Always 2 brackets 'description' => 'Wall mounting brackets', 'sort_order' => 5 ], [ 'rule_name' => 'Ceiling Brackets', 'condition_expression' => 'installation_type == "CEILING"', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'BRACKET_CEILING_STD')->first()->id, 'quantity_multiplier' => 2, 'description' => 'Ceiling mounting brackets', 'sort_order' => 6 ], // Extra brackets for wide screens [ 'rule_name' => 'Extra Brackets for Wide Screens', 'condition_expression' => 'width > 2000', 'action_type' => 'MODIFY_QUANTITY', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'BRACKET_WALL_STD')->first()->id, 'quantity_multiplier' => 1.5, // Add 50% more brackets 'description' => 'Additional brackets for wide screens', 'sort_order' => 7 ] ]; foreach ($rules as $ruleData) { BomConditionRule::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'rule_name' => $ruleData['rule_name'] ], $ruleData ); } } /** * Create BOM template for basic model */ private function createBomTemplate(Tenant $tenant, DesignModel $model): void { // Create model version first $modelVersion = ModelVersion::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'version_no' => '1.0' ], [ 'status' => 'RELEASED', 'description' => 'Initial release version', 'created_by' => 1 ] ); // Create BOM template $bomTemplate = BomTemplate::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_version_id' => $modelVersion->id, 'name' => 'Basic Screen Door BOM' ], [ 'description' => 'Base BOM template for basic screen door', 'is_active' => true, 'created_by' => 1 ] ); // Create BOM template items (base components always included) $baseItems = [ [ 'ref_type' => 'MATERIAL', 'ref_id' => Material::where('tenant_id', $tenant->id)->where('code', 'RAIL_GUIDE_ALU')->first()->id, 'quantity' => 1, // Will be calculated by formula 'waste_rate' => 5, 'order' => 1 ], [ 'ref_type' => 'MATERIAL', 'ref_id' => Material::where('tenant_id', $tenant->id)->where('code', 'CABLE_STEEL')->first()->id, 'quantity' => 2, // Height * 2 'waste_rate' => 10, 'order' => 2 ], [ 'ref_type' => 'MATERIAL', 'ref_id' => Material::where('tenant_id', $tenant->id)->where('code', 'SPRING_TENSION')->first()->id, 'quantity' => 2, 'waste_rate' => 0, 'order' => 3 ], [ 'ref_type' => 'PRODUCT', 'ref_id' => Product::where('tenant_id', $tenant->id)->where('code', 'CONTROLLER_BASIC')->first()->id, 'quantity' => 1, 'waste_rate' => 0, 'order' => 4 ], [ 'ref_type' => 'PRODUCT', 'ref_id' => Product::where('tenant_id', $tenant->id)->where('code', 'CASE_ALUMINUM')->first()->id, 'quantity' => 1, 'waste_rate' => 0, 'order' => 5 ] ]; foreach ($baseItems as $itemData) { BomTemplateItem::firstOrCreate( [ 'bom_template_id' => $bomTemplate->id, 'ref_type' => $itemData['ref_type'], 'ref_id' => $itemData['ref_id'], 'order' => $itemData['order'] ], $itemData ); } } /** * Create advanced model parameters */ private function createAdvancedModelParameters(Tenant $tenant, DesignModel $model): void { $parameters = [ [ 'parameter_name' => 'width', 'parameter_type' => 'NUMBER', 'is_required' => true, 'default_value' => '1200', 'min_value' => 600, 'max_value' => 4000, 'unit' => 'mm', 'description' => 'Screen width', 'sort_order' => 1 ], [ 'parameter_name' => 'height', 'parameter_type' => 'NUMBER', 'is_required' => true, 'default_value' => '2200', 'min_value' => 1200, 'max_value' => 3500, 'unit' => 'mm', 'description' => 'Screen height', 'sort_order' => 2 ], [ 'parameter_name' => 'screen_type', 'parameter_type' => 'SELECT', 'is_required' => true, 'default_value' => 'FABRIC_PREMIUM', 'options' => ['FABRIC_STD', 'FABRIC_PREMIUM', 'STEEL_FINE', 'STEEL_COARSE'], 'description' => 'Type of screen material', 'sort_order' => 3 ], [ 'parameter_name' => 'controller_type', 'parameter_type' => 'SELECT', 'is_required' => true, 'default_value' => 'SMART', 'options' => ['BASIC', 'SMART'], 'description' => 'Controller type', 'sort_order' => 4 ], [ 'parameter_name' => 'case_material', 'parameter_type' => 'SELECT', 'is_required' => true, 'default_value' => 'ALUMINUM', 'options' => ['ALUMINUM', 'PLASTIC'], 'description' => 'Case material', 'sort_order' => 5 ], [ 'parameter_name' => 'wind_resistance', 'parameter_type' => 'NUMBER', 'is_required' => false, 'default_value' => '80', 'min_value' => 40, 'max_value' => 120, 'unit' => 'km/h', 'description' => 'Required wind resistance', 'sort_order' => 6 ] ]; foreach ($parameters as $paramData) { ModelParameter::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'parameter_name' => $paramData['parameter_name'] ], $paramData ); } } /** * Create advanced model formulas */ private function createAdvancedModelFormulas(Tenant $tenant, DesignModel $model): void { $formulas = [ [ 'formula_name' => 'outer_width', 'expression' => 'width + 120', 'description' => 'Outer width including reinforced frame', 'sort_order' => 1 ], [ 'formula_name' => 'outer_height', 'expression' => 'height + 180', 'description' => 'Outer height including reinforced frame', 'sort_order' => 2 ], [ 'formula_name' => 'screen_area', 'expression' => '(width * height) / 1000000', 'description' => 'Screen area in square meters', 'sort_order' => 3 ], [ 'formula_name' => 'wind_load', 'expression' => 'screen_area * wind_resistance * 0.6', 'description' => 'Wind load calculation in Newtons', 'sort_order' => 4 ], [ 'formula_name' => 'required_motor_torque', 'expression' => 'wind_load * 0.1 + screen_area * 5', 'description' => 'Required motor torque in Nm', 'sort_order' => 5 ], [ 'formula_name' => 'frame_sections_count', 'expression' => 'ceiling(width / 600) + ceiling(height / 800)', 'description' => 'Number of frame sections needed', 'sort_order' => 6 ] ]; foreach ($formulas as $formulaData) { ModelFormula::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'formula_name' => $formulaData['formula_name'] ], $formulaData ); } } /** * Create advanced BOM condition rules */ private function createAdvancedBomConditionRules(Tenant $tenant, DesignModel $model): void { $rules = [ // Motor selection based on calculated torque [ 'rule_name' => 'High Torque Motor Required', 'condition_expression' => 'required_motor_torque > 15 OR wind_resistance > 100', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'MOTOR_DC_24V')->first()->id, 'quantity_multiplier' => 1, 'description' => 'Use high-power motor for demanding conditions', 'sort_order' => 1 ], // Screen material selection [ 'rule_name' => 'Premium Fabric Material', 'condition_expression' => 'screen_type == "FABRIC_PREMIUM"', 'action_type' => 'INCLUDE', 'target_type' => 'MATERIAL', 'target_id' => Material::where('tenant_id', $tenant->id)->where('code', 'FABRIC_SCREEN_PREMIUM')->first()->id, 'quantity_multiplier' => 1.05, 'description' => 'Premium fabric screen material', 'sort_order' => 2 ], // Controller selection [ 'rule_name' => 'Smart Controller', 'condition_expression' => 'controller_type == "SMART"', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'CONTROLLER_SMART')->first()->id, 'quantity_multiplier' => 1, 'description' => 'Smart controller with app connectivity', 'sort_order' => 3 ], // Case material selection [ 'rule_name' => 'Plastic Case for Light Duty', 'condition_expression' => 'case_material == "PLASTIC" AND wind_resistance <= 60', 'action_type' => 'INCLUDE', 'target_type' => 'PRODUCT', 'target_id' => Product::where('tenant_id', $tenant->id)->where('code', 'CASE_PLASTIC')->first()->id, 'quantity_multiplier' => 1, 'description' => 'Plastic case for light-duty applications', 'sort_order' => 4 ] ]; foreach ($rules as $ruleData) { BomConditionRule::firstOrCreate( [ 'tenant_id' => $tenant->id, 'model_id' => $model->id, 'rule_name' => $ruleData['rule_name'] ], $ruleData ); } } }