M3 Integration fixes

This commit is contained in:
Mark Gregory
2026-09-21 10:14:57 +01:00
parent 4af997c465
commit 6d60cbff84
5853 changed files with 79032 additions and 1825 deletions
+80 -59
View File
@@ -11,7 +11,6 @@ use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Livewire\Component;
use Modules\Helpdesk\Models\AutomationRule;
@@ -32,6 +31,30 @@ use Modules\Helpdesk\Support\Color;
final class SettingsManager extends Component
{
private const RULE_MAX_40 = 'max:40';
private const RULE_MAX_80 = 'max:80';
private const RULE_MAX_100 = 'max:100';
private const RULE_MAX_120 = 'max:120';
private const RULE_MAX_160 = 'max:160';
private const RULE_MAX_180 = 'max:180';
private const RULE_MAX_220 = 'max:220';
private const RULE_MAX_500 = 'max:500';
private const RULE_MIN_0 = 'min:0';
private const RULE_TEAM_EXISTS = 'exists:helpdesk_teams,id';
private const RULE_PROJECT_EXISTS = 'exists:helpdesk_projects,id';
private const RULE_CATEGORY_EXISTS = 'exists:helpdesk_categories,id';
public string $section = 'statuses';
public int|string|null $default_helpdesk_company_id = null;
@@ -127,10 +150,10 @@ final class SettingsManager extends Component
public function saveStatus(): void
{
$data = $this->validate([
'statusForm.name' => ['required', 'string', 'max:80'],
'statusForm.slug' => ['nullable', 'string', 'max:100'],
'statusForm.name' => ['required', 'string', self::RULE_MAX_80],
'statusForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
'statusForm.color' => ['required', 'string', Color::validationRule()],
'statusForm.sort_order' => ['required', 'integer', 'min:0'],
'statusForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
'statusForm.is_closed' => ['boolean'],
'statusForm.is_default' => ['boolean'],
])['statusForm'];
@@ -168,10 +191,10 @@ final class SettingsManager extends Component
public function savePriority(): void
{
$data = $this->validate([
'priorityForm.name' => ['required', 'string', 'max:80'],
'priorityForm.slug' => ['nullable', 'string', 'max:100'],
'priorityForm.name' => ['required', 'string', self::RULE_MAX_80],
'priorityForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
'priorityForm.color' => ['required', 'string', Color::validationRule()],
'priorityForm.sort_order' => ['required', 'integer', 'min:0'],
'priorityForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
'priorityForm.is_default' => ['boolean'],
])['priorityForm'];
@@ -210,7 +233,7 @@ final class SettingsManager extends Component
$data = $this->validate([
'categoryForm.company_id' => ['nullable', 'integer'],
'categoryForm.name' => ['required', 'string', 'max:120'],
'categoryForm.name' => ['required', 'string', self::RULE_MAX_120],
'categoryForm.slug' => ['nullable', 'string', 'max:140'],
'categoryForm.color' => ['required', 'string', Color::validationRule()],
'categoryForm.description' => ['nullable', 'string'],
@@ -252,7 +275,7 @@ final class SettingsManager extends Component
$data = $this->validate([
'teamForm.company_id' => ['nullable', 'integer'],
'teamForm.name' => ['required', 'string', 'max:120'],
'teamForm.name' => ['required', 'string', self::RULE_MAX_120],
'teamForm.slug' => ['nullable', 'string', 'max:140'],
'teamForm.color' => ['required', 'string', Color::validationRule()],
'teamForm.description' => ['nullable', 'string'],
@@ -294,9 +317,9 @@ final class SettingsManager extends Component
$data = $this->validate([
'projectForm.company_id' => ['nullable', 'integer'],
'projectForm.team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
'projectForm.title' => ['required', 'string', 'max:160'],
'projectForm.slug' => ['nullable', 'string', 'max:180'],
'projectForm.team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
'projectForm.title' => ['required', 'string', self::RULE_MAX_160],
'projectForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'projectForm.color' => ['required', 'string', Color::validationRule()],
'projectForm.description' => ['nullable', 'string'],
'projectForm.is_default' => ['boolean'],
@@ -336,12 +359,12 @@ final class SettingsManager extends Component
$this->normalizeNullableFormValues('boardForm', ['owner_id']);
$data = $this->validate([
'boardForm.name' => ['required', 'string', 'max:160'],
'boardForm.slug' => ['nullable', 'string', 'max:180'],
'boardForm.name' => ['required', 'string', self::RULE_MAX_160],
'boardForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'boardForm.description' => ['nullable', 'string'],
'boardForm.owner_id' => ['nullable', 'integer', 'exists:users,id'],
'boardForm.is_default' => ['boolean'],
'boardForm.sort_order' => ['required', 'integer', 'min:0'],
'boardForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
'boardForm.status_ids' => ['array'],
'boardForm.status_ids.*' => ['integer', 'exists:helpdesk_statuses,id'],
])['boardForm'];
@@ -404,12 +427,12 @@ final class SettingsManager extends Component
$data = $this->validate([
'repositoryForm.company_id' => ['nullable', 'integer'],
'repositoryForm.project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
'repositoryForm.name' => ['required', 'string', 'max:160'],
'repositoryForm.provider' => ['required', 'string', 'max:40'],
'repositoryForm.remote_url' => ['required', 'string', 'max:500'],
'repositoryForm.default_branch' => ['required', 'string', 'max:120'],
'repositoryForm.webhook_secret' => ['nullable', 'string', 'max:120'],
'repositoryForm.project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
'repositoryForm.name' => ['required', 'string', self::RULE_MAX_160],
'repositoryForm.provider' => ['required', 'string', self::RULE_MAX_40],
'repositoryForm.remote_url' => ['required', 'string', self::RULE_MAX_500],
'repositoryForm.default_branch' => ['required', 'string', self::RULE_MAX_120],
'repositoryForm.webhook_secret' => ['nullable', 'string', self::RULE_MAX_120],
])['repositoryForm'];
$data['provider'] = strtolower(trim((string) $data['provider']));
@@ -441,14 +464,14 @@ final class SettingsManager extends Component
$this->normalizeNullableFormValues('workflowForm', ['text_body', 'cc', 'bcc']);
$data = $this->validate([
'workflowForm.name' => ['required', 'string', 'max:160'],
'workflowForm.event' => ['required', 'string', 'max:80'],
'workflowForm.subject' => ['required', 'string', 'max:220'],
'workflowForm.name' => ['required', 'string', self::RULE_MAX_160],
'workflowForm.event' => ['required', 'string', self::RULE_MAX_80],
'workflowForm.subject' => ['required', 'string', self::RULE_MAX_220],
'workflowForm.html_body' => ['required', 'string'],
'workflowForm.text_body' => ['nullable', 'string'],
'workflowForm.to_role' => ['required', 'string', 'max:40'],
'workflowForm.cc' => ['nullable', 'string', 'max:500'],
'workflowForm.bcc' => ['nullable', 'string', 'max:500'],
'workflowForm.to_role' => ['required', 'string', self::RULE_MAX_40],
'workflowForm.cc' => ['nullable', 'string', self::RULE_MAX_500],
'workflowForm.bcc' => ['nullable', 'string', self::RULE_MAX_500],
'workflowForm.is_active' => ['boolean'],
])['workflowForm'];
@@ -480,15 +503,15 @@ final class SettingsManager extends Component
$data = $this->validate([
'cannedForm.company_id' => ['nullable', 'integer'],
'cannedForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
'cannedForm.team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
'cannedForm.name' => ['required', 'string', 'max:160'],
'cannedForm.slug' => ['nullable', 'string', 'max:180'],
'cannedForm.visibility' => ['required', 'string', 'max:40'],
'cannedForm.subject' => ['nullable', 'string', 'max:220'],
'cannedForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
'cannedForm.team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
'cannedForm.name' => ['required', 'string', self::RULE_MAX_160],
'cannedForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'cannedForm.visibility' => ['required', 'string', self::RULE_MAX_40],
'cannedForm.subject' => ['nullable', 'string', self::RULE_MAX_220],
'cannedForm.body' => ['required', 'string'],
'cannedForm.is_active' => ['boolean'],
'cannedForm.sort_order' => ['required', 'integer', 'min:0'],
'cannedForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
])['cannedForm'];
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
$this->persistSettingModel(CannedResponse::class, $this->cannedForm['id'], $data);
@@ -520,9 +543,9 @@ final class SettingsManager extends Component
$data = $this->validate([
'slaForm.company_id' => ['nullable', 'integer'],
'slaForm.priority_id' => ['nullable', 'integer', 'exists:helpdesk_priorities,id'],
'slaForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
'slaForm.name' => ['required', 'string', 'max:160'],
'slaForm.slug' => ['nullable', 'string', 'max:180'],
'slaForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
'slaForm.name' => ['required', 'string', self::RULE_MAX_160],
'slaForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'slaForm.first_response_minutes' => ['required', 'integer', 'min:1'],
'slaForm.resolution_minutes' => ['required', 'integer', 'min:1'],
'slaForm.business_hours_only' => ['boolean'],
@@ -561,20 +584,20 @@ final class SettingsManager extends Component
$data = $this->validate([
'automationForm.company_id' => ['nullable', 'integer'],
'automationForm.name' => ['required', 'string', 'max:160'],
'automationForm.slug' => ['nullable', 'string', 'max:180'],
'automationForm.name' => ['required', 'string', self::RULE_MAX_160],
'automationForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'automationForm.match_sender' => ['nullable', 'string', 'max:190'],
'automationForm.match_subject' => ['nullable', 'string', 'max:220'],
'automationForm.match_subject' => ['nullable', 'string', self::RULE_MAX_220],
'automationForm.match_mailbox' => ['nullable', 'string', 'max:190'],
'automationForm.match_category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
'automationForm.match_category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
'automationForm.set_priority_id' => ['nullable', 'integer', 'exists:helpdesk_priorities,id'],
'automationForm.set_category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
'automationForm.set_team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
'automationForm.set_project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
'automationForm.set_category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
'automationForm.set_team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
'automationForm.set_project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
'automationForm.set_status_id' => ['nullable', 'integer', 'exists:helpdesk_statuses,id'],
'automationForm.set_agent_id' => ['nullable', 'integer', 'exists:users,id'],
'automationForm.is_active' => ['boolean'],
'automationForm.sort_order' => ['required', 'integer', 'min:0'],
'automationForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
])['automationForm'];
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
$this->persistSettingModel(AutomationRule::class, $this->automationForm['id'], $data);
@@ -605,11 +628,11 @@ final class SettingsManager extends Component
$data = $this->validate([
'productForm.company_id' => ['nullable', 'integer'],
'productForm.name' => ['required', 'string', 'max:160'],
'productForm.slug' => ['nullable', 'string', 'max:180'],
'productForm.name' => ['required', 'string', self::RULE_MAX_160],
'productForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'productForm.type' => ['required', 'string', 'max:60'],
'productForm.version' => ['nullable', 'string', 'max:80'],
'productForm.release_channel' => ['nullable', 'string', 'max:80'],
'productForm.version' => ['nullable', 'string', self::RULE_MAX_80],
'productForm.release_channel' => ['nullable', 'string', self::RULE_MAX_80],
'productForm.description' => ['nullable', 'string'],
'productForm.is_active' => ['boolean'],
])['productForm'];
@@ -642,8 +665,8 @@ final class SettingsManager extends Component
$data = $this->validate([
'tagForm.company_id' => ['nullable', 'integer'],
'tagForm.name' => ['required', 'string', 'max:80'],
'tagForm.slug' => ['nullable', 'string', 'max:100'],
'tagForm.name' => ['required', 'string', self::RULE_MAX_80],
'tagForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
'tagForm.color' => ['required', 'string', Color::validationRule()],
])['tagForm'];
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
@@ -676,10 +699,10 @@ final class SettingsManager extends Component
$data = $this->validate([
'checklistTemplateForm.company_id' => ['nullable', 'integer'],
'checklistTemplateForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
'checklistTemplateForm.project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
'checklistTemplateForm.name' => ['required', 'string', 'max:160'],
'checklistTemplateForm.slug' => ['nullable', 'string', 'max:180'],
'checklistTemplateForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
'checklistTemplateForm.project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
'checklistTemplateForm.name' => ['required', 'string', self::RULE_MAX_160],
'checklistTemplateForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
'checklistTemplateForm.items_text' => ['required', 'string'],
'checklistTemplateForm.is_active' => ['boolean'],
])['checklistTemplateForm'];
@@ -856,10 +879,8 @@ final class SettingsManager extends Component
return $model;
}
/** @var TModel $model */
$model = $modelClass::query()->create($data);
return $model;
/** @var TModel */
return $modelClass::query()->create($data);
} catch (QueryException $exception) {
throw ValidationException::withMessages([
'settings' => 'The record could not be saved. Check the slug is unique for this section/company and try again.',