@php
$dashboardDailyCostRowsSource = is_array($dashboardDailyCostRows ?? null) ? $dashboardDailyCostRows : [];
$expenseDailyBudgetSource = is_array($payrollExpenseWidget['daily_budget'] ?? null) ? $payrollExpenseWidget['daily_budget'] : [];
$expenseDailyByDate = collect($expenseDailyBudgetSource)->keyBy(fn ($row) => (string) ($row['date'] ?? ''));
$attendanceDates = is_array($dashSeries['dates'] ?? null) ? $dashSeries['dates'] : [];
$attendanceOnTime = is_array($morningSeries['checkin_ontime'] ?? null) ? $morningSeries['checkin_ontime'] : [];
$attendanceLatePre = is_array($morningSeries['checkin_late_precheck'] ?? null) ? $morningSeries['checkin_late_precheck'] : [];
$attendanceLateGrace = is_array($morningSeries['checkin_late_grace'] ?? null) ? $morningSeries['checkin_late_grace'] : [];
$attendanceNonShift = is_array($morningSeries['checkin_nonshift'] ?? null) ? $morningSeries['checkin_nonshift'] : [];
$attendanceWeekendHoliday = is_array($morningSeries['checkin_lembur'] ?? null) ? $morningSeries['checkin_lembur'] : [];
$attendanceCuti = is_array($morningSeries['cuti'] ?? null) ? $morningSeries['cuti'] : [];
$attendanceSick = is_array($morningSeries['sick'] ?? null) ? $morningSeries['sick'] : [];
$attendanceAlpha = is_array($morningSeries['missing_checkin_due'] ?? null) ? $morningSeries['missing_checkin_due'] : [];
$estimateCount = max(1, (int) ($payrollExpenseWidget['estimate_count'] ?? 0));
$fallbackDailyEmployeeCost = (float) ($payrollExpenseWidget['estimate_net'] ?? 0) > 0
? ((float) ($payrollExpenseWidget['estimate_net'] ?? 0) / $estimateCount / max(1, count($expenseDailyBudgetSource)))
: 0.0;
$dailyCostRows = $dashboardDailyCostRowsSource;
foreach ($attendanceDates as $i => $attendanceDate) {
if ($dashboardDailyCostRowsSource !== []) {
break;
}
$sourceBudget = (array) ($expenseDailyByDate->get((string) $attendanceDate) ?? ($expenseDailyBudgetSource[$i] ?? []));
$hadirCount = (int) (($attendanceOnTime[$i] ?? 0) + ($attendanceLatePre[$i] ?? 0) + ($attendanceLateGrace[$i] ?? 0) + ($attendanceNonShift[$i] ?? 0) + ($attendanceWeekendHoliday[$i] ?? 0));
$leavePaidCount = (int) (($attendanceCuti[$i] ?? 0) + ($attendanceSick[$i] ?? 0));
$alphaCount = (int) ($attendanceAlpha[$i] ?? 0);
$paidCount = $hadirCount + $leavePaidCount;
$sourceEmployeeCount = max(1, (int) ($sourceBudget['employee_count'] ?? 0));
$employeeCostPerDay = (float) ($sourceBudget['net'] ?? 0) > 0
? ((float) ($sourceBudget['net'] ?? 0) / $sourceEmployeeCount)
: $fallbackDailyEmployeeCost;
$pph21PerDay = (float) ($sourceBudget['pph21'] ?? 0) > 0 ? ((float) ($sourceBudget['pph21'] ?? 0) / $sourceEmployeeCount) : 0.0;
$bpjsPerDay = (float) ($sourceBudget['bpjs'] ?? 0) > 0 ? ((float) ($sourceBudget['bpjs'] ?? 0) / $sourceEmployeeCount) : 0.0;
$reimbursePerDay = (float) ($sourceBudget['reimburse'] ?? 0) > 0 ? ((float) ($sourceBudget['reimburse'] ?? 0) / $sourceEmployeeCount) : 0.0;
$dailyCostRows[] = array_merge($sourceBudget, [
'date' => (string) $attendanceDate,
'day' => substr((string) $attendanceDate, -2),
'mode' => (string) ($sourceBudget['mode'] ?? 'attendance_based'),
'label' => 'Attendance cost: hadir + leave paid, alpha tidak dibayar',
'employee_count' => $paidCount,
'hadir_count' => $hadirCount,
'leave_paid_count' => $leavePaidCount,
'alpha_count' => $alphaCount,
'net' => round($employeeCostPerDay * $paidCount, 2),
'net_hadir' => round($employeeCostPerDay * $hadirCount, 2),
'net_leave_paid' => round($employeeCostPerDay * $leavePaidCount, 2),
'pph21' => round($pph21PerDay * $paidCount, 2),
'bpjs' => round($bpjsPerDay * $paidCount, 2),
'reimburse' => round($reimbursePerDay * $paidCount, 2),
]);
}
if (empty($dailyCostRows)) {
$dailyCostRows = $expenseDailyBudgetSource;
}
$dailyCostMax = 1.0;
$dailyCostTotals = [
'grand' => 0.0,
'employee' => 0.0,
'pph21' => 0.0,
'bpjs' => 0.0,
'reimburse' => 0.0,
];
$dailyCostActiveDays = 0;
$dailyCostActualDays = 0;
$dailyCostEstimateDays = 0;
foreach ($dailyCostRows as $costRow) {
$employeeCost = max(0.0, (float) ($costRow['net'] ?? 0));
$pph21Cost = max(0.0, (float) ($costRow['pph21'] ?? 0));
$bpjsCost = max(0.0, (float) ($costRow['bpjs'] ?? 0));
$reimburseCost = max(0.0, (float) ($costRow['reimburse'] ?? 0));
$grandCost = $employeeCost + $pph21Cost + $bpjsCost + $reimburseCost;
$dailyCostMax = max($dailyCostMax, $grandCost);
$dailyCostTotals['grand'] += $grandCost;
$dailyCostTotals['employee'] += $employeeCost;
$dailyCostTotals['pph21'] += $pph21Cost;
$dailyCostTotals['bpjs'] += $bpjsCost;
$dailyCostTotals['reimburse'] += $reimburseCost;
if (!empty($costRow['is_workday']) || $grandCost > 0) {
$dailyCostActiveDays++;
}
if (($costRow['mode'] ?? '') === 'actual') {
$dailyCostActualDays++;
} else {
$dailyCostEstimateDays++;
}
}
$dailyCostAvg = $dailyCostActiveDays > 0 ? $dailyCostTotals['grand'] / $dailyCostActiveDays : 0.0;
$dailyCostShort = function (float $value): string {
if ($value >= 1000000000) return 'Rp ' . number_format($value / 1000000000, 1, ',', '.') . 'M';
if ($value >= 1000000) return 'Rp ' . number_format($value / 1000000, 1, ',', '.') . 'Jt';
if ($value >= 1000) return 'Rp ' . number_format($value / 1000, 0, ',', '.') . 'Rb';
return 'Rp ' . number_format($value, 0, ',', '.');
};
@endphp
Daily Cost Overview
{{ $payrollExpenseWidget['profil_code'] ?? '-' }}
@if (!empty($payrollExpenseWidget['period_start']) && !empty($payrollExpenseWidget['period_end']))
| {{ $payrollExpenseWidget['period_start'] }} s/d {{ $payrollExpenseWidget['period_end'] }}
@endif
{{ number_format($dailyCostActualDays) }} actual / {{ number_format($dailyCostEstimateDays) }} estimasi
Rata-rata Cost / Day
{{ $dailyCostShort($dailyCostAvg) }}
Per tanggal - klik bar untuk detail karyawan dan komponen cost.
@if (!empty($dailyCostRows))
@php
$dailyCostChartRows = collect($dailyCostRows)->map(function ($costRow) use ($dailyCostShort, $payrollExpenseWidget) {
$employeeCost = max(0.0, (float) ($costRow['net'] ?? 0));
$hadirCost = max(0.0, (float) ($costRow['net_hadir'] ?? $employeeCost));
$leavePaidCost = max(0.0, (float) ($costRow['net_leave_paid'] ?? 0));
$pph21Cost = max(0.0, (float) ($costRow['pph21'] ?? 0));
$bpjsCost = max(0.0, (float) ($costRow['bpjs'] ?? 0));
$reimburseCost = max(0.0, (float) ($costRow['reimburse'] ?? 0));
$grandCost = $employeeCost + $pph21Cost + $bpjsCost + $reimburseCost;
$dateText = (string) ($costRow['date'] ?? '');
$dayName = $dateText !== '' ? \Carbon\Carbon::parse($dateText)->locale('id')->isoFormat('ddd') : '';
$payload = array_merge([
'kind' => 'payroll_daily_budget',
'profil_bulan_id' => (int) ($payrollExpenseWidget['profil_id'] ?? 0),
'grand_total' => round($grandCost, 2),
], $costRow);
return [
'label' => trim($dayName . ' ' . (string) ($costRow['day'] ?? '')),
'date' => $dateText,
'day_name' => $dayName,
'grand' => round($grandCost, 2),
'employee' => round($employeeCost, 2),
'hadir' => round($hadirCost, 2),
'leave_paid' => round($leavePaidCost, 2),
'pph21' => round($pph21Cost, 2),
'bpjs' => round($bpjsCost, 2),
'reimburse' => round($reimburseCost, 2),
'alpha_count' => (int) ($costRow['alpha_count'] ?? 0),
'hadir_count' => (int) ($costRow['hadir_count'] ?? 0),
'leave_paid_count' => (int) ($costRow['leave_paid_count'] ?? 0),
'is_workday' => !empty($costRow['is_workday']),
'is_today' => !empty($costRow['is_today']),
'short' => $dailyCostShort($grandCost),
'payload' => $payload,
];
})->values()->all();
@endphp
@else
Belum ada data daily payroll. Pilih profil payroll atau generate penggajian dulu.
@endif
LEGENDA
Cost
Grand total per hari
Mode
H = hadir, L = leave paid, A = alpha. Klik bar untuk detail personal.