generated from liutk/owl-admin-base
admin 请假申请
parent
03797a1e7c
commit
a013b50bcf
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers\Hr;
|
||||
|
||||
use App\Admin\Controllers\AdminController;
|
||||
use App\Admin\Services\HolidayApplyService;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use App\Enums\{CheckStatus, EmployeeStatus};
|
||||
use App\Models\HolidayApply;
|
||||
use App\Traits\HasCheckActions;
|
||||
|
||||
/**
|
||||
* 请假管理
|
||||
*/
|
||||
class HolidayController extends AdminController
|
||||
{
|
||||
use HasCheckActions;
|
||||
|
||||
protected string $serviceName = HolidayApplyService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createTypeButton('drawer', 'xl')->visible(Admin::user()->can('admin.hr.holiday.create')),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->bulkActions([])
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amisMake()->SelectControl()->name('store_id')->label(__('holiday_apply.store_id'))
|
||||
->source(admin_url('api/stores?_all=1'))
|
||||
->labelField('title')
|
||||
->valueField('id')
|
||||
->searchable()
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->TextControl()->name('employee_name')->label(__('holiday_apply.employee_id'))
|
||||
->placeholder(__('employee.name').'/'.__('employee.phone'))
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->SelectControl()->name('type_id')->label(__('holiday_apply.type_id'))
|
||||
->source(admin_url('api/keywords/tree-list?parent_key=holiday_type'))
|
||||
->labelField('name')
|
||||
->valueField('key')
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->SelectControl()->name('check_status')->label(__('holiday_apply.check_status'))
|
||||
->options(CheckStatus::options())
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
]),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('store.title')->label(__('employee_sign.store_id')),
|
||||
amisMake()->TableColumn()->name('employee.name')->label(__('holiday_apply.employee_id')),
|
||||
amisMake()->TableColumn()->name('type.name')->label(__('holiday_apply.type_id')),
|
||||
amisMake()->TableColumn()->name('reason')->label(__('holiday_apply.reason')),
|
||||
amisMake()->TableColumn()->name('start_at')->label(__('holiday_apply.start_at')),
|
||||
amisMake()->TableColumn()->name('end_at')->label(__('holiday_apply.end_at')),
|
||||
amisMake()->TableColumn()->name('check_status')->label(__('holiday_apply.check_status'))->set('type', 'mapping')->map(CheckStatus::options()),
|
||||
amisMake()->TableColumn()->name('created_at')->label(__('holiday_apply.created_at')),
|
||||
$this->rowActions([
|
||||
$this->rowShowButton()->visible(Admin::user()->can('admin.hr.holiday.view')),
|
||||
$this->rowEditTypeButton('drawer', 'xl')
|
||||
->visible(Admin::user()->can('admin.hr.holiday.update'))
|
||||
->visibleOn('${OR(check_status == '.CheckStatus::None->value.', check_status == '.CheckStatus::Cancel->value.', check_status == '.CheckStatus::Fail->value.')}'),
|
||||
$this->rowDeleteButton()
|
||||
->visible(Admin::user()->can('admin.hr.holiday.delete'))
|
||||
->visibleOn('${OR(check_status == '.CheckStatus::None->value.', check_status == '.CheckStatus::Cancel->value.', check_status == '.CheckStatus::Fail->value.')}'),
|
||||
$this->applyAction(),
|
||||
$this->cancelAction(),
|
||||
]),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form($edit): Form
|
||||
{
|
||||
return $this->baseForm()->title('')->body([
|
||||
amisMake()->SelectControl()->name('employee_id')->label(__('holiday_apply.employee_id'))
|
||||
->source(admin_url('api/employees?_all=1&store_id_gt=0&employee_status='.EmployeeStatus::Online->value))
|
||||
->labelField('name')
|
||||
->valueField('id')
|
||||
->searchable()
|
||||
->joinValues(false)
|
||||
->extractValue()
|
||||
->required(),
|
||||
amisMake()->SelectControl()
|
||||
->name('type_id')
|
||||
->label(__('holiday_apply.type_id'))
|
||||
->source(admin_url('api/keywords/tree-list?parent_key=holiday_type'))
|
||||
->labelField('name')
|
||||
->valueField('key')
|
||||
->required(),
|
||||
amisMake()->DateRangeControl()
|
||||
->format('YYYY-MM-DD')
|
||||
->name('date_range')
|
||||
->label(__('holiday_apply.date'))
|
||||
->required(),
|
||||
amisMake()->TextControl()->name('reason')->label(__('holiday_apply.reason'))->required(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
$subjectType = $this->getMorphAlias();
|
||||
$detail = amisMake()->Property()->items([
|
||||
['label' => __('holiday_apply.store_id'), 'content' => '${store.title}'],
|
||||
['label' => __('holiday_apply.employee_id'), 'content' => '${employee.name}'],
|
||||
['label' => __('holiday_apply.type_id'), 'content' => '${type.name}'],
|
||||
['label' => __('holiday_apply.date'), 'content' => '${start_at} ${end_at}'],
|
||||
['label' => __('holiday_apply.reason'), 'content' => '${reason}'],
|
||||
['label' => __('holiday_apply.created_at'), 'content' => '${created_at}'],
|
||||
['label' => __('holiday_apply.check_status'), 'content' => amisMake()->Mapping()->name('check_status')->map(CheckStatus::options())],
|
||||
['label' => __('holiday_apply.checked_at'), 'content' => '${checked_at}'],
|
||||
['label' => __('holiday_apply.check_remarks'), 'content' => '${check_remarks}'],
|
||||
]);
|
||||
$table = amisMake()->Service()
|
||||
->id('holiday-checklog-table')
|
||||
->initFetch(false)
|
||||
->api(
|
||||
amisMake()->BaseApi()->method('get')->url(admin_url('api/workflow/logs'))->data([
|
||||
'subject_type' => $subjectType,
|
||||
'subject_id' => '${id}',
|
||||
])
|
||||
)
|
||||
->body(
|
||||
amisMake()->Table()->columnsTogglable(false)->itemActions([
|
||||
$this->succesAction()->reload('holiday-detail'),
|
||||
$this->failAction()->reload('holiday-detail'),
|
||||
])->columns([
|
||||
amisMake()->TableColumn()->name('batch_id')->label(__('workflow_log.batch_id')),
|
||||
amisMake()->TableColumn()->name('check_name')->label(__('workflow_log.check_name')),
|
||||
amisMake()->TableColumn()->name('check_user.name')->label(__('workflow_log.check_user_id')),
|
||||
amisMake()->TableColumn()->name('check_status')->label(__('workflow_log.check_status'))->set('type', 'mapping')->map(CheckStatus::options()),
|
||||
amisMake()->TableColumn()->name('checked_at')->label(__('workflow_log.checked_at')),
|
||||
amisMake()->TableColumn()->name('remarks')->label(__('workflow_log.remarks')),
|
||||
])
|
||||
);
|
||||
return $this->baseDetail()->id('holiday-detail')->title('')->onEvent([
|
||||
'inited' => [
|
||||
'actions' => [
|
||||
['actionType' => 'reload', 'componentId' => 'holiday-checklog-table'],
|
||||
]
|
||||
]
|
||||
])->body([$detail, amisMake()->Divider(), $table]);
|
||||
}
|
||||
|
||||
public function getMorphAlias()
|
||||
{
|
||||
return (new HolidayApply)->getMorphClass();
|
||||
}
|
||||
}
|
||||
|
|
@ -32,4 +32,9 @@ class EmployeeSignRepairFilter extends ModelFilter
|
|||
$end = Carbon::createFromTimestamp(data_get($dates, 1, time()))->endOfDay();
|
||||
$this->whereBetween('date', [$start, $end]);
|
||||
}
|
||||
|
||||
public function checkStatus($key)
|
||||
{
|
||||
$this->where('check_status', $key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class HolidayApplyFilter extends ModelFilter
|
||||
{
|
||||
protected $drop_id = false;
|
||||
|
||||
public $relations = [
|
||||
'store' => [
|
||||
'store_title' => 'title',
|
||||
],
|
||||
'employee' => [
|
||||
'employee_name' => 'name',
|
||||
'employee_search' => 'search',
|
||||
],
|
||||
];
|
||||
|
||||
public function employeeId($key)
|
||||
{
|
||||
$this->where('employee_id', $key);
|
||||
}
|
||||
|
||||
public function typeId($key)
|
||||
{
|
||||
$this->where('type_id', $key);
|
||||
}
|
||||
|
||||
public function checkStatus($key)
|
||||
{
|
||||
$this->where('check_status', $key);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services;
|
||||
|
||||
use App\Admin\Filters\HolidayApplyFilter;
|
||||
use App\Models\{HolidayApply, Employee};
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class HolidayApplyService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = ['store', 'employee', 'type'];
|
||||
|
||||
protected string $modelName = HolidayApply::class;
|
||||
|
||||
protected string $modelFilterName = HolidayApplyFilter::class;
|
||||
|
||||
public function resloveData($data, $model = null)
|
||||
{
|
||||
// 获取员工所在的门店
|
||||
if (!isset($data['store_id']) && isset($data['employee_id'])) {
|
||||
$data['store_id'] = Employee::where('id', $data['employee_id'])->value('store_id');
|
||||
}
|
||||
// 处理日期
|
||||
if (isset($data['date_range']) && !isset($data['start_at']) && !isset($data['end_at'])) {
|
||||
$dates = explode(',', $data['date_range']);
|
||||
$data['start_at'] = Carbon::createFromFormat('Y-m-d', data_get($dates, 0))->startOfDay();
|
||||
$data['end_at'] = Carbon::createFromFormat('Y-m-d', data_get($dates, 1))->endOfDay();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function validate($data, $model = null)
|
||||
{
|
||||
// 验证申请时间是否重叠
|
||||
if (HolidayApply::where('employee_id', data_get($data, 'employee_id', $model?->employee_id))->where(fn($q) => $q->whereBetween('start_at', [$data['start_at'], $data['end_at']])->orWhereBetween('end_at', [$data['start_at'], $data['end_at']]))->exists()) {
|
||||
return '该时间段已经申请过了';
|
||||
}
|
||||
$createRules = [
|
||||
'employee_id' => ['required'],
|
||||
'type_id' => ['required'],
|
||||
'reason' => ['required'],
|
||||
'start_at' => ['required'],
|
||||
'end_at' => ['required'],
|
||||
];
|
||||
$updateRules = [];
|
||||
$validator = Validator::make($data, $model ? $updateRules : $createRules, []);
|
||||
if ($validator->fails()) {
|
||||
return $validator->errors()->first();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ use App\Admin\Controllers\Hr\RestController;
|
|||
use App\Admin\Controllers\Hr\SignController;
|
||||
use App\Admin\Controllers\Hr\SignLogController;
|
||||
use App\Admin\Controllers\Hr\SignRepairController;
|
||||
use App\Admin\Controllers\Hr\HolidayController;
|
||||
use App\Admin\Controllers\Store\DeviceController;
|
||||
use App\Admin\Controllers\Store\EmployeeController as StoreEmployeeController;
|
||||
use App\Admin\Controllers\Store\StoreController;
|
||||
|
|
@ -81,6 +82,8 @@ Route::group([
|
|||
$router->resource('signs', SignController::class)->only(['index', 'show']);
|
||||
// 补卡申请
|
||||
$router->resource('repairs', SignRepairController::class);
|
||||
// 请假申请
|
||||
$router->resource('holiday', HolidayController::class);
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Enums\SignTime;
|
||||
use App\Enums\{SignTime, CheckStatus};
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Contracts\Checkable;
|
||||
|
|
@ -23,7 +23,8 @@ class EmployeeSignRepair extends Model implements Checkable
|
|||
protected $casts = [
|
||||
'date' => 'date:Y-m-d',
|
||||
'checked_at' => 'datetime',
|
||||
'repair_type' => SignTime::class
|
||||
'repair_type' => SignTime::class,
|
||||
'check_status' => CheckStatus::class,
|
||||
];
|
||||
|
||||
public function modelFilter()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Contracts\Checkable;
|
||||
use App\Traits\HasCheckable;
|
||||
use App\Traits\HasDateTimeFormatter;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Enums\{CheckStatus};
|
||||
|
||||
/**
|
||||
* 请假申请
|
||||
*/
|
||||
class HolidayApply extends Model implements Checkable
|
||||
{
|
||||
use Filterable, HasCheckable, HasDateTimeFormatter;
|
||||
|
||||
protected $fillable = ['store_id', 'employee_id', 'start_at', 'end_at', 'type_id', 'reason', 'check_status', 'checked_at', 'check_remarks'];
|
||||
|
||||
protected $casts = [
|
||||
'start_at' => 'date:Y-m-d',
|
||||
'end_at' => 'date:Y-m-d',
|
||||
'check_status' => CheckStatus::class,
|
||||
];
|
||||
|
||||
public function modelFilter()
|
||||
{
|
||||
return App\Admin\Filters\HolidayApplyFilter::class;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
|
||||
public function type()
|
||||
{
|
||||
// holiday_type
|
||||
return $this->belongsTo(Keyword::class, 'type_id', 'key');
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ class AppServiceProvider extends ServiceProvider
|
|||
collect([
|
||||
\App\Models\AdminUser::class,
|
||||
\App\Models\EmployeeSignRepair::class,
|
||||
\App\Models\HolidayApply::class,
|
||||
])->mapWithKeys(fn ($model) => [(new $model)->getTable() => $model])->all()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use App\Enums\CheckStatus;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('holiday_applies', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->comment('门店, stores.id');
|
||||
$table->foreignId('employee_id')->comment('申请人, employees.id');
|
||||
$table->datetime('start_at')->comment('结束时间');
|
||||
$table->datetime('end_at')->comment('开始时间');
|
||||
$table->string('type_id')->comment('类型(holiday_type), keywords.key');
|
||||
$table->string('reason')->comment('事由');
|
||||
|
||||
$table->unsignedInteger('check_status')->default(CheckStatus::None->value)->comment('审核状态');
|
||||
$table->timestamp('checked_at')->nullable()->comment('审核通过时间');
|
||||
$table->string('check_remarks')->nullable()->comment('审核未通过原因');
|
||||
$table->timestamps();
|
||||
$table->comment('请假申请');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('holiday_applies');
|
||||
}
|
||||
};
|
||||
|
|
@ -128,6 +128,12 @@ class AdminPermissionSeeder extends Seeder
|
|||
'uri' => '/hr/repairs',
|
||||
'resource' => true,
|
||||
],
|
||||
'holiday' => [
|
||||
'name' => '请假申请',
|
||||
'icon' => '',
|
||||
'uri' => '/hr/holiday',
|
||||
'resource' => true,
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,11 @@ class KeywordSeeder extends Seeder
|
|||
'name' => '上报数据类型',
|
||||
'children' => ['大乐透', '七星彩', '排列三', '排列五', '合买', '即开', ['key' => 'ledger_item_type_other', 'name' => '其他']],
|
||||
],
|
||||
[
|
||||
'key' => 'holiday_type',
|
||||
'name' => '请假类型',
|
||||
'children' => ['病假', '事假'],
|
||||
]
|
||||
];
|
||||
|
||||
$this->insertKeywors($keywords);
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ class WorkflowSeeder extends Seeder
|
|||
public function run(): void
|
||||
{
|
||||
$now = now();
|
||||
$config = [
|
||||
$config = json_encode([
|
||||
["sort" => 1, "type" => "user", "user" => 1, "title" => "员工", "value" => 1, "subTitle" => "Admin"],
|
||||
];
|
||||
]);
|
||||
Workflow::truncate();
|
||||
Workflow::insert([
|
||||
['key' => 'employee_sign_repair', 'name' => '补卡申请', 'config' => json_encode($config), 'created_at' => now(), 'updated_at' => now()]
|
||||
['key' => 'employee_sign_repair', 'name' => '补卡申请', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
|
||||
['key' => 'holiday_apply', 'name' => '请假申请', 'config' => $config, 'created_at' => now(), 'updated_at' => now()],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'created_at' => '提交日期',
|
||||
'updated_at' => '更新时间',
|
||||
|
||||
'check_status' => '审核状态',
|
||||
'checked_at' => '审核通过时间',
|
||||
'check_remarks' => '审核未通过原因',
|
||||
'start_at' => '开始时间',
|
||||
'end_at' => '结束时间',
|
||||
'date' => '请假日期',
|
||||
|
||||
'store_id' => '门店',
|
||||
'employee_id' => '员工',
|
||||
'reason' => '请假事由',
|
||||
'type_id' => '请假类型',
|
||||
];
|
||||
Loading…
Reference in New Issue