api 升职申请

main
panliang 2024-04-16 17:01:54 +08:00
parent 9dceb459fc
commit f66433e658
10 changed files with 271 additions and 24 deletions

View File

@ -61,6 +61,7 @@ class PromotionController extends AdminController
]),
]))
->columns([
amisMake()->TableColumn()->name('id')->label(__('employee_promotion.id')),
amisMake()->TableColumn()->name('store.title')->label(__('employee_promotion.store_id')),
amisMake()->TableColumn()->name('employee.name')->label(__('employee_promotion.employee_id')),
amisMake()->TableColumn()->name('job.name')->label(__('employee_promotion.job_id')),
@ -70,9 +71,11 @@ class PromotionController extends AdminController
$this->rowActions([
$this->rowShowButton()->visible(Admin::user()->can('admin.hr.promotion.view')),
$this->rowEditTypeButton('drawer', 'xl')
->visible(Admin::user()->can('admin.hr.promotion.update')),
->visible(Admin::user()->can('admin.hr.promotion.update'))
->visibleOn('${can_update}'),
$this->rowDeleteButton()
->visible(Admin::user()->can('admin.hr.promotion.delete')),
->visible(Admin::user()->can('admin.hr.promotion.delete'))
->visibleOn('${can_update}'),
$this->cancelAction()->visibleOn('${promotion_status == '.PromotionStatus::Processing->value.'}'),
]),
]);
@ -102,7 +105,8 @@ class PromotionController extends AdminController
amisMake()->SelectControl()->name('job_id')->label(__('employee_promotion.job_id'))
->source(admin_url('api/keywords/tree-list').'?parent_key=job')
->labelField('name')
->valueField('key'),
->valueField('key')
->required(),
amisMake()->TextControl()->name('remarks')->label(__('employee_promotion.remarks')),
]);
}
@ -119,6 +123,19 @@ class PromotionController extends AdminController
['label' => __('employee_promotion.invitor_id'), 'content' => '${invitor.name}'],
['label' => __('employee_promotion.promotion_status'), 'content' => amisMake()->Mapping()->name('promotion_status')->map(PromotionStatus::options())],
['label' => __('employee_promotion.remarks'), 'content' => '${remarks}'],
['label' => __('employee_promotion.created_at'), 'content' => '${created_at}', 'span' => 3],
]);
$data = amisMake()->Property()->items([
['label' => __('employee_promotion.age'), 'content' => '${employee_data.age}'],
['label' => __('employee_promotion.sex'), 'content' => '${employee_data.sex}'],
['label' => __('employee_promotion.education'), 'content' => '${employee_data.education}'],
['label' => __('employee_promotion.first_work_time'), 'content' => '${employee_data.first_work_time}'],
['label' => __('employee_promotion.work_years'), 'content' => '${employee_data.work_years}'],
['label' => __('employee_promotion.work_years_in_company'), 'content' => '${employee_data.work_years_in_company}'],
['label' => __('employee_promotion.comment_self'), 'content' => '${employee_data.comment_self}', 'span' => 3],
['label' => __('employee_promotion.plans'), 'content' => '${employee_data.plans}', 'span' => 3],
['label' => __('employee_promotion.reason'), 'content' => '${employee_data.reason}', 'span' => 3],
]);
return $this->baseDetail()->id($detailId)->title('')->onEvent([
@ -129,6 +146,8 @@ class PromotionController extends AdminController
],
])->body([
$detail,
amisMake()->Divider()->title('补充资料'),
$data,
amisMake()->Divider(),
$this->baseWorkflowLogService($detailId)->id($serviceId),
]);

View File

@ -37,6 +37,9 @@ class EmployeePromotionService extends BaseService
*/
public function apply($model, $data = [])
{
if (!$model->canUpdate()) {
return $this->setError('审核中, 无法修改');
}
$validator = Validator::make($data, [
'age' => ['required'],
'sex' => ['required'],
@ -48,7 +51,7 @@ class EmployeePromotionService extends BaseService
'plans' => ['required'],
]);
if ($validator->fails()) {
return $validator->errors()->first();
return $this->setError($validator->errors()->first());
}
$model->update(['employee_data' => $data, 'promotion_status' => PromotionStatus::Invitor]);
@ -65,35 +68,25 @@ class EmployeePromotionService extends BaseService
*/
public function invitor($model, $data = [])
{
if (!$model->canUpdate()) {
return $this->setError('审核中, 无法修改');
}
$validator = Validator::make($data, [
'reason' => ['required'],
]);
if ($validator->fails()) {
return $validator->errors()->first();
return $this->setError($validator->errors()->first());
}
try {
DB::beginTransaction();
$attributes = array_merge($model->employee_data, $data);
$model->update(['employee_data' => $data, 'promotion_status' => PromotionStatus::Processing]);
// 发起审核申请
$service = WorkflowService::make();
if ($service->apply($model->workflow, $model->employee) !== true) {
return $this->setError($service->getError());
}
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
return $this->setError($e->getMessage());
}
$attributes = array_merge($model->employee_data, $data);
$model->update(['employee_data' => $attributes, 'promotion_status' => PromotionStatus::Processing]);
return true;
}
public function validate($data, $model = null)
{
// todo 验证申请人的职位是否重复
$createRules = [
'store_id' => ['required'],
'employee_id' => ['required'],
@ -108,4 +101,35 @@ class EmployeePromotionService extends BaseService
return true;
}
public function update($primaryKey, $data): bool
{
$model = $this->query()->whereKey($primaryKey)->firstOrFail();
if (!$model->canUpdate()) {
return $this->setError('审核中, 无法修改');
}
$data = $this->resloveData($data, $model);
$validate = $this->validate($data, $model);
if ($validate !== true) {
$this->setError($validate);
return false;
}
$model->update($data);
$this->currentModel = $model;
return true;
}
public function delete(string $ids): mixed
{
$list = $this->query()->with(['workflow'])->whereIn('id', explode(',', $ids))->get();
foreach ($list as $item) {
if (!$item->canUpdate()) {
return $this->setError($item->promotion_status->text() . ', 无法删除');
}
$item->delete();
}
return true;
}
}

View File

@ -113,6 +113,8 @@ class WorkFlowService extends BaseService
'checked_at' => data_get($options, 'checked_at', now()),
]);
$check->subject->checkFail();
return true;
}
@ -128,6 +130,8 @@ class WorkFlowService extends BaseService
'check_status' => CheckStatus::Cancel,
]);
$check->subject->checkCancel();
return true;
}

View File

@ -12,7 +12,7 @@ enum PromotionStatus: int
*/
case Employee = 1;
/**
* 补充, 等待推荐人填写理由
* 推荐, 等待推荐人填写理由
*/
case Invitor = 2;
/**
@ -32,7 +32,7 @@ enum PromotionStatus: int
{
return [
self::Employee->value => '待提交',
self::Invitor->value => '待补充',
self::Invitor->value => '待推荐',
self::Processing->value => '审核中',
self::Success->value => '审核通过',
self::Fail->value => '审核不通过',

View File

@ -0,0 +1,115 @@
<?php
namespace App\Http\Controllers\Api\Hr;
use App\Http\Controllers\Api\Controller;
use Illuminate\Http\Request;
use App\Models\EmployeePromotion;
use App\Http\Resources\EmployeePromotionResource;
use App\Admin\Services\{EmployeePromotionService, WorkFlowService};
use App\Exceptions\RuntimeException;
use Illuminate\Support\Facades\DB;
use App\Enums\PromotionStatus;
/**
* 升职申请
*/
class PromotionController extends Controller
{
/**
* 申请列表
*/
public function applyList(Request $request)
{
$user = $this->guard()->user();
$list = EmployeePromotion::with(['workflow', 'invitor', 'job'])
->where('employee_id', $user->id)
->filter($request->all())
->orderBy('id', 'desc')
->paginate($request->input('per_page'));
return EmployeePromotionResource::collection($list);
}
/**
* 推荐列表
*/
public function inviteList(Request $request)
{
$user = $this->guard()->user();
$list = EmployeePromotion::with(['workflow', 'employee', 'job'])
->where('invitor_id', $user->id)
->filter($request->all())
->orderBy('id', 'desc')
->paginate($request->input('per_page'));
return EmployeePromotionResource::collection($list);
}
public function show($id)
{
$info = EmployeePromotion::with(['workflow', 'employee', 'invitor', 'job'])->findOrFail($id);
return EmployeePromotionResource::make($info);
}
/**
* 申请人完善资料
*/
public function applyUpdate($id, Request $request, EmployeePromotionService $service)
{
$user = $this->guard()->user();
$info = EmployeePromotion::where('employee_id', $user->id)->findOrFail($id);
if (!$service->apply($info, $request->all())) {
throw new RuntimeException($service->getError());
}
return response()->noContent();
}
/**
* 推荐人填写
*/
public function inviteUpdate($id, Request $request, EmployeePromotionService $service)
{
$user = $this->guard()->user();
$model = EmployeePromotion::with(['workflow', 'employee'])->where('invitor_id', $user->id)->findOrFail($id);
try {
DB::beginTransaction();
if (!$service->invitor($model, $request->all())) {
throw new RuntimeException($service->getError());
}
$workflow = WorkFlowService::make();
if (!$workflow->apply($model->workflow, $model->employee)) {
throw new RuntimeException($workflow->getError());
}
DB::commit();
return response()->noContent();
} catch (\Exception $e) {
DB::rollBack();
throw new RuntimeException($e->getMessage());
}
}
public function destroy($id, EmployeePromotionService $service)
{
$user = $this->guard()->user();
$model = EmployeePromotion::where('employee_id', $user->id)->findOrFail($id);
try {
DB::beginTransaction();
if (!$service->delete($id)) {
throw new RuntimeException($service->getError());
}
DB::commit();
return response()->noContent();
} catch (\Exception $e) {
DB::rollBack();
throw new RuntimeException($e->getMessage());
}
}
}

View File

@ -4,7 +4,7 @@ namespace App\Http\Controllers\Api;
use Illuminate\Http\{Request, Response};
use Illuminate\Database\Eloquent\Relations\Relation;
use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource, HolidayApplyResource, OvertimeApplyResource, AgreementResource};
use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource, HolidayApplyResource, OvertimeApplyResource, AgreementResource, EmployeePromotionResource};
use App\Enums\CheckStatus;
use App\Models\{WorkflowLog, WorkflowCheck};
use Illuminate\Support\Facades\DB;
@ -129,6 +129,7 @@ class WorkflowController extends Controller
'overtime_applies' => OvertimeApplyResource::class,
'agreements' => AgreementResource::class,
'offical_business' => OfficalBusinessResource::class,
'employee_promotions' => EmployeePromotionResource::class,
];
$resource = data_get($map, $key);
if (!$resource) {

View File

@ -0,0 +1,38 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class EmployeePromotionResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'employee_id' => $this->employee_id,
'employee' => EmployeeResource::make($this->whenLoaded('employee')),
'store_id' => $this->store_id,
'store' => StoreResource::make($this->whenLoaded('store')),
'invitor_id' => $this->invitor_id,
'invitor' => EmployeeResource::make($this->whenLoaded('invitor')),
'job_id' => $this->job_id,
'job' => KeywordResource::make($this->whenLoaded('job')),
'promotion_status' => $this->promotion_status,
'promotion_status_text' => $this->promotion_status->text(),
'employee_data' => $this->employee_data,
'created_at' => $this->created_at->timestamp,
'workflow_check' => WorkflowCheckResource::make($this->whenLoaded('workflow')),
];
}
}

View File

@ -7,6 +7,7 @@ use App\Traits\HasCheckable;
use App\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
/**
* 员工升职申请
@ -22,11 +23,38 @@ class EmployeePromotion extends Model
'employee_data' => 'json',
];
protected $appends = ['can_update'];
public function modelFilter()
{
return \App\Admin\Filters\EmployeePromotionFilter::class;
}
public function checkSuccess()
{
$this->update(['promotion_status' => PromotionStatus::Success]);
}
public function checkFail()
{
$this->update(['promotion_status' => PromotionStatus::Fail]);
}
public function checkCancel()
{
$this->update(['promotion_status' => PromotionStatus::Employee]);
}
public function canUpdate(): bool
{
return in_array($this->promotion_status, [PromotionStatus::Employee, PromotionStatus::Invitor, PromotionStatus::Fail]);
}
public function getCanUpdateAttribute()
{
return $this->canUpdate();
}
public function store()
{
return $this->belongsTo(Store::class, 'store_id');

View File

@ -39,6 +39,16 @@ trait HasCheckable
}
public function checkFail()
{
}
public function checkCancel()
{
}
public function canUpdate(): bool
{
return in_array($this->workflow?->check_status, [CheckStatus::None, CheckStatus::Fail, CheckStatus::Cancel]);

View File

@ -71,6 +71,14 @@ Route::group([
// 出差报备
Route::apiResource('hr/offical-bussiness', \App\Http\Controllers\Api\Hr\OfficalBusinessController::class);
// 升职申请
Route::get('hr/promotion/apply', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'applyList']);
Route::get('hr/promotion/invite', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'inviteList']);
Route::get('hr/promotion/{id}', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'show']);
Route::post('hr/promotion/{id}/apply', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'applyUpdate']);
Route::post('hr/promotion/{id}/invite', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'inviteUpdate']);
Route::delete('hr/promotion/{id}', [\App\Http\Controllers\Api\Hr\PromotionController::class, 'destroy']);
// 报销管理
Route::apiResource('reimbursements', \App\Http\Controllers\Api\ReimbursementController::class);