Files
sam-api/database/seeders/ParametricBomSeeder.php

821 lines
29 KiB
PHP
Raw Normal View History

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Tenant;
use App\Models\User;
use App\Models\Category;
use App\Models\Product;
use App\Models\Material;
use App\Models\Design\DesignModel;
use App\Models\Design\ModelVersion;
use App\Models\Design\ModelParameter;
use App\Models\Design\ModelFormula;
use App\Models\Design\BomConditionRule;
use App\Models\Design\BomTemplate;
use App\Models\Design\BomTemplateItem;
use Illuminate\Support\Facades\Hash;
class ParametricBomSeeder extends Seeder
{
/**
* Run the database seeds for parametric BOM testing.
*/
public function run(): void
{
// Create test tenant
$tenant = Tenant::firstOrCreate(
['code' => '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
);
}
}
}