generated from liutk/owl-admin-base
api 审核流程
parent
b3177862bc
commit
77205d7fa9
|
|
@ -37,6 +37,14 @@ class EmployeeSignFilter extends ModelFilter
|
|||
$this->whereBetween('date', [$start, $end]);
|
||||
}
|
||||
|
||||
public function month($key)
|
||||
{
|
||||
$time = Carbon::createFromFormat('Y-m', $key);
|
||||
$start = $time->copy()->startOfMonth();
|
||||
$end = $time->copy()->endOfMonth();
|
||||
$this->whereBetween('date', [$start, $end]);
|
||||
}
|
||||
|
||||
public function signType($key)
|
||||
{
|
||||
$this->whereIn('sign_type', is_array($key) ? $key : explode(',', $key));
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace App\Admin\Services;
|
|||
|
||||
use App\Admin\Filters\EmployeeSignRepairFilter;
|
||||
use App\Models\Employee;
|
||||
use App\Models\EmployeeSignRepair;
|
||||
use App\Models\{EmployeeSignRepair, EmployeeSign};
|
||||
use App\Models\WorkflowCheck;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
|
@ -17,22 +17,6 @@ class EmployeeSignRepairService extends BaseService
|
|||
|
||||
protected string $modelFilterName = EmployeeSignRepairFilter::class;
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
$data = $this->resloveData($data);
|
||||
|
||||
$validate = $this->validate($data);
|
||||
if ($validate !== true) {
|
||||
$this->setError($validate);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->modelName::create($data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function resloveData($data, $model = null)
|
||||
{
|
||||
// 获取员工所在的门店
|
||||
|
|
@ -43,28 +27,16 @@ class EmployeeSignRepairService extends BaseService
|
|||
return $data;
|
||||
}
|
||||
|
||||
public function preDelete(array $ids): void
|
||||
{
|
||||
// 删除审核流程记录
|
||||
WorkflowCheck::where('subject_type', (new WorkflowLog)->getMorphClass())->whereIn('subject_id', $ids)->delete();
|
||||
}
|
||||
|
||||
public function validate($data, $model = null)
|
||||
{
|
||||
// 验证申请时间是否重叠
|
||||
// todo
|
||||
$unique = Rule::unique('employee_sign_repairs', 'date')
|
||||
->where('employee_id', data_get($data, 'employee_id', $model?->employee_id))
|
||||
->where('repair_type', data_get($data, 'repair_type', $model?->repair_type));
|
||||
$createRules = [
|
||||
'employee_id' => ['required'],
|
||||
'repair_type' => ['required'],
|
||||
'date' => ['required', $unique],
|
||||
'date' => ['required'],
|
||||
'store_id' => ['required'],
|
||||
'reason' => ['required'],
|
||||
];
|
||||
$updateRules = [
|
||||
'date' => [$unique->ignore($model?->id)],
|
||||
];
|
||||
$message = [
|
||||
'date.required' => __('employee_sign_repair.date').'必填',
|
||||
|
|
@ -78,6 +50,8 @@ class EmployeeSignRepairService extends BaseService
|
|||
if ($validator->fails()) {
|
||||
return $validator->errors()->first();
|
||||
}
|
||||
// todo 已经打卡不能申请
|
||||
// todo 验证申请时间是否重复
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use App\Models\Employee;
|
|||
use App\Models\EmployeeRest;
|
||||
use App\Models\EmployeeSign;
|
||||
use App\Models\EmployeeSignLog;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class EmployeeSignService extends BaseService
|
||||
{
|
||||
|
|
@ -63,8 +64,6 @@ class EmployeeSignService extends BaseService
|
|||
$type = $logs->where('sign_type', SignType::Outside)->count() > 0 ? SignType::Outside : SignType::Normal;
|
||||
}
|
||||
$attributes = [
|
||||
'date' => $date,
|
||||
'store_id' => $employee->store_id,
|
||||
'sign_type' => $type,
|
||||
'first_time' => $firstTime,
|
||||
'last_time' => $lastTime,
|
||||
|
|
@ -75,7 +74,60 @@ class EmployeeSignService extends BaseService
|
|||
},
|
||||
'remarks' => $remarks,
|
||||
];
|
||||
$employee->signs()->create($attributes);
|
||||
$employee->signs()->updateOrCreate([
|
||||
'date' => $date,
|
||||
'store_id' => $employee->store_id,
|
||||
], $attributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打卡
|
||||
*
|
||||
* @param Employee $user 用户
|
||||
* @param SignTime $time 上班/下班 打卡
|
||||
* @param mixed $date 打卡时间
|
||||
* @param array $options {type: 正常/外勤 打卡, remarks: 备注, position: 位置}
|
||||
* @return boolean
|
||||
*/
|
||||
public function signDay(Employee $user, SignTime $time, $date = '', array $options = [])
|
||||
{
|
||||
$date = $date ?: now();
|
||||
$log = EmployeeSignLog::create([
|
||||
'store_id' => $user->store_id,
|
||||
'employee_id' => $user->id,
|
||||
'sign_time' => $time,
|
||||
'time' => $date,
|
||||
'sign_type' => data_get($options, 'type'),
|
||||
'remarks' => data_get($options, 'remarks'),
|
||||
'position' => data_get($options, 'position'),
|
||||
]);
|
||||
|
||||
// 更新打卡情况
|
||||
$sign = EmployeeSign::firstOrCreate([
|
||||
'date' => $date->format('Y-m-d'),
|
||||
'store_id' => $user->store_id,
|
||||
'employee_id' => $user->id,
|
||||
]);
|
||||
$sign->sign_type = $log->sign_type;
|
||||
if ($time == SignTime::Morning) {
|
||||
$sign->first_time = $log->time;
|
||||
} else if ($time == SignTime::Afternoon) {
|
||||
$sign->last_time = $log->time;
|
||||
}
|
||||
$sign->sign_status = SignStatus::Lose;
|
||||
if ($sign->first_time && $sign->last_time) {
|
||||
$sign->sign_status = SignStatus::Normal;
|
||||
}
|
||||
$sign->remarks = $log->remarks;
|
||||
|
||||
$sign->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasRest(Employee $user, $date)
|
||||
{
|
||||
return EmployeeRest::where('employee_id', $user->id)->where('date', $date)->exists();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ class WorkFlowService extends BaseService
|
|||
'check_remarks' => data_get($options, 'remarks'),
|
||||
]);
|
||||
|
||||
$check->subject->checkSuccess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,22 @@
|
|||
|
||||
namespace App\Enums;
|
||||
|
||||
/**
|
||||
* 打卡状态
|
||||
*/
|
||||
enum SignStatus: int
|
||||
{
|
||||
/**
|
||||
* 正常打卡
|
||||
*/
|
||||
case Normal = 1;
|
||||
/**
|
||||
* 缺卡
|
||||
*/
|
||||
case Lose = 2;
|
||||
/**
|
||||
* 旷工
|
||||
*/
|
||||
case Absent = 3;
|
||||
|
||||
public static function options()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Hr;
|
||||
|
||||
use App\Http\Controllers\Api\Controller;
|
||||
use App\Models\{EmployeeSign};
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use App\Exceptions\RuntimeException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Admin\Services\EmployeeSignService;
|
||||
use App\Enums\{SignTime, SignType, SignStatus};
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* 考勤打卡
|
||||
*/
|
||||
class SignController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$time = $request->filled('time') ? Carbon::createFromFormat('Y-m', $request->input('time')) : now();
|
||||
$list = EmployeeSign::where('employee_id', $user->id)->filter(['month' => $time->format('Y-m')])->get();
|
||||
$data = [];
|
||||
$start = $time->copy()->startOfMonth();
|
||||
$end = $time->copy()->endOfMonth();
|
||||
do {
|
||||
$info = $list->where(fn($item) => $item->date->format('Y-m-d') == $start->format('Y-m-d'))->first();
|
||||
array_push($data, [
|
||||
'date' => $start->format('Y-m-d'),
|
||||
'sign_status' => $info ? $info->sign_status : null,
|
||||
'first_time' => $info?->first_time->format('H:i'),
|
||||
'last_time' => $info?->last_time->format('H:i'),
|
||||
]);
|
||||
$start->addDay();
|
||||
} while(!$end->isSameDay($start));
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function info(Request $request, EmployeeSignService $service)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$date = now();
|
||||
// 上午: 上班打卡, 下午: 下班打卡
|
||||
$time = $date->format('H') <= 12 ? SignTime::Morning : SignTime::Afternoon;
|
||||
// 根据定位的距离判断, 是否外勤
|
||||
$type = SignType::Normal;
|
||||
// 当前位置不在考勤范围内,请选择外勤打卡
|
||||
$description = '已进入考勤范围xx店';
|
||||
|
||||
return compact('time', 'type', 'description');
|
||||
}
|
||||
|
||||
public function store(Request $request, EmployeeSignService $service)
|
||||
{
|
||||
$request->validate([
|
||||
'type' => ['required'],
|
||||
'time' => ['required'],
|
||||
]);
|
||||
$user = $this->guard()->user();
|
||||
$time = SignTime::from($request->input('time'));
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
if (!$service->signDay($user, $time, now(), $request->only(['remarks', 'position', 'type']))) {
|
||||
throw new RuntimeException($service->getError());
|
||||
}
|
||||
DB::commit();
|
||||
return response('', Response::HTTP_OK);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Hr;
|
||||
|
||||
use App\Http\Controllers\Api\Controller;
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use App\Models\EmployeeSignRepair;
|
||||
use App\Http\Resources\{EmployeeSignRepairResource, WorkflowLogResource};
|
||||
use App\Admin\Services\{EmployeeSignRepairService, WorkFlowService};
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Exceptions\RuntimeException;
|
||||
use App\Enums\{CheckStatus};
|
||||
|
||||
/**
|
||||
* 补卡申请
|
||||
*/
|
||||
class SignRepairController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$list = EmployeeSignRepair::with(['workflow'])
|
||||
->where('employee_id', $user->id)
|
||||
->filter($request->all())
|
||||
->orderBy('id', 'desc')
|
||||
->paginate($request->input('per_page'));
|
||||
return EmployeeSignRepairResource::collection($list);
|
||||
}
|
||||
|
||||
public function store(Request $request, EmployeeSignRepairService $service)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$data = $request->all();
|
||||
$data['employee_id'] = $user->id;
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$data = $service->resloveData($data);
|
||||
$result = $service->validate($data);
|
||||
if ($result !== true) {
|
||||
throw new RuntimeException($result);
|
||||
}
|
||||
$model = EmployeeSignRepair::create($data);
|
||||
$workflow = WorkFlowService::make();
|
||||
if (!$workflow->apply($model->workflow, $user)) {
|
||||
throw new RuntimeException($workflow->getError());
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return response('', Response::HTTP_OK);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
$info = EmployeeSignRepair::with(['workflow', 'employee', 'store'])->findOrFail($id);
|
||||
|
||||
return EmployeeSignRepairResource::make($info);
|
||||
}
|
||||
|
||||
public function update($id, Request $request, EmployeeSignRepairService $service)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$model = EmployeeSignRepair::with(['workflow'])->where('employee_id', $user->id)->findOrFail($id);
|
||||
if (!$model->canUpdate()) {
|
||||
throw new RuntimeException('审核中, 无法修改');
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$data = $service->resloveData($data, $model);
|
||||
$result = $service->validate($data, $model);
|
||||
if ($result !== true) {
|
||||
throw new RuntimeException($result);
|
||||
}
|
||||
$model->update($data);
|
||||
$workflow = WorkFlowService::make();
|
||||
if (!$workflow->apply($model->workflow, $user)) {
|
||||
throw new RuntimeException($workflow->getError());
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return response('', Response::HTTP_OK);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy($id, EmployeeSignRepairService $service)
|
||||
{
|
||||
$user = $this->guard()->user();
|
||||
$model = EmployeeSignRepair::with(['workflow'])->where('employee_id', $user->id)->findOrFail($id);
|
||||
if (!$model->canUpdate()) {
|
||||
throw new RuntimeException('审核中, 无法删除');
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
if (!$service->delete($id)) {
|
||||
throw new RuntimeException($service->getError());
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
return response('', Response::HTTP_OK);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use App\Http\Resources\{ReimbursementResource, WorkflowLogResource, EmployeeSignRepairResource};
|
||||
use App\Enums\CheckStatus;
|
||||
use App\Models\{WorkflowLog, WorkflowCheck};
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Admin\Services\WorkFlowService;
|
||||
use App\Exceptions\RuntimeException;
|
||||
|
||||
class WorkflowController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'subject_type' => 'required',
|
||||
]);
|
||||
$subjectType = $request->input('subject_type');
|
||||
$model = Relation::getMorphedModel($subjectType);
|
||||
$resource = $this->mapResource($subjectType);
|
||||
|
||||
$user = $request->user();
|
||||
$query = $model::query()->with(['workflow'])
|
||||
->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 $resource::collection($list);
|
||||
}
|
||||
|
||||
public function show($id, Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'subject_type' => 'required',
|
||||
]);
|
||||
$subjectType = $request->input('subject_type');
|
||||
$model = Relation::getMorphedModel($subjectType);
|
||||
$resource = $this->mapResource($subjectType);
|
||||
|
||||
$include = ['workflow'];
|
||||
if ($request->input('include')) {
|
||||
$explodes = explode(',', $request->input('include'));
|
||||
$include = array_merge($include, $explodes);
|
||||
}
|
||||
$info = $model::query()->with($include)->findOrFail($id);
|
||||
|
||||
return $resource::make($info);
|
||||
}
|
||||
|
||||
public function logs($id, Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'subject_type' => 'required',
|
||||
]);
|
||||
$check = WorkflowCheck::where('subject_type', $request->input('subject_type'))->where('subject_id', $id)->firstOrFail();
|
||||
$logs = $check->logs()->sort()->get();
|
||||
|
||||
return WorkflowLogResource::collection($logs);
|
||||
}
|
||||
|
||||
public function check($id, Request $request, WorkFlowService $workFlowService)
|
||||
{
|
||||
$request->validate([
|
||||
'subject_type' => 'required',
|
||||
'status' => ['required'],
|
||||
'remarks' => [Rule::requiredIf(fn() => !$request->input('status'))]
|
||||
], [
|
||||
'remarks.required_if' => '未通过原因必填',
|
||||
]);
|
||||
$check = WorkflowCheck::where('subject_type', $request->input('subject_type'))->where('subject_id', $id)->firstOrFail();
|
||||
$user = $request->user();
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$log = $check->logs()->where('check_status', CheckStatus::Processing)->first();
|
||||
if (!$log) {
|
||||
throw new RuntimeException('审核已经完成');
|
||||
}
|
||||
if (!$workFlowService->check($user, $log, !!$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());
|
||||
}
|
||||
}
|
||||
|
||||
protected function mapResource($key)
|
||||
{
|
||||
$map = [
|
||||
'reimbursements' => ReimbursementResource::class,
|
||||
'employee_sign_repairs' => EmployeeSignRepairResource::class,
|
||||
];
|
||||
return data_get($map, $key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class EmployeeSignRepairResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'date' => $this->date->timestamp,
|
||||
|
||||
'employee_id' => $this->employee_id,
|
||||
'employee' => EmployeeResource::make($this->whenLoaded('employee')),
|
||||
'store_id' => $this->store_id,
|
||||
'store' => StoreResource::make($this->whenLoaded('store')),
|
||||
|
||||
'reason' => $this->reason,
|
||||
'repair_type' => $this->repair_type,
|
||||
'sign_type' => $this->sign_type,
|
||||
'outside_remarks' => $this->outside_remarks,
|
||||
'created_at' => $this->created_at->timestamp,
|
||||
|
||||
'workflow_check' => WorkflowCheckResource::make($this->whenLoaded('workflow')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -14,22 +14,12 @@ class WorkflowCheckResource extends JsonResource
|
|||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
$resource = $this->mapResource($this->subject_type);
|
||||
return [
|
||||
'check_status' => $this->check_status,
|
||||
'check_status_text' => $this->check_status?->text(),
|
||||
'checked_at' => $this->checked_at?->getTimestamp(),
|
||||
'check_remarks' => (string) $this->check_remarks,
|
||||
'subject' => $resource ? $resource::make($this->whenLoaded('subject')) : '',
|
||||
'logs' => WorkflowLogResource::collection($this->whenLoaded('logs')),
|
||||
];
|
||||
}
|
||||
|
||||
protected function mapResource($key)
|
||||
{
|
||||
$map = [
|
||||
'reimbursements' => ReimbursementResource::class,
|
||||
];
|
||||
return data_get($map, $key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@ class EmployeeSign extends Model
|
|||
'last_time' => 'datetime',
|
||||
];
|
||||
|
||||
public function modelFilter()
|
||||
{
|
||||
return \App\Admin\Filters\EmployeeSignFilter::class;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class EmployeeSignLog extends Model
|
|||
|
||||
protected $table = 'employee_sign_logs';
|
||||
|
||||
protected $fillable = ['store_id', 'employee_id', 'sign_type', 'sign_time', 'remarks', 'position', 'time'];
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'sign_type' => SignType::class,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\{SignTime};
|
||||
use App\Enums\{SignTime, SignType, CheckStatus};
|
||||
use App\Traits\HasCheckable;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use EloquentFilter\Filterable;
|
||||
|
|
@ -17,14 +17,19 @@ class EmployeeSignRepair extends Model
|
|||
|
||||
protected $table = 'employee_sign_repairs';
|
||||
|
||||
protected $fillable = ['date', 'store_id', 'employee_id', 'reason', 'repair_type'];
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'date' => 'date:Y-m-d',
|
||||
'checked_at' => 'datetime',
|
||||
'date' => 'datetime',
|
||||
'repair_type' => SignTime::class,
|
||||
'sign_type' => SignType::class,
|
||||
];
|
||||
|
||||
public function canUpdate(): bool
|
||||
{
|
||||
return in_array($this->workflow?->check_status, [CheckStatus::None, CheckStatus::Fail, CheckStatus::Cancel]);
|
||||
}
|
||||
|
||||
public function modelFilter()
|
||||
{
|
||||
return \App\Admin\Filters\EmployeeSignRepairFilter::class;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ trait HasCheckable
|
|||
return Str::snake(class_basename(__CLASS__));
|
||||
}
|
||||
|
||||
public function checkSuccess()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联审核流水
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Enums\{SignType, SignTime, SignStatus};
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
|
|
@ -16,10 +17,10 @@ return new class extends Migration
|
|||
$table->date('date')->comment('日期');
|
||||
$table->foreignId('store_id')->comment('门店, stores.id');
|
||||
$table->foreignId('employee_id')->comment('员工, employees.id');
|
||||
$table->unsignedInteger('sign_type')->default(1)->comment('类别(1: 正常打卡, 2: 外勤)');
|
||||
$table->unsignedInteger('sign_type')->default(SignType::Normal)->comment('类别(1: 正常打卡, 2: 外勤)');
|
||||
$table->timestamp('first_time')->nullable()->comment('上班打卡时间');
|
||||
$table->timestamp('last_time')->nullable()->comment('下班打卡时间');
|
||||
$table->unsignedInteger('sign_status')->default(1)->comment('考勤状态(1: 正常, 2: 旷工, 3: 缺卡)');
|
||||
$table->unsignedInteger('sign_status')->default(SignStatus::Normal)->comment('考勤状态(1: 正常, 2: 旷工, 3: 缺卡)');
|
||||
$table->string('remarks')->nullable()->comment('备注');
|
||||
$table->timestamps();
|
||||
|
||||
|
|
@ -30,9 +31,12 @@ return new class extends Migration
|
|||
$table->id();
|
||||
$table->foreignId('store_id')->comment('门店, stores.id');
|
||||
$table->foreignId('employee_id')->comment('员工, employees.id');
|
||||
$table->unsignedInteger('sign_type')->default(1)->comment('类别(1: 正常打卡, 2: 外勤)');
|
||||
$table->unsignedInteger('sign_time')->default(1)->comment('打卡时间(1: 上班, 2: 下班)');
|
||||
$table->unsignedInteger('sign_type')->default(SignType::Normal)->comment('类别(1: 正常打卡, 2: 外勤)');
|
||||
$table->unsignedInteger('sign_time')->default(SignTime::Morning)->comment('打卡时间(1: 上班, 2: 下班)');
|
||||
$table->string('remarks')->nullable()->comment('备注');
|
||||
$table->string('outside_remarks')->nullable()->comment('外勤备注');
|
||||
$table->unsignedInteger('is_repair')->default(0)->comment('是否补卡');
|
||||
$table->foreignId('repair_id')->nullable()->comment('补卡记录');
|
||||
$table->json('position')->comment('打卡位置');
|
||||
$table->timestamp('time')->comment('打卡时间');
|
||||
$table->timestamps();
|
||||
|
|
@ -50,11 +54,13 @@ return new class extends Migration
|
|||
|
||||
Schema::create('employee_sign_repairs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->date('date')->comment('补卡日期');
|
||||
$table->datetime('date')->comment('补卡日期');
|
||||
$table->foreignId('store_id')->comment('门店, stores.id');
|
||||
$table->foreignId('employee_id')->comment('员工, employees.id');
|
||||
$table->string('reason')->comment('补卡原因');
|
||||
$table->unsignedInteger('repair_type')->default(1)->comment('上班/下班');
|
||||
$table->unsignedInteger('repair_type')->default(SignTime::Morning)->comment('上班/下班');
|
||||
$table->unsignedInteger('sign_type')->default(SignType::Normal)->comment('类别(1: 正常打卡, 2: 外勤)');
|
||||
$table->string('outside_remarks')->nullable()->comment('外勤备注');
|
||||
|
||||
$table->timestamps();
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,20 @@ Route::group([
|
|||
Route::apiResource('hr/employee', \App\Http\Controllers\Api\Hr\EmployeeController::class);
|
||||
});
|
||||
|
||||
// 考勤打卡
|
||||
Route::get('hr/sign/info', [\App\Http\Controllers\Api\Hr\SignController::class, 'info']);
|
||||
Route::get('hr/sign', [\App\Http\Controllers\Api\Hr\SignController::class, 'index']);
|
||||
Route::post('hr/sign', [\App\Http\Controllers\Api\Hr\SignController::class, 'store']);
|
||||
|
||||
// 补卡申请
|
||||
Route::apiResource('hr/sign-repairs', \App\Http\Controllers\Api\Hr\SignRepairController::class);
|
||||
|
||||
// 报销管理
|
||||
Route::get('reimbursements/check', [\App\Http\Controllers\Api\ReimbursementController::class, 'checkList']);
|
||||
Route::post('reimbursements/{id}/check', [\App\Http\Controllers\Api\ReimbursementController::class, 'check']);
|
||||
Route::get('reimbursements/{id}/logs', [\App\Http\Controllers\Api\ReimbursementController::class, 'logs']);
|
||||
Route::apiResource('reimbursements', \App\Http\Controllers\Api\ReimbursementController::class);
|
||||
|
||||
// 审核流程
|
||||
Route::get('workflow', [\App\Http\Controllers\Api\WorkflowController::class, 'index']);
|
||||
Route::get('workflow/{id}', [\App\Http\Controllers\Api\WorkflowController::class, 'show']);
|
||||
Route::get('workflow/{id}/logs', [\App\Http\Controllers\Api\WorkflowController::class, 'logs']);
|
||||
Route::post('workflow/{id}/check', [\App\Http\Controllers\Api\WorkflowController::class, 'check']);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue