'Test Company', 'email' => 'company_' . rand(1000, 9999) . '@test.com', 'password' => bcrypt('password'), 'type' => 'company', ]); // 2. Create an Employee user $employee = User::create([ 'name' => 'Test Employee', 'email' => 'employee_' . rand(1000, 9999) . '@test.com', 'password' => bcrypt('password'), 'type' => 'employee', ]); // 3. Create a Payroll Run $payrollRun = PayrollRun::create([ 'title' => 'June 11-25 2026', 'payroll_frequency' => 'semi-monthly', 'pay_period_start' => '2026-06-11', 'pay_period_end' => '2026-06-25', 'pay_date' => '2026-06-30', 'status' => 'draft', 'created_by' => $company->id, ]); // 4. Create a Payroll Entry simulating the old bug state (0 in DB columns, but OT present in JSON) $earningsBreakdown = [ 'basic_salary' => 10000.00, 'summary' => [ 'days_worked' => 10, 'reg_ot_hours' => '3.50', 'reg_ot_amount' => 450.75, ] ]; $entry = PayrollEntry::create([ 'payroll_run_id' => $payrollRun->id, 'employee_id' => $employee->id, 'basic_salary' => 10000.00, 'component_earnings' => 450.75, 'total_earnings' => 10450.75, 'total_deductions' => 0.00, 'gross_pay' => 10450.75, 'net_pay' => 10450.75, 'working_days' => 10, 'present_days' => 10, 'full_present_days' => 10, 'half_days' => 0, 'holiday_days' => 0, 'paid_leave_days' => 0, 'unpaid_leave_days' => 0, 'absent_days' => 0, 'overtime_hours' => 0.00, // old bugged default 'overtime_amount' => 0.00, // old bugged default 'per_day_salary' => 1000.00, 'earnings_breakdown' => $earningsBreakdown, 'deductions_breakdown' => [], 'created_by' => $company->id, ]); // 5. Run the migration logic manually to test the update $migration = require database_path('migrations/2026_06_26_150000_backfill_payroll_entry_overtime.php'); $migration->up(); // 6. Assert that values have been backfilled correctly $freshEntry = $entry->fresh(); expect((float)$freshEntry->overtime_hours)->toBe(3.50); expect((float)$freshEntry->overtime_amount)->toBe(450.75); });