240 lines
10 KiB
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!');
|
|
}
|
|
}
|