From 53c7f00340f0716667eb9bf93acde922e8e3886b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Fri, 27 Feb 2026 17:59:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[payroll]=20=EA=B8=89=EC=97=AC=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C=20(=EC=9D=B4=EB=A6=84=20=EA=B8=B0=EB=B0=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 허용 사용자: 이경호, 전진선, 김보곤 - 웹 컨트롤러: 미허용 시 안내 뷰 반환 - API 컨트롤러: 모든 엔드포인트에 403 반환 - restricted.blade.php 안내 페이지 생성 --- .../Api/Admin/HR/PayrollController.php | 68 ++++++++++++++++++- app/Http/Controllers/HR/PayrollController.php | 6 ++ .../views/hr/payrolls/restricted.blade.php | 17 +++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 resources/views/hr/payrolls/restricted.blade.php diff --git a/app/Http/Controllers/Api/Admin/HR/PayrollController.php b/app/Http/Controllers/Api/Admin/HR/PayrollController.php index 5d9a7e03..51aac929 100644 --- a/app/Http/Controllers/Api/Admin/HR/PayrollController.php +++ b/app/Http/Controllers/Api/Admin/HR/PayrollController.php @@ -12,15 +12,33 @@ class PayrollController extends Controller { + private const ALLOWED_PAYROLL_USERS = ['이경호', '전진선', '김보곤']; + public function __construct( private PayrollService $payrollService ) {} + private function checkPayrollAccess(): ?JsonResponse + { + if (! in_array(auth()->user()->name, self::ALLOWED_PAYROLL_USERS)) { + return response()->json([ + 'success' => false, + 'message' => '급여관리는 관계자만 볼 수 있습니다.', + ], 403); + } + + return null; + } + /** * 급여 목록 조회 (HTMX → HTML / 일반 → JSON) */ public function index(Request $request): JsonResponse|Response { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $payrolls = $this->payrollService->getPayrolls( $request->all(), $request->integer('per_page', 20) @@ -47,6 +65,10 @@ public function index(Request $request): JsonResponse|Response */ public function stats(Request $request): JsonResponse|Response { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $stats = $this->payrollService->getMonthlyStats( $request->integer('year') ?: null, $request->integer('month') ?: null @@ -67,6 +89,10 @@ public function stats(Request $request): JsonResponse|Response */ public function store(Request $request): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'pay_year' => 'required|integer|min:2020|max:2100', @@ -124,6 +150,10 @@ public function store(Request $request): JsonResponse */ public function update(Request $request, int $id): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'base_salary' => 'sometimes|required|numeric|min:0', 'overtime_pay' => 'nullable|numeric|min:0', @@ -175,6 +205,10 @@ public function update(Request $request, int $id): JsonResponse */ public function destroy(Request $request, int $id): JsonResponse|Response { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + try { $result = $this->payrollService->deletePayroll($id); @@ -214,6 +248,10 @@ public function destroy(Request $request, int $id): JsonResponse|Response */ public function confirm(Request $request, int $id): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + try { $payroll = $this->payrollService->confirmPayroll($id); @@ -245,6 +283,10 @@ public function confirm(Request $request, int $id): JsonResponse */ public function pay(Request $request, int $id): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + try { $payroll = $this->payrollService->payPayroll($id); @@ -276,6 +318,10 @@ public function pay(Request $request, int $id): JsonResponse */ public function copyFromPrevious(Request $request): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'pay_year' => 'required|integer|min:2020|max:2100', 'pay_month' => 'required|integer|min:1|max:12', @@ -315,6 +361,10 @@ public function copyFromPrevious(Request $request): JsonResponse */ public function bulkGenerate(Request $request): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'year' => 'required|integer|min:2020|max:2100', 'month' => 'required|integer|min:1|max:12', @@ -342,8 +392,12 @@ public function bulkGenerate(Request $request): JsonResponse /** * 엑셀(CSV) 내보내기 */ - public function export(Request $request): StreamedResponse + public function export(Request $request): StreamedResponse|JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $payrolls = $this->payrollService->getExportData($request->all()); $year = $request->input('year', now()->year); $month = $request->input('month', now()->month); @@ -392,6 +446,10 @@ public function export(Request $request): StreamedResponse */ public function settingsIndex(Request $request): JsonResponse|Response { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $settings = $this->payrollService->getSettings(); if ($request->header('HX-Request')) { @@ -409,6 +467,10 @@ public function settingsIndex(Request $request): JsonResponse|Response */ public function settingsUpdate(Request $request): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'health_insurance_rate' => 'nullable|numeric|min:0|max:100', 'long_term_care_rate' => 'nullable|numeric|min:0|max:100', @@ -444,6 +506,10 @@ public function settingsUpdate(Request $request): JsonResponse */ public function calculate(Request $request): JsonResponse { + if ($denied = $this->checkPayrollAccess()) { + return $denied; + } + $validated = $request->validate([ 'base_salary' => 'required|numeric|min:0', 'overtime_pay' => 'nullable|numeric|min:0', diff --git a/app/Http/Controllers/HR/PayrollController.php b/app/Http/Controllers/HR/PayrollController.php index 87e7a7fa..12b6d3aa 100644 --- a/app/Http/Controllers/HR/PayrollController.php +++ b/app/Http/Controllers/HR/PayrollController.php @@ -11,6 +11,8 @@ class PayrollController extends Controller { + private const ALLOWED_PAYROLL_USERS = ['이경호', '전진선', '김보곤']; + public function __construct( private PayrollService $payrollService ) {} @@ -24,6 +26,10 @@ public function index(Request $request): View|Response return response('', 200)->header('HX-Redirect', route('hr.payrolls.index')); } + if (! in_array(auth()->user()->name, self::ALLOWED_PAYROLL_USERS)) { + return view('hr.payrolls.restricted'); + } + $stats = $this->payrollService->getMonthlyStats(); $departments = $this->payrollService->getDepartments(); $employees = $this->payrollService->getActiveEmployees(); diff --git a/resources/views/hr/payrolls/restricted.blade.php b/resources/views/hr/payrolls/restricted.blade.php new file mode 100644 index 00000000..2118af0d --- /dev/null +++ b/resources/views/hr/payrolls/restricted.blade.php @@ -0,0 +1,17 @@ +@extends('layouts.app') + +@section('title', '급여관리 - 접근 제한') + +@section('content') +
+
+
+ + + +
+

접근이 제한된 페이지입니다

+

급여관리는 관계자만 볼 수 있습니다.

+
+
+@endsection