diff --git a/database/seeders/DemoProjectContractorSeeder.php b/database/seeders/DemoProjectContractorSeeder.php index b80e87f..7ddd34e 100644 --- a/database/seeders/DemoProjectContractorSeeder.php +++ b/database/seeders/DemoProjectContractorSeeder.php @@ -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++) { diff --git a/package-lock.json b/package-lock.json index 1a7e900..9ac8ce9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": {