feat: [payroll] 급여 확정 취소 기능 추가
- 확정 상태에서 작성중으로 되돌리는 기능 추가
- Model: isUnconfirmable() 상태 헬퍼 추가
- Service: unconfirmPayroll() 메서드 추가
- Controller: unconfirm() 엔드포인트 추가
- Route: POST /{id}/unconfirm 라우트 추가
- View: 확정 취소 버튼 및 JS 함수 추가
This commit is contained in:
@@ -278,6 +278,41 @@ public function confirm(Request $request, int $id): JsonResponse
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 급여 확정 취소
|
||||
*/
|
||||
public function unconfirm(Request $request, int $id): JsonResponse
|
||||
{
|
||||
if ($denied = $this->checkPayrollAccess()) {
|
||||
return $denied;
|
||||
}
|
||||
|
||||
try {
|
||||
$payroll = $this->payrollService->unconfirmPayroll($id);
|
||||
|
||||
if (! $payroll) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '급여 확정을 취소할 수 없습니다.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '급여 확정이 취소되었습니다.',
|
||||
'data' => $payroll,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '급여 확정 취소 중 오류가 발생했습니다.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 급여 지급 처리
|
||||
*/
|
||||
|
||||
@@ -141,6 +141,11 @@ public function isConfirmable(): bool
|
||||
return $this->status === self::STATUS_DRAFT;
|
||||
}
|
||||
|
||||
public function isUnconfirmable(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_CONFIRMED;
|
||||
}
|
||||
|
||||
public function isPayable(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_CONFIRMED;
|
||||
|
||||
@@ -278,6 +278,31 @@ public function confirmPayroll(int $id): ?Payroll
|
||||
return $payroll->fresh(['user']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 급여 확정 취소 (confirmed → draft)
|
||||
*/
|
||||
public function unconfirmPayroll(int $id): ?Payroll
|
||||
{
|
||||
$tenantId = session('selected_tenant_id', 1);
|
||||
|
||||
$payroll = Payroll::query()
|
||||
->forTenant($tenantId)
|
||||
->find($id);
|
||||
|
||||
if (! $payroll || ! $payroll->isUnconfirmable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$payroll->update([
|
||||
'status' => Payroll::STATUS_DRAFT,
|
||||
'confirmed_at' => null,
|
||||
'confirmed_by' => null,
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
return $payroll->fresh(['user']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 급여 지급 처리
|
||||
*/
|
||||
|
||||
@@ -888,6 +888,33 @@ function confirmPayroll(id) {
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 급여 확정 취소 =====
|
||||
function unconfirmPayroll(id) {
|
||||
if (!confirm('이 급여의 확정을 취소하시겠습니까? 작성중 상태로 되돌아갑니다.')) return;
|
||||
|
||||
fetch('{{ url("/api/admin/hr/payrolls") }}/' + id + '/unconfirm', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
refreshTable();
|
||||
refreshStats();
|
||||
showToast(result.message, 'success');
|
||||
} else {
|
||||
showToast(result.message, 'error');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
showToast('확정 취소 중 오류가 발생했습니다.', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// ===== 급여 지급 =====
|
||||
function payPayroll(id) {
|
||||
if (!confirm('이 급여를 지급 처리하시겠습니까?')) return;
|
||||
|
||||
@@ -121,6 +121,15 @@
|
||||
</button>
|
||||
@endif
|
||||
|
||||
{{-- 확정 취소 (confirmed만) --}}
|
||||
@if($payroll->isUnconfirmable())
|
||||
<button type="button" onclick="unconfirmPayroll({{ $payroll->id }})" class="p-1 text-orange-600 hover:text-orange-800" title="확정 취소">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"/>
|
||||
</svg>
|
||||
</button>
|
||||
@endif
|
||||
|
||||
{{-- 지급 (confirmed만) --}}
|
||||
@if($payroll->isPayable())
|
||||
<button type="button" onclick="payPayroll({{ $payroll->id }})" class="p-1 text-emerald-600 hover:text-emerald-800" title="지급처리">
|
||||
|
||||
@@ -1127,6 +1127,7 @@
|
||||
Route::put('/{id}', [\App\Http\Controllers\Api\Admin\HR\PayrollController::class, 'update'])->name('update');
|
||||
Route::delete('/{id}', [\App\Http\Controllers\Api\Admin\HR\PayrollController::class, 'destroy'])->name('destroy');
|
||||
Route::post('/{id}/confirm', [\App\Http\Controllers\Api\Admin\HR\PayrollController::class, 'confirm'])->name('confirm');
|
||||
Route::post('/{id}/unconfirm', [\App\Http\Controllers\Api\Admin\HR\PayrollController::class, 'unconfirm'])->name('unconfirm');
|
||||
Route::post('/{id}/pay', [\App\Http\Controllers\Api\Admin\HR\PayrollController::class, 'pay'])->name('pay');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user