generated from liutk/owl-admin-base
207 lines
6.6 KiB
PHP
207 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Admin\Services\WorkFlowService;
|
|
use App\Enums\CheckStatus;
|
|
use App\Exceptions\RuntimeException;
|
|
use App\Http\Resources\ReimbursementResource;
|
|
use App\Http\Resources\WorkflowLogResource;
|
|
use App\Models\Keyword;
|
|
use App\Models\Reimbursement;
|
|
use App\Models\WorkflowCheck;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\Rule;
|
|
use Throwable;
|
|
|
|
/**
|
|
* 报销管理
|
|
*/
|
|
class ReimbursementController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
/** @var \App\Models\Employee */
|
|
$user = $request->user();
|
|
|
|
$reimbursements = $user->reimbursements()
|
|
->with(['type', 'workflow'])
|
|
->filter($request->input())
|
|
->orderByDesc(WorkflowCheck::checkStatusSortBuilder(new Reimbursement()))
|
|
->orderBy('id', 'desc')
|
|
->paginate($request->input('per_page', 20));
|
|
|
|
return ReimbursementResource::collection($reimbursements);
|
|
}
|
|
|
|
public function store(Request $request, WorkFlowService $workFlowService): ReimbursementResource
|
|
{
|
|
$validated = $request->validate(
|
|
rules: [
|
|
'reimbursement_type_id' => ['bail', 'required', Rule::exists(Keyword::class, 'key')],
|
|
'expense' => ['bail', 'required', 'min:0', 'max:99999999', 'decimal:0,2'],
|
|
'reason' => ['bail', 'required', 'max:255'],
|
|
'photos' => ['bail', 'required', 'array'],
|
|
],
|
|
attributes: [
|
|
'reimbursement_type_id' => '报销分类',
|
|
'expense' => '报销金额',
|
|
'reason' => '报销原因',
|
|
'photos' => '报销凭证',
|
|
],
|
|
);
|
|
|
|
/** @var \App\Models\Employee */
|
|
$user = $request->user();
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$validated['store_id'] = $user->store_id;
|
|
/** @var \App\Models\Reimbursement */
|
|
$reimbursement = $user->reimbursements()->create($validated);
|
|
|
|
$workFlowService->apply($reimbursement->workflow, $user);
|
|
|
|
DB::commit();
|
|
} catch (Throwable $th) {
|
|
DB::rollBack();
|
|
|
|
throw tap($th, fn ($th) => report($th));
|
|
}
|
|
|
|
return ReimbursementResource::make(
|
|
$reimbursement->load(['type', 'workflow']),
|
|
);
|
|
}
|
|
|
|
public function show($id, Request $request): ReimbursementResource
|
|
{
|
|
$reimbursement = Reimbursement::with(['type', 'workflow', 'employee', 'store'])->findOrFail($id);
|
|
|
|
return ReimbursementResource::make($reimbursement);
|
|
}
|
|
|
|
public function update($id, Request $request, WorkFlowService $workFlowService): ReimbursementResource
|
|
{
|
|
$validated = $request->validate(
|
|
rules: [
|
|
'reimbursement_type_id' => ['bail', 'required', Rule::exists(Keyword::class, 'key')],
|
|
'expense' => ['bail', 'required', 'numeric', 'min:0'],
|
|
'reason' => ['bail', 'required', 'max:255'],
|
|
'photos' => ['bail', 'required', 'array'],
|
|
],
|
|
attributes: [
|
|
'reimbursement_type_id' => '报销分类',
|
|
'expense' => '报销金额',
|
|
'reason' => '报销原因',
|
|
'photos' => '报销凭证',
|
|
],
|
|
);
|
|
|
|
/** @var \App\Models\Employee */
|
|
$user = $request->user();
|
|
|
|
/** @var \App\Models\Reimbursement */
|
|
$reimbursement = $user->reimbursements()->find($id);
|
|
|
|
if (is_null($reimbursement)) {
|
|
throw new RuntimeException('报销记录未找到');
|
|
}
|
|
|
|
if (! $reimbursement->canUpdate()) {
|
|
throw new RuntimeException('['.$reimbursement->workflow->check_status->text().']报销记录不可修改');
|
|
}
|
|
|
|
try {
|
|
DB::beginTransaction();
|
|
|
|
$reimbursement->update($validated);
|
|
|
|
$workFlowService->apply($reimbursement->workflow, $user);
|
|
|
|
DB::commit();
|
|
} catch (Throwable $th) {
|
|
DB::rollBack();
|
|
|
|
throw tap($th, fn ($th) => report($th));
|
|
}
|
|
|
|
return ReimbursementResource::make(
|
|
$reimbursement->load(['type', 'workflow']),
|
|
);
|
|
}
|
|
|
|
public function destroy($id, Request $request)
|
|
{
|
|
/** @var \App\Models\Employee */
|
|
$user = $request->user();
|
|
|
|
/** @var \App\Models\Reimbursement */
|
|
$reimbursement = $user->reimbursements()->find($id);
|
|
|
|
if (is_null($reimbursement)) {
|
|
throw new RuntimeException('报销记录未找到');
|
|
}
|
|
|
|
if (! $reimbursement->canDelete()) {
|
|
throw new RuntimeException('['.$reimbursement->workflow->check_status->text().']报销记录不可删除');
|
|
}
|
|
|
|
$reimbursement->delete();
|
|
|
|
return response()->noContent();
|
|
}
|
|
|
|
public function checkList(Request $request)
|
|
{
|
|
$user = $request->user();
|
|
$query = Reimbursement::with(['workflow', 'type', 'store'])
|
|
->whereHas('workflow', fn ($q) => $q->where('check_status', CheckStatus::Processing))
|
|
->whereHas('workflow.logs', fn ($q) => $q->own($user))->orderBy('created_at', 'desc');
|
|
|
|
$list = $query->paginate($request->input('per_page'));
|
|
|
|
return ReimbursementResource::collection($list);
|
|
}
|
|
|
|
public function check($id, Request $request, WorkFlowService $workFlowService)
|
|
{
|
|
$request->validate([
|
|
'status' => ['required'],
|
|
'remarks' => [Rule::requiredIf(fn () => ! $request->input('status'))],
|
|
], [
|
|
'remarks.required_if' => '未通过原因必填',
|
|
]);
|
|
$info = Reimbursement::findOrFail($id);
|
|
$user = $request->user();
|
|
try {
|
|
DB::beginTransaction();
|
|
$log = $info->workflow->logs()->where('check_status', CheckStatus::Processing)->first();
|
|
if (! $log) {
|
|
throw new RuntimeException('审核已经完成');
|
|
}
|
|
if (! $workFlowService->check($user, $log, (bool) $request->input('status'), ['remarks' => $request->input('remarks')])) {
|
|
throw new RuntimeException($workFlowService->getError());
|
|
}
|
|
|
|
DB::commit();
|
|
|
|
return response('', Response::HTTP_OK);
|
|
} catch (\Exception $e) {
|
|
DB::rollBack();
|
|
throw new RuntimeException($e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function logs($id)
|
|
{
|
|
$info = Reimbursement::findOrFail($id);
|
|
$logs = $info->workflow->logs()->sort()->get();
|
|
|
|
return WorkflowLogResource::collection($logs);
|
|
}
|
|
}
|