Files
GSB-Construction/database/seeders/DemoProjectContractorSeeder.php

252 lines
11 KiB
PHP

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use Modules\ContractorManagement\Models\Contractor;
use Modules\ProjectManagement\Models\Project;
use Modules\ProjectManagement\Models\Task;
use Modules\ProjectManagement\Enums\ProjectStatus;
use Modules\ProjectManagement\Enums\TaskStatus;
use Modules\DailyReports\Models\DailyReport;
use Modules\DocumentManagement\Models\Document;
use Modules\DocumentManagement\Models\DocumentCategory;
use Modules\MasterData\Models\Material;
use Modules\MaterialLogistics\Models\Warehouse;
use Modules\MaterialLogistics\Models\ProjectInventory;
use Faker\Factory as Faker;
use Illuminate\Support\Str;
class DemoProjectContractorSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$faker = Faker::create();
$this->command->info('Seeding Customers...');
$customers = [];
for ($i = 1; $i <= 3; $i++) {
$customers[] = User::firstOrCreate(
['email' => "customer{$i}@demo.com"],
[
'name' => "Demo Customer {$i}",
'password' => bcrypt('password'),
'user_type' => 'customer',
]
);
}
$this->command->info('Seeding Contractors...');
$specializations = ['General Building', 'MEP', 'Civil Works', 'Landscaping', 'Interior Fit-out'];
$contractors = [];
for ($i = 1; $i <= 5; $i++) {
$contractors[] = Contractor::firstOrCreate(
['email' => "contractor{$i}@demo.com"],
[
'company_name' => "Demo Contractor {$i}",
'contact_person' => $faker->name,
'phone' => $faker->phoneNumber,
'specialization' => $specializations[array_rand($specializations)],
'address' => $faker->address,
'tax_id' => $faker->numerify('TAX-####-####'),
'payment_terms' => 'Net 30',
'rating' => 4.5,
'status' => 'active',
'type' => 'sub',
]
);
}
$this->command->info('Seeding Materials Catalog...');
$materialNames = ['Portland Cement 40kg', 'Steel Rebar 12mm', 'Concrete Hollow Blocks 4"', 'Sand (per cu.m)', 'Gravel (per cu.m)', 'Plywood 1/2"', 'PVC Pipe 2"'];
$materials = [];
foreach ($materialNames as $mName) {
$materials[] = Material::firstOrCreate(
['name' => $mName],
[
'sku' => strtoupper(Str::random(8)),
'category' => 'Construction',
'unit' => $faker->randomElement(['pcs', 'bags', 'cu.m', 'length']),
'unit_cost' => $faker->randomFloat(2, 50, 1000),
'status' => 'active',
'type' => 'single',
]
);
}
$this->command->info('Seeding Main Warehouse...');
$warehouse = Warehouse::firstOrCreate(
['code' => 'WH-CEN-01'],
[
'name' => 'Central Depot',
'address' => $faker->address,
'type' => 'main',
'status' => 'active',
]
);
$this->command->info('Seeding Document Categories...');
$docCategories = [];
foreach (['Architectural', 'Structural', 'MEP', 'Permits', 'Contracts'] as $catName) {
$docCategories[] = DocumentCategory::firstOrCreate(
['name' => $catName],
['description' => "Standard $catName category"]
);
}
$this->command->info('Seeding Projects & Tasks...');
$statuses = [
ProjectStatus::Planning,
ProjectStatus::InProgress,
ProjectStatus::Completed,
ProjectStatus::OnHold
];
for ($i = 1; $i <= 10; $i++) {
$contractor = $contractors[array_rand($contractors)];
$customer = $customers[array_rand($customers)];
$startDate = $faker->dateTimeBetween('-1 year', '-1 month');
$endDate = (clone $startDate)->modify('+' . $faker->numberBetween(3, 24) . ' months');
$project = Project::firstOrCreate(
['name' => "Demo Project {$i}"],
[
'description' => "This is a generated demo project for testing.",
'customer_id' => $customer->id,
'client_name' => $customer->name,
'contractor_id' => $contractor->id,
'location' => $faker->address,
'status' => $statuses[array_rand($statuses)],
'contract_value' => $faker->randomFloat(2, 50000, 5000000),
'contract_duration' => $faker->numberBetween(3, 24),
'start_date' => $startDate->format('Y-m-d'),
'target_end_date' => $endDate->format('Y-m-d'),
'completion_percentage' => $faker->randomFloat(2, 0, 100),
'total_capitalization' => 0,
]
);
// Sync contractor relation safely
$contractor->projects()->syncWithoutDetaching([
$project->id => ['role' => 'Primary Contractor', 'contract_amount' => $project->contract_value]
]);
$pmRoleExists = \Spatie\Permission\Models\Role::where('name', 'Project Manager')->exists();
if ($pmRoleExists) {
$pm = User::role('Project Manager')->first();
if ($pm) {
$project->personnel()->syncWithoutDetaching([$pm->id => ['role' => 'pm']]);
}
}
// Seed Tasks for this Project
for ($t = 1; $t <= 5; $t++) {
Task::firstOrCreate(
['project_id' => $project->id, 'name' => "Task {$t} for Project {$i}"],
[
'description' => "Demo task {$t} description",
'status' => $faker->randomElement([TaskStatus::Pending, TaskStatus::InProgress, TaskStatus::Completed]),
'estimated_hours' => $faker->numberBetween(10, 100),
'start_date' => $startDate->format('Y-m-d'),
'end_date' => $endDate->format('Y-m-d'),
]
);
}
// Seed Daily Reports for this Project (if InProgress)
if ($project->status === ProjectStatus::InProgress) {
for ($r = 1; $r <= 2; $r++) {
DailyReport::firstOrCreate(
['project_id' => $project->id, 'report_number' => "DR-{$project->id}-{$r}"],
[
'user_id' => $customers[0]->id,
'report_date' => $faker->dateTimeBetween($startDate, 'now')->format('Y-m-d'),
'weather' => $faker->randomElement(['Sunny', 'Cloudy', 'Rainy']),
'temperature' => $faker->numberBetween(20, 35) . 'C',
'work_accomplished' => "Completed general works for the day.",
]
);
}
}
// Seed Documents for this Project
for ($d = 1; $d <= 3; $d++) {
$cat = $docCategories[array_rand($docCategories)];
Document::firstOrCreate(
['project_id' => $project->id, 'title' => "Document {$d} for Project {$i}"],
[
'category_id' => $cat->id,
'status' => $faker->randomElement(['Pending', 'Approved']),
'description' => "Sample attached document",
'file_size' => $faker->numberBetween(1024, 10485760),
'version_count' => 1,
'mime_type' => 'application/pdf',
]
);
}
// Seed Project Inventory
$selectedMats = $faker->randomElements($materials, 3);
foreach ($selectedMats as $mat) {
ProjectInventory::firstOrCreate(
['project_id' => $project->id, 'material_id' => $mat->id],
[
'on_hand_qty' => $faker->numberBetween(10, 500),
'unit_cost' => $mat->unit_cost,
]
);
}
}
$this->command->info('Seeding Bidding Packages...');
$bidStatuses = [\Modules\BiddingManagement\Enums\BidPackageStatus::Open, \Modules\BiddingManagement\Enums\BidPackageStatus::Evaluating, \Modules\BiddingManagement\Enums\BidPackageStatus::Awarded];
$allProjects = Project::all();
if ($allProjects->count() > 0) {
for ($b = 1; $b <= 3; $b++) {
$proj = $allProjects->random();
$package = \Modules\BiddingManagement\Models\BidPackage::firstOrCreate(
['title' => "Bid Package {$b} - {$proj->name}"],
[
'project_id' => $proj->id,
'created_by' => $customers[0]->id,
'description' => "Tender document for phase {$b}",
'status' => $faker->randomElement($bidStatuses),
'evaluation_mode' => \Modules\BiddingManagement\Enums\EvaluationMode::Simple,
'submission_deadline' => $faker->dateTimeBetween('now', '+1 month'),
'validity_period' => clone $faker->dateTimeBetween('+2 months', '+3 months'),
]
);
// Invite contractors
$invitedContractors = $faker->randomElements($contractors, 2);
foreach ($invitedContractors as $ic) {
$invitation = \Modules\BiddingManagement\Models\BidInvitation::firstOrCreate(
['bid_package_id' => $package->id, 'contractor_id' => $ic->id],
['status' => 'invited', 'invited_at' => now()]
);
// Add Submission
\Modules\BiddingManagement\Models\BidSubmission::firstOrCreate(
['bid_invitation_id' => $invitation->id],
[
'submitted_price' => $faker->randomFloat(2, 10000, 500000),
'completion_days' => $faker->numberBetween(30, 180),
'status' => \Modules\BiddingManagement\Enums\BidSubmissionStatus::Submitted,
'submitted_at' => now(),
]
);
}
}
}
$this->command->info('Demo Data seeded successfully across all modules!');
}
}