Enhance DemoProjectContractorSeeder with realistic names, milestone generation, and fix contractor linking for TenantScope

This commit is contained in:
2026-05-25 13:56:31 +08:00
parent 5cbaec5d17
commit e1cd383ce3
2 changed files with 64 additions and 12 deletions

View File

@@ -57,6 +57,7 @@ class DemoProjectContractorSeeder extends Seeder
'rating' => 4.5,
'status' => 'active',
'type' => 'sub',
'parent_id' => \Modules\ContractorManagement\Models\Contractor::where('type', 'main')->value('id') ?? null,
]
);
}
@@ -106,6 +107,18 @@ class DemoProjectContractorSeeder extends Seeder
ProjectStatus::OnHold
];
$projectNames = [
'Skyline Tower Construction', 'Riverside Commercial Complex', 'Green Valley Residential Estate',
'Harbor View Bridge Expansion', 'Downtown Plaza Renovation', 'Metro Hospital Annex',
'Tech Park Office Building', 'Sunrise Shopping Mall', 'Highway 95 Repaving', 'Central Station Modernization'
];
$taskNames = [
'Site Clearing and Preparation', 'Excavation and Trenching', 'Foundation Concrete Pouring',
'Steel Framework Erection', 'Plumbing Rough-in', 'Electrical Wiring Installation',
'HVAC System Setup', 'Roofing and Waterproofing', 'Interior Drywall Installation', 'Painting and Finishing'
];
for ($i = 1; $i <= 10; $i++) {
$contractor = $contractors[array_rand($contractors)];
$customer = $customers[array_rand($customers)];
@@ -113,10 +126,11 @@ class DemoProjectContractorSeeder extends Seeder
$startDate = $faker->dateTimeBetween('-1 year', '-1 month');
$endDate = (clone $startDate)->modify('+' . $faker->numberBetween(3, 24) . ' months');
$projectName = $projectNames[$i - 1];
$project = Project::firstOrCreate(
['name' => "Demo Project {$i}"],
['name' => $projectName],
[
'description' => "This is a generated demo project for testing.",
'description' => "Construction project for {$projectName}.",
'customer_id' => $customer->id,
'client_name' => $customer->name,
'contractor_id' => $contractor->id,
@@ -145,11 +159,12 @@ class DemoProjectContractorSeeder extends Seeder
}
// Seed Tasks for this Project
for ($t = 1; $t <= 5; $t++) {
$selectedTasks = $faker->randomElements($taskNames, 5);
foreach ($selectedTasks as $t => $taskName) {
Task::firstOrCreate(
['project_id' => $project->id, 'name' => "Task {$t} for Project {$i}"],
['project_id' => $project->id, 'name' => $taskName],
[
'description' => "Demo task {$t} description",
'description' => "Execution of {$taskName}",
'status' => $faker->randomElement([TaskStatus::Pending, TaskStatus::InProgress, TaskStatus::Completed]),
'estimated_hours' => $faker->numberBetween(10, 100),
'start_date' => $startDate->format('Y-m-d'),
@@ -158,6 +173,39 @@ class DemoProjectContractorSeeder extends Seeder
);
}
// Seed Milestones
if ($project->milestones()->count() === 0) {
$defaults = [
['name' => 'Mobilization', 'weight_percentage' => 5],
['name' => 'Earthworks & Foundation', 'weight_percentage' => 15],
['name' => 'Structural Works', 'weight_percentage' => 25],
['name' => 'Roofing & Waterproofing', 'weight_percentage' => 15],
['name' => 'Architectural Finishing', 'weight_percentage' => 20],
['name' => 'MEP Rough-In', 'weight_percentage' => 10],
['name' => 'Final Inspection & Punch List', 'weight_percentage' => 5],
['name' => 'Turnover', 'weight_percentage' => 5],
];
$duration = $project->contract_duration;
$count = count($defaults);
foreach ($defaults as $idx => $milestone) {
$plannedDate = null;
if ($startDate && $duration && $duration > 0) {
$daysOffset = (int) round(($idx + 1) / $count * $duration * 30); // duration is in months, approx * 30 days
$plannedDate = (clone $startDate)->modify("+{$daysOffset} days");
}
$project->milestones()->create([
'name' => $milestone['name'],
'weight_percentage' => $milestone['weight_percentage'],
'sort_order' => $idx,
'is_default' => true,
'planned_date' => $plannedDate,
]);
}
}
// Seed Daily Reports for this Project (if InProgress)
if ($project->status === ProjectStatus::InProgress) {
for ($r = 1; $r <= 2; $r++) {

18
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{
"name": "gsb-cons",
"name": "gsbconstruction",
"lockfileVersion": 3,
"requires": true,
"packages": {
@@ -2449,7 +2449,7 @@
"version": "18.19.130",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
@@ -2459,14 +2459,14 @@
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
"devOptional": true,
"dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.28",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
"devOptional": true,
"dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -3205,7 +3205,7 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"devOptional": true,
"dev": true,
"license": "MIT"
},
"node_modules/data-uri-to-buffer": {
@@ -4909,6 +4909,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -5736,6 +5737,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
@@ -5748,6 +5750,7 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
@@ -6003,6 +6006,7 @@
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
@@ -6627,7 +6631,7 @@
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -6641,7 +6645,7 @@
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"devOptional": true,
"dev": true,
"license": "MIT"
},
"node_modules/unicorn-magic": {