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

240 lines
10 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 = 0; $i < 3; $i++) {
$customers[] = User::create([
'name' => $faker->company . ' (Customer)',
'email' => $faker->unique()->safeEmail,
'password' => bcrypt('password'),
'user_type' => 'customer',
]);
}
$this->command->info('Seeding Contractors...');
$specializations = ['General Building', 'MEP', 'Civil Works', 'Landscaping', 'Interior Fit-out'];
$contractors = [];
for ($i = 0; $i < 5; $i++) {
$contractors[] = Contractor::create([
'company_name' => $faker->company . ' Construction',
'contact_person' => $faker->name,
'email' => $faker->companyEmail,
'phone' => $faker->phoneNumber,
'specialization' => $faker->randomElement($specializations),
'address' => $faker->address,
'tax_id' => $faker->numerify('TAX-####-####'),
'payment_terms' => $faker->randomElement(['Net 30', 'Net 60', 'Upon Completion']),
'rating' => $faker->randomFloat(1, 3, 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' => $faker->sentence]
);
}
$this->command->info('Seeding Projects...');
$statuses = [
ProjectStatus::Planning,
ProjectStatus::InProgress,
ProjectStatus::Completed,
ProjectStatus::OnHold
];
for ($i = 0; $i < 10; $i++) {
$contractor = $faker->randomElement($contractors);
$customer = $faker->randomElement($customers);
$startDate = $faker->dateTimeBetween('-1 year', '-1 month');
$endDate = (clone $startDate)->modify('+' . $faker->numberBetween(3, 24) . ' months');
$project = Project::create([
'name' => 'Project ' . ucwords($faker->word) . ' ' . $faker->city,
'description' => $faker->paragraph,
'customer_id' => $customer->id,
'client_name' => $customer->name,
'contractor_id' => $contractor->id,
'location' => $faker->address,
'status' => $faker->randomElement($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,
]);
$contractor->projects()->attach($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()->attach($pm->id, ['role' => 'pm']);
}
}
// Seed Tasks for this Project
for ($t = 0; $t < 5; $t++) {
Task::create([
'project_id' => $project->id,
'name' => $faker->sentence(3),
'description' => $faker->paragraph,
'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 = 0; $r < 2; $r++) {
DailyReport::create([
'project_id' => $project->id,
'user_id' => $customers[0]->id, // Use any user as creator for demo
'report_number' => 'DR-' . $project->id . '-' . ($r + 1),
'report_date' => $faker->dateTimeBetween($startDate, 'now')->format('Y-m-d'),
'weather' => $faker->randomElement(['Sunny', 'Cloudy', 'Rainy']),
'temperature' => $faker->numberBetween(20, 35) . 'C',
'work_accomplished' => $faker->paragraph,
]);
}
}
// Seed Documents for this Project
for ($d = 0; $d < 3; $d++) {
$cat = $faker->randomElement($docCategories);
Document::create([
'title' => $faker->words(3, true),
'category_id' => $cat->id,
'project_id' => $project->id,
'status' => $faker->randomElement(['Pending', 'Approved']),
'description' => $faker->sentence,
'file_size' => $faker->numberBetween(1024, 10485760), // 1KB to 10MB
'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];
for ($b = 0; $b < 3; $b++) {
$proj = $faker->randomElement($projectsList ?? Project::all()->all());
if (!$proj) continue;
$package = \Modules\BiddingManagement\Models\BidPackage::firstOrCreate(
['title' => 'Bid Package ' . $faker->words(2, true) . ' - ' . $proj->name],
[
'project_id' => $proj->id,
'created_by' => $customers[0]->id,
'description' => $faker->paragraph,
'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!');
}
}