generated from liutk/owl-admin-base
admin 加班申请
parent
a013b50bcf
commit
73b3f4342b
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers\Hr;
|
||||
|
||||
use App\Admin\Controllers\AdminController;
|
||||
use App\Admin\Services\OvertimeApplyService;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use App\Enums\{CheckStatus, EmployeeStatus};
|
||||
use App\Models\OvertimeApply;
|
||||
use App\Traits\HasCheckActions;
|
||||
|
||||
/**
|
||||
* 加班管理
|
||||
*/
|
||||
class OvertimeController extends AdminController
|
||||
{
|
||||
use HasCheckActions;
|
||||
|
||||
protected string $serviceName = OvertimeApplyService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createTypeButton('drawer', 'xl')->visible(Admin::user()->can('admin.hr.overtime.create')),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->bulkActions([])
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amisMake()->SelectControl()->name('store_id')->label(__('overtime_apply.store_id'))
|
||||
->source(admin_url('api/stores?_all=1'))
|
||||
->labelField('title')
|
||||
->valueField('id')
|
||||
->searchable()
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->TextControl()->name('employee_name')->label(__('overtime_apply.employee_id'))
|
||||
->placeholder(__('employee.name').'/'.__('employee.phone'))
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->DateRangeControl()->name('date_range')->label(__('overtime_apply.date'))
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
amisMake()->SelectControl()->name('check_status')->label(__('overtime_apply.check_status'))
|
||||
->options(CheckStatus::options())
|
||||
->columnRatio(3)
|
||||
->clearable(),
|
||||
]),
|
||||
]))
|
||||
->columns([
|
||||
amisMake()->TableColumn()->name('store.title')->label(__('overtime_apply.store_id')),
|
||||
amisMake()->TableColumn()->name('employee.name')->label(__('overtime_apply.employee_id')),
|
||||
amisMake()->TableColumn()->name('date')->label(__('overtime_apply.date')),
|
||||
amisMake()->TableColumn()->name('hours')->label(__('overtime_apply.hours')),
|
||||
amisMake()->TableColumn()->name('check_status')->label(__('overtime_apply.check_status'))->set('type', 'mapping')->map(CheckStatus::options()),
|
||||
amisMake()->TableColumn()->name('created_at')->label(__('overtime_apply.created_at')),
|
||||
$this->rowActions([
|
||||
$this->rowShowButton()->visible(Admin::user()->can('admin.hr.overtime.view')),
|
||||
$this->rowEditTypeButton('drawer', 'xl')
|
||||
->visible(Admin::user()->can('admin.hr.overtime.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.overtime.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(__('overtime_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()->InputDatetimeRange()
|
||||
->name('datetime_range')
|
||||
->label(__('overtime_apply.date'))
|
||||
->required(),
|
||||
amisMake()->TextControl()->name('reason')->label(__('overtime_apply.reason')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
$subjectType = $this->getMorphAlias();
|
||||
$detail = amisMake()->Property()->items([
|
||||
['label' => __('overtime_apply.store_id'), 'content' => '${store.title}'],
|
||||
['label' => __('overtime_apply.employee_id'), 'content' => '${employee.name}'],
|
||||
['label' => __('overtime_apply.date'), 'content' => '${date}'],
|
||||
['label' => __('overtime_apply.start_at'), 'content' => '${start_at}'],
|
||||
['label' => __('overtime_apply.end_at'), 'content' => '${end_at}'],
|
||||
['label' => __('overtime_apply.hours'), 'content' => '${hours}'],
|
||||
['label' => __('overtime_apply.created_at'), 'content' => '${created_at}'],
|
||||
['label' => __('overtime_apply.reason'), 'content' => '${reason}', 'span' => 2],
|
||||
['label' => __('overtime_apply.check_status'), 'content' => amisMake()->Mapping()->name('check_status')->map(CheckStatus::options())],
|
||||
['label' => __('overtime_apply.checked_at'), 'content' => '${checked_at}'],
|
||||
['label' => __('overtime_apply.check_remarks'), 'content' => '${check_remarks}'],
|
||||
]);
|
||||
$table = amisMake()->Service()
|
||||
->id('overtime-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('overtime-detail'),
|
||||
$this->failAction()->reload('overtime-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('overtime-detail')->title('')->onEvent([
|
||||
'inited' => [
|
||||
'actions' => [
|
||||
['actionType' => 'reload', 'componentId' => 'overtime-checklog-table'],
|
||||
]
|
||||
]
|
||||
])->body([$detail, amisMake()->Divider(), $table]);
|
||||
}
|
||||
|
||||
public function getMorphAlias()
|
||||
{
|
||||
return (new OvertimeApply)->getMorphClass();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class OvertimeApplyFilter 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 checkStatus($key)
|
||||
{
|
||||
$this->where('check_status', $key);
|
||||
}
|
||||
|
||||
public function dateRange($key)
|
||||
{
|
||||
$dates = explode(',', $key);
|
||||
$start = Carbon::createFromTimestamp(data_get($dates, 0, time()))->startOfDay();
|
||||
$end = Carbon::createFromTimestamp(data_get($dates, 1, time()))->endOfDay();
|
||||
$this->whereBetween('date', [$start, $end]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Services;
|
||||
|
||||
use App\Admin\Filters\OvertimeApplyFilter;
|
||||
use App\Models\{OvertimeApply, Employee};
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class OvertimeApplyService extends BaseService
|
||||
{
|
||||
protected array $withRelationships = ['store', 'employee'];
|
||||
|
||||
protected string $modelName = OvertimeApply::class;
|
||||
|
||||
protected string $modelFilterName = OvertimeApplyFilter::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['datetime_range'])) {
|
||||
$time = explode(',', $data['datetime_range']);
|
||||
$start = Carbon::createFromTimestamp(data_get($time, 0));
|
||||
$end = Carbon::createFromTimestamp(data_get($time, 1));
|
||||
$data['start_at'] = $start;
|
||||
$data['end_at'] = $end;
|
||||
$data['date'] = $start->format('Y-m-d');
|
||||
$data['hours'] = $start->diffInHours($end);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function validate($data, $model = null)
|
||||
{
|
||||
$createRules = [
|
||||
'employee_id' => ['required'],
|
||||
'start_at' => ['required'],
|
||||
'end_at' => ['required'],
|
||||
];
|
||||
$updateRules = [];
|
||||
$validator = Validator::make($data, $model ? $updateRules : $createRules, []);
|
||||
if ($validator->fails()) {
|
||||
return $validator->errors()->first();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ 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\Hr\OvertimeController;
|
||||
use App\Admin\Controllers\Store\DeviceController;
|
||||
use App\Admin\Controllers\Store\EmployeeController as StoreEmployeeController;
|
||||
use App\Admin\Controllers\Store\StoreController;
|
||||
|
|
@ -84,6 +85,8 @@ Route::group([
|
|||
$router->resource('repairs', SignRepairController::class);
|
||||
// 请假申请
|
||||
$router->resource('holiday', HolidayController::class);
|
||||
// 加班申请
|
||||
$router->resource('overtime', OvertimeController::class);
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<?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 OvertimeApply extends Model implements Checkable
|
||||
{
|
||||
use Filterable, HasDateTimeFormatter, HasCheckable;
|
||||
|
||||
protected $fillable = ['store_id', 'employee_id', 'date', 'start_at', 'end_at', 'hours', 'reason', 'check_status', 'checked_at', 'check_remarks'];
|
||||
|
||||
protected $casts = [
|
||||
'date' => 'date:Y-m-d',
|
||||
'start_at' => 'datetime',
|
||||
'end_at' => 'datetime',
|
||||
'check_status' => CheckStatus::class,
|
||||
];
|
||||
|
||||
public function modelFilter()
|
||||
{
|
||||
return App\Admin\Filters\HolidayApplyFilter::class;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ class AppServiceProvider extends ServiceProvider
|
|||
\App\Models\AdminUser::class,
|
||||
\App\Models\EmployeeSignRepair::class,
|
||||
\App\Models\HolidayApply::class,
|
||||
\App\Models\OvertimeApply::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('overtime_applies', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('store_id')->comment('门店, stores.id');
|
||||
$table->foreignId('employee_id')->comment('申请人, employees.id');
|
||||
$table->date('date')->comment('加班日期');
|
||||
$table->timestamp('start_at')->comment('结束时间');
|
||||
$table->timestamp('end_at')->comment('开始时间');
|
||||
$table->unsignedInteger('hours')->comment('时长');
|
||||
$table->string('reason')->nullable()->comment('事由');
|
||||
|
||||
$table->unsignedInteger('check_status')->default(CheckStatus::None->value)->comment('审核状态');
|
||||
$table->timestamp('checked_at')->nullable()->comment('审核通过时间');
|
||||
$table->string('check_remarks')->nullable()->comment('审核未通过原因');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('overtime_applies');
|
||||
}
|
||||
};
|
||||
|
|
@ -133,7 +133,13 @@ class AdminPermissionSeeder extends Seeder
|
|||
'icon' => '',
|
||||
'uri' => '/hr/holiday',
|
||||
'resource' => true,
|
||||
]
|
||||
],
|
||||
'overtime' => [
|
||||
'name' => '加班申请',
|
||||
'icon' => '',
|
||||
'uri' => '/hr/overtime',
|
||||
'resource' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class WorkflowSeeder extends Seeder
|
|||
Workflow::insert([
|
||||
['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()],
|
||||
['key' => 'overtime_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' => '加班日期',
|
||||
'hours' => '时长',
|
||||
|
||||
'store_id' => '门店',
|
||||
'employee_id' => '员工',
|
||||
'reason' => '加班事由',
|
||||
];
|
||||
Loading…
Reference in New Issue