118 lines
4.3 KiB
PHP
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),
|
|
]);
|
|
}
|
|
}
|
|
}
|