Files
nnterp-react-admin/database/seeders/DemoUtilizationSeeder.php
2026-03-14 12:52:18 +08:00

118 lines
4.3 KiB
PHP

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DemoUtilizationSeeder extends Seeder
{
public function run(DemoContext $ctx): void
{
if (DB::table('time_entries')->where('created_by', $ctx->userId)->exists()) {
return;
}
$types = ['billable', 'non_billable', 'internal', 'training'];
$today = now();
// 1. Time Entries — 2 months of data across employees
foreach ($ctx->employeeUserIds as $empUserId) {
for ($d = 60; $d >= 1; $d--) {
$date = $today->copy()->subDays($d);
if ($date->isWeekend()) continue;
$numEntries = rand(1, 3);
for ($e = 0; $e < $numEntries; $e++) {
$type = $types[array_rand($types)];
$engId = !empty($ctx->engagementIds) && $type === 'billable'
? $ctx->engagementIds[array_rand($ctx->engagementIds)]
: null;
DB::table('time_entries')->insert([
'user_id' => $empUserId,
'engagement_id' => $engId,
'date' => $date->format('Y-m-d'),
'hours' => round(rand(10, 40) / 10, 1), // 1.0 - 4.0 hours
'type' => $type,
'description' => ucfirst($type) . ' work',
'is_billable' => $type === 'billable',
'created_by' => $ctx->userId,
'created_at' => $date,
'updated_at' => $date,
]);
}
}
}
// 2. Utilization Targets (per employee per current month)
$period = $today->format('Y-m');
foreach ($ctx->employeeUserIds as $empUserId) {
DB::table('utilization_targets')->insert([
'user_id' => $empUserId,
'period' => $period,
'target_pct' => rand(70, 85),
'available_hours' => 168,
'created_by' => $ctx->userId,
'created_at' => now(),
'updated_at' => now(),
]);
}
// 3. Cost Rates (hourly cost/bill rates)
foreach ($ctx->employeeUserIds as $empUserId) {
$costRate = rand(300, 800);
DB::table('cost_rates')->insert([
'user_id' => $empUserId,
'cost_rate' => $costRate,
'bill_rate' => round($costRate * rand(18, 25) / 10),
'effective_date' => now()->subMonths(6)->format('Y-m-d'),
'created_by' => $ctx->userId,
'created_at' => now(),
'updated_at' => now(),
]);
}
// 4. Utilization Rules
$ruleIds = [];
$ruleIds[] = DB::table('utilization_rules')->insertGetId([
'name' => 'Low Utilization Alert',
'metric' => 'utilization_pct',
'operator' => '<',
'threshold' => 60,
'action' => 'flag',
'is_active' => true,
'created_by' => $ctx->userId,
'created_at' => now(),
'updated_at' => now(),
]);
$ruleIds[] = DB::table('utilization_rules')->insertGetId([
'name' => 'High Billable Target',
'metric' => 'billable_pct',
'operator' => '>',
'threshold' => 90,
'action' => 'dashboard_alert',
'is_active' => true,
'created_by' => $ctx->userId,
'created_at' => now(),
'updated_at' => now(),
]);
// 5. Pre-generated Alerts
foreach (array_slice($ctx->employeeUserIds, 0, 2) as $empUserId) {
$empName = DB::table('users')->where('id', $empUserId)->value('name') ?? 'Employee';
DB::table('utilization_alerts')->insert([
'rule_id' => $ruleIds[0],
'user_id' => $empUserId,
'message' => "$empName: Utilization is 48% (< 60%)",
'period' => $today->subMonth()->format('Y-m'),
'value' => 48.0,
'is_read' => false,
'created_at' => now()->subDays(5),
'updated_at' => now()->subDays(5),
]);
}
}
}