diff --git a/app/Http/Controllers/Api/Admin/HR/EmployeeSalaryController.php b/app/Http/Controllers/Api/Admin/HR/EmployeeSalaryController.php
index 417eb39e..76a4b543 100644
--- a/app/Http/Controllers/Api/Admin/HR/EmployeeSalaryController.php
+++ b/app/Http/Controllers/Api/Admin/HR/EmployeeSalaryController.php
@@ -61,6 +61,8 @@ public function update(Request $request, int $id): JsonResponse
$validated = $request->validate([
'annual_salary' => 'nullable|integer|min:0',
+ 'meal_allowance' => 'nullable|integer|min:0|max:1000000',
+ 'fixed_overtime_hours' => 'nullable|integer|min:0|max:100',
'effective_date' => 'nullable|date',
'notes' => 'nullable|string|max:500',
]);
diff --git a/app/Models/HR/Employee.php b/app/Models/HR/Employee.php
index 9550cc74..083a544c 100644
--- a/app/Models/HR/Employee.php
+++ b/app/Models/HR/Employee.php
@@ -180,12 +180,24 @@ public function setJsonExtraValue(string $key, mixed $value): void
public function getSalaryInfo(): array
{
- return $this->json_extra['salary_info'] ?? [
+ $defaults = [
'annual_salary' => null,
'effective_date' => null,
'notes' => null,
+ 'fixed_overtime_hours' => null,
+ 'meal_allowance' => 200000,
+ 'monthly_salary' => null,
+ 'base_salary' => null,
+ 'fixed_overtime_pay' => null,
+ 'hourly_wage' => null,
+ 'monthly_work_hours' => 209,
+ 'overtime_multiplier' => 1.5,
'history' => [],
];
+
+ $data = $this->json_extra['salary_info'] ?? [];
+
+ return array_merge($defaults, $data);
}
public function setSalaryInfo(array $data): void
@@ -197,6 +209,10 @@ public function setSalaryInfo(array $data): void
if ($current['annual_salary'] !== null) {
$history[] = [
'annual_salary' => $current['annual_salary'],
+ 'fixed_overtime_hours' => $current['fixed_overtime_hours'],
+ 'meal_allowance' => $current['meal_allowance'],
+ 'base_salary' => $current['base_salary'],
+ 'fixed_overtime_pay' => $current['fixed_overtime_pay'],
'effective_date' => $current['effective_date'],
'notes' => $current['notes'],
'recorded_at' => now()->format('Y-m-d H:i:s'),
@@ -204,12 +220,56 @@ public function setSalaryInfo(array $data): void
];
}
- $this->setJsonExtraValue('salary_info', [
- 'annual_salary' => $data['annual_salary'] ?? null,
+ $annualSalary = $data['annual_salary'] ?? null;
+ $mealAllowance = $data['meal_allowance'] ?? 200000;
+ $fixedOvertimeHours = $data['fixed_overtime_hours'] ?? null;
+ $breakdown = $this->calculateSalaryBreakdown($annualSalary, $mealAllowance, $fixedOvertimeHours);
+
+ $this->setJsonExtraValue('salary_info', array_merge([
+ 'annual_salary' => $annualSalary,
'effective_date' => $data['effective_date'] ?? null,
'notes' => $data['notes'] ?? null,
- 'history' => $history,
- ]);
+ 'fixed_overtime_hours' => $fixedOvertimeHours,
+ 'meal_allowance' => $mealAllowance,
+ ], $breakdown, ['history' => $history]));
+ }
+
+ /**
+ * 급여 산정 계산
+ *
+ * 공식: (기본급 + 식대) = 월급여 × 209 / (209 + 고정연장근로시간 × 1.5)
+ */
+ private function calculateSalaryBreakdown(?int $annualSalary, int $mealAllowance, ?int $fixedOvertimeHours): array
+ {
+ $monthlyWorkHours = 209;
+ $overtimeMultiplier = 1.5;
+
+ if (! $annualSalary) {
+ return [
+ 'monthly_salary' => null,
+ 'base_salary' => null,
+ 'fixed_overtime_pay' => null,
+ 'hourly_wage' => null,
+ 'monthly_work_hours' => $monthlyWorkHours,
+ 'overtime_multiplier' => $overtimeMultiplier,
+ ];
+ }
+
+ $monthlySalary = (int) round($annualSalary / 12);
+ $otFactor = ($fixedOvertimeHours ?? 0) * $overtimeMultiplier;
+ $basePlusMeal = (int) round($monthlySalary * $monthlyWorkHours / ($monthlyWorkHours + $otFactor));
+ $baseSalary = $basePlusMeal - $mealAllowance;
+ $hourlyWage = (int) floor($basePlusMeal / $monthlyWorkHours);
+ $fixedOvertimePay = $monthlySalary - $baseSalary - $mealAllowance;
+
+ return [
+ 'monthly_salary' => $monthlySalary,
+ 'base_salary' => $baseSalary,
+ 'fixed_overtime_pay' => $fixedOvertimePay,
+ 'hourly_wage' => $hourlyWage,
+ 'monthly_work_hours' => $monthlyWorkHours,
+ 'overtime_multiplier' => $overtimeMultiplier,
+ ];
}
/**
diff --git a/resources/views/hr/employees/partials/salary-info.blade.php b/resources/views/hr/employees/partials/salary-info.blade.php
index f53dc51c..be157734 100644
--- a/resources/views/hr/employees/partials/salary-info.blade.php
+++ b/resources/views/hr/employees/partials/salary-info.blade.php
@@ -26,51 +26,245 @@ class="inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-lg
+ {{-- ============================================================ --}}
{{-- 조회 모드 --}}
-
-
-
연봉
-
-
-
-
-
- 미입력
-
+ {{-- ============================================================ --}}
+
+ {{-- 기본 연봉 정보 --}}
+
+
+
연봉
+
+
+
+
+
+ 미입력
+
+
+
+
+
-
-
+
+ {{-- 급여 산정 테이블 (저장된 데이터가 있을 때) --}}
+
+
+
+ 급여 산정 내역
+
+
+ {{-- 요약 테이블 --}}
+
+
+
+
+
+ | 총급여(연봉) |
+ 기본급 |
+ 식대 |
+ 고정연장근로수당 |
+ 합계(월) |
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+ {{-- 상세 산정 내역 --}}
+
+
+
+
+
+ | 월급여 |
+ |
+ |
+
+
+ | 기본급 |
+ |
+ |
+
+
+ | 식대 |
+ |
+ 고정값 |
+
+
+ | 월 근로시간 |
+ |
+ 고정값 |
+
+
+ | 월 고정연장근로시간 |
+ |
+ 변동값 |
+
+
+ | 통상시급 |
+ |
+ (기본급+식대) / 209, 연차수당 계산시 적용시급 |
+
+
+ | 연장근로수당배수 |
+ |
+ |
+
+
+ | 고정연장근로수당 |
+ |
+ 통상시급 x 월고정연장근로시간 x 연장근로수당배수 |
+
+
+
+
+
+
+
+ {{-- ============================================================ --}}
{{-- 수정 모드 --}}
+ {{-- ============================================================ --}}
-
-
-
-
+ {{-- 입력 필드 --}}
+
+
+
+
+
+
+
+
+
비과세 한도: 200,000원
+
+
+
+
+
변동값 (사원별 상이)
+
-
-
-
-
-
-
-
+
+
+ {{-- 실시간 급여 산정 미리보기 --}}
+
+
+
급여 산정 미리보기
+
+ {{-- 요약 테이블 --}}
+
+
+
+
+ | 총급여(연봉) |
+ 기본급 |
+ 식대 |
+ 고정연장근로수당 |
+ 합계(월) |
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+ {{-- 상세 산정 내역 --}}
+
+
+
+
+ | 월급여 |
+ |
+ |
+
+
+ | 기본급 |
+ |
+ |
+
+
+ | 식대 |
+ |
+ 고정값 |
+
+
+ | 월 근로시간 |
+ 209 |
+ 고정값 |
+
+
+ | 월 고정연장근로시간 |
+ |
+ 변동값 |
+
+
+ | 통상시급 |
+ |
+ (기본급+식대) / 209, 연차수당 계산시 적용시급 |
+
+
+ | 연장근로수당배수 |
+ 1.5 |
+ |
+
+
+ | 고정연장근로수당 |
+ |
+ 통상시급 x 월고정연장근로시간 x 연장근로수당배수 |
+
+
+
+
+
+
+
+
+ {{-- 버튼 --}}
+ {{-- ============================================================ --}}
{{-- 연봉 변경 이력 --}}
+ {{-- ============================================================ --}}
@@ -96,6 +292,7 @@ class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-
| 연봉 |
+ 고정OT시간 |
적용일 |
비고 |
기록일 |
@@ -107,6 +304,7 @@ class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-
|
+ |
|
|
|
@@ -134,17 +332,47 @@ class="inline-flex items-center justify-center w-7 h-7 rounded text-red-400 hove
@push('scripts')