store-manage/app/Admin/Services/Plan/TaskService.php

229 lines
7.4 KiB
PHP

<?php
namespace App\Admin\Services\Plan;
use App\Admin\Filters\TaskFilter;
use App\Admin\Services\BaseService;
use App\Enums\TaskStatus;
use App\Models\Ledger;
use App\Models\Plan;
use App\Models\PlanHygiene;
use App\Models\PlanPerformance;
use App\Models\Store;
use App\Models\Task;
use App\Models\TaskHygiene;
use App\Models\TaskLedger;
use App\Models\TaskPerformance;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Validator;
/**
* @method Task getModel()
* @method Task|Builder query()
*/
class TaskService extends BaseService
{
protected string $modelName = Task::class;
protected string $modelFilterName = TaskFilter::class;
public function getDetail($id)
{
if ($task = parent::getDetail($id)) {
$task->taskable->setRelation('task', $task->withoutRelations());
}
return $task;
}
public function store($data): bool
{
if (! isset($data['plan_id'])) {
admin_abort('任务计划未找到');
}
/** @var \App\Models\Plan */
$plan = Plan::findOrFail($data['plan_id']);
if (! $plan->isPublished()) {
admin_abort('任务计划未发布');
}
switch (get_class($planable = $plan->planable)) {
// 业绩指标
case PlanPerformance::class:
$payload = $data['task_performance'] ?? [];
Validator::validate(
data: $payload,
rules: [
'store_id' => ['bail', 'required'],
'expected_performance' => ['bail', 'required', 'numeric', 'min:0'],
],
attributes: [
'store_id' => __('plan.task_performance.store'),
'expected_performance' => __('plan.task_performance.expected_performance'),
],
);
/** @var \App\Models\Store */
$store = Store::findOrFail($payload['store_id']);
if (TaskPerformance::where('store_id', $store->id)->where('month', $planable->month)->exists()) {
admin_abort('门店已有业绩指标任务');
}
// 开始时间
$startAt = Carbon::createFromFormat('Y-m-d H:i:s', "{$planable->month}-01 00:00:00");
// 结束时间
$endAt = $startAt->copy()->endOfMonth();
// 门店实际业绩
$actualPerformance = Ledger::where('store_id', $store->id)
->whereBetween('date', [$startAt->format('Y-m-d'), $endAt->format('Y-m-d')])
->sum('sales');
/** @var \App\Models\TaskPerformance */
$taskable = TaskPerformance::create([
'month' => $planable->month,
'store_id' => $store->id,
'store_master_id' => $store->master_id,
'actual_performance' => $actualPerformance,
'expected_performance' => $payload['expected_performance'],
]);
$task = new Task([
'plan_id' => $plan->id,
'name' => '业绩指标',
'start_at' => $startAt,
'end_at' => $endAt,
'task_status' => TaskStatus::Pending,
]);
if ($taskable->isSuccess()) {
$task->task_status = TaskStatus::Success;
$task->completed_at = now();
}
$taskable->task()->save($task);
break;
// 清洁卫生
case PlanHygiene::class:
$payload = $data['task_hygiene'] ?? [];
Validator::validate(
data: $payload,
rules: [
'store_id' => ['bail', 'required'],
],
attributes: [
'store_id' => __('plan.task_hygiene.store'),
],
);
/** @var \App\Models\Store */
$store = Store::findOrFail($payload['store_id']);
if (TaskHygiene::where('store_id', $store->id)->where('month', $planable->month)->exists()) {
admin_abort('门店已有清洁卫生任务');
}
$taskable = TaskHygiene::create([
'month' => $planable->month,
'store_id' => $store->id,
'store_master_id' => $store->master_id,
]);
// 开始时间
$startAt = Carbon::createFromFormat('Y-m-d H:i:s', "{$planable->month}-01 00:00:00");
// 结束时间
$endAt = $startAt->copy()->endOfMonth();
$taskable->task()->create([
'plan_id' => $plan->id,
'name' => '清洁卫生',
'start_at' => $startAt,
'end_at' => $endAt,
'task_status' => TaskStatus::Pending,
]);
break;
default:
admin_abort('任务计划不可新增任务');
break;
}
return true;
}
public function update($primaryKey, $data): bool
{
/** @var \App\Models\Task */
$task = Task::findOrFail($primaryKey);
if (in_array($task->task_status, [TaskStatus::Success, TaskStatus::Failed])) {
admin_abort("[{$task->task_status->text()}]任务不可修改");
}
switch (get_class($taskable = $task->taskable)) {
// 业绩指标
case TaskPerformance::class:
$payload = $data['task_performance'] ?? [];
Validator::validate(
data: $payload,
rules: [
'expected_performance' => ['bail', 'required', 'numeric', 'min:0'],
],
attributes: [
'expected_performance' => __('plan.task_performance.expected_performance'),
],
);
$taskable->update([
'expected_performance' => $payload['expected_performance'],
]);
if (! $task->isSuccess() && $taskable->isSuccess()) {
$task->markAsSuccess();
}
break;
default:
admin_abort('任务不可修改');
break;
}
return true;
}
public function preDelete(array $ids): void
{
/** @var \Illuminate\Database\Eloquent\Collection */
$tasks = Task::findMany($ids);
$tasks->each(fn (Task $task) => $task->taskable()->delete());
}
public function addRelations($query, string $scene = 'list')
{
if (in_array($scene, ['edit', 'detail'])) {
$query->with([
'taskable' => function (MorphTo $morphTo) {
$morphTo->morphWith([
TaskLedger::class => ['store', 'storeMaster'],
TaskPerformance::class => ['store', 'storeMaster'],
TaskHygiene::class => ['store', 'storeMaster', 'workflow'],
]);
},
]);
}
}
}