28 lines
1.2 KiB
PHP
28 lines
1.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\CrmTask;
|
|
use App\Models\Lead;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
final class CrmNextAction
|
|
{
|
|
/** @return Builder<CrmTask> */
|
|
public function future(Lead $lead, ?string $exceptTask = null): Builder
|
|
{
|
|
return CrmTask::availableForWork()->where('tasks.lead_id', $lead->id)->where('tasks.due_at', '>', now())
|
|
->when($exceptTask !== null, fn ($query) => $query->where('tasks.id', '!=', $exceptTask));
|
|
}
|
|
|
|
/** Both write paths lock the dossier (when linked), lead, then task before checking. */
|
|
public function assertMayFinish(?Lead $lead, CrmTask $task, string $status): void
|
|
{
|
|
if ($lead !== null && ! $lead->trashed() && in_array($lead->status, ['new', 'qualified'], true)
|
|
&& in_array($status, ['done', 'cancelled'], true) && ! $this->future($lead, $task->id)->exists()) {
|
|
throw ValidationException::withMessages(['status' => 'Crie a próxima acção com prazo futuro antes de encerrar a última tarefa de um acompanhamento activo. Tarefas num dossier encerrado não estão disponíveis.']);
|
|
}
|
|
}
|
|
}
|