seedStatuses(); $this->seedPriorities(); $this->seedCategories(); $this->seedTeamsAndProjects(); $this->seedKanbanBoards(); $this->seedWorkflowTemplates(); $this->seedRedmineInspiredDefaults(); } /** * Seed ticket workflow statuses. */ private function seedStatuses(): void { Status::query()->where('is_default', true)->update(['is_default' => false]); foreach ([ ['name' => 'New', 'slug' => 'new', 'color' => 'blue', 'sort_order' => 5, 'is_closed' => false, 'is_default' => true], ['name' => 'Open', 'slug' => 'open', 'color' => 'green', 'sort_order' => 10, 'is_closed' => false, 'is_default' => false], ['name' => 'In Progress', 'slug' => 'in-progress', 'color' => 'indigo', 'sort_order' => 20, 'is_closed' => false, 'is_default' => false], ['name' => 'Waiting Customer', 'slug' => 'waiting-customer', 'color' => 'amber', 'sort_order' => 30, 'is_closed' => false, 'is_default' => false], ['name' => 'Waiting Third Party', 'slug' => 'waiting-third-party', 'color' => 'purple', 'sort_order' => 40, 'is_closed' => false, 'is_default' => false], ['name' => 'Resolved', 'slug' => 'resolved', 'color' => 'green', 'sort_order' => 80, 'is_closed' => true, 'is_default' => false], ['name' => 'Closed', 'slug' => 'closed', 'color' => 'gray', 'sort_order' => 90, 'is_closed' => true, 'is_default' => false], ['name' => 'Cancelled', 'slug' => 'cancelled', 'color' => 'red', 'sort_order' => 100, 'is_closed' => true, 'is_default' => false], ] as $row) { Status::query()->updateOrCreate(['slug' => $row['slug']], $row); } } /** * Seed ticket priorities. */ private function seedPriorities(): void { Priority::query()->where('is_default', true)->update(['is_default' => false]); foreach ([ ['name' => 'Low', 'slug' => 'low', 'color' => 'gray', 'sort_order' => 10, 'is_default' => false], ['name' => 'Normal', 'slug' => 'normal', 'color' => 'blue', 'sort_order' => 20, 'is_default' => true], ['name' => 'High', 'slug' => 'high', 'color' => 'amber', 'sort_order' => 30, 'is_default' => false], ['name' => 'Urgent', 'slug' => 'urgent', 'color' => 'red', 'sort_order' => 40, 'is_default' => false], ['name' => 'Critical', 'slug' => 'critical', 'color' => 'red', 'sort_order' => 50, 'is_default' => false], ] as $row) { Priority::query()->updateOrCreate(['slug' => $row['slug']], $row); } } /** * Seed ticket categories. */ private function seedCategories(): void { Category::query() ->where('is_default', true) ->update(['is_default' => false]); foreach ([ ['name' => 'Development', 'color' => 'indigo', 'description' => 'Software changes, enhancements and development work.', 'is_default' => true], ['name' => 'Systems Deployment', 'color' => 'blue', 'description' => 'Deployment, release, infrastructure and environment requests.', 'is_default' => false], ['name' => 'Concepts', 'color' => 'purple', 'description' => 'Ideas, concepts, design discussion and future improvements.', 'is_default' => false], ['name' => 'Bug', 'color' => 'red', 'description' => 'Defects, regressions and incorrect behaviour.', 'is_default' => false], ] as $row) { Category::query()->updateOrCreate( ['slug' => Str::slug($row['name'])], $row + ['slug' => Str::slug($row['name'])], ); } } /** * Seed the default support team and a default project. */ private function seedTeamsAndProjects(): void { Team::query() ->where('is_default', true) ->update(['is_default' => false]); Project::query() ->where('is_default', true) ->update(['is_default' => false]); $team = Team::query()->updateOrCreate( ['slug' => 'support'], [ 'name' => 'Support', 'slug' => 'support', 'color' => 'blue', 'description' => 'Default support team for triage, ownership and ticket routing.', 'is_default' => true, ], ); Project::query()->updateOrCreate( ['slug' => 'support-desk'], [ 'team_id' => $team->id, 'title' => 'Support Desk', 'slug' => 'support-desk', 'color' => 'indigo', 'description' => 'Default project for operational helpdesk tickets.', 'is_default' => true, ], ); } /** * Seed the default configurable Kanban board. */ private function seedKanbanBoards(): void { KanbanBoard::query()->where('is_default', true)->update(['is_default' => false]); $board = KanbanBoard::query()->updateOrCreate( ['slug' => 'standard-support'], [ 'name' => 'Standard Support', 'slug' => 'standard-support', 'description' => 'Default Helpdesk workflow board covering new work through closure.', 'is_default' => true, 'sort_order' => 1, ], ); $statuses = Status::query() ->whereIn('slug', ['new', 'open', 'in-progress', 'stalled', 'on-hold', 'closed']) ->orderBy('sort_order') ->get(); $sync = []; foreach ($statuses as $index => $status) { $sync[$status->id] = ['sort_order' => ($index + 1) * 10]; } $board->statuses()->syncWithoutDetaching($sync); } /** * Seed default professional workflow email templates. */ private function seedWorkflowTemplates(): void { foreach ([ ['name' => 'Ticket raised requester notice', 'event' => 'ticket.created', 'subject' => 'Ticket {{ ticket.reference }} has been raised', 'html_body' => '

Hello {{ requester.name }},

Your ticket {{ ticket.reference }} has been raised successfully.

Subject: {{ ticket.subject }}

Priority: {{ ticket.priority }}

', 'to_role' => 'requester'], ['name' => 'Ticket updated requester notice', 'event' => 'ticket.updated', 'subject' => 'Ticket {{ ticket.reference }} has been updated', 'html_body' => '

Hello {{ requester.name }},

Your ticket {{ ticket.reference }} has been updated.

Status: {{ ticket.status }}

Priority: {{ ticket.priority }}

', 'to_role' => 'requester'], ['name' => 'Ticket response requester notice', 'event' => 'ticket.commented', 'subject' => 'New response on ticket {{ ticket.reference }}', 'html_body' => '

Hello {{ requester.name }},

A new response has been added to {{ ticket.reference }}.

Subject: {{ ticket.subject }}

', 'to_role' => 'requester'], ['name' => 'Ticket closed requester notice', 'event' => 'ticket.closed', 'subject' => 'Ticket {{ ticket.reference }} has been closed', 'html_body' => '

Hello {{ requester.name }},

Your ticket {{ ticket.reference }} has been closed.

Thank you for using the support desk.

', 'to_role' => 'requester'], ] as $template) { WorkflowTemplate::query()->updateOrCreate( ['name' => $template['name'], 'event' => $template['event']], $template + ['text_body' => null, 'cc' => null, 'bcc' => null, 'is_active' => true], ); } } /** * Seed RedmineUP-inspired professional helpdesk defaults. */ private function seedRedmineInspiredDefaults(): void { $medium = Priority::query()->where('slug', 'medium')->first(); $bug = Category::query()->where('slug', 'bug')->first(); SlaPolicy::query()->updateOrCreate( ['slug' => 'standard-support-sla'], [ 'priority_id' => $medium?->id, 'category_id' => null, 'name' => 'Standard Support SLA', 'slug' => 'standard-support-sla', 'first_response_minutes' => 240, 'resolution_minutes' => 2880, 'business_hours_only' => false, 'is_default' => true, 'is_active' => true, ], ); CannedResponse::query()->updateOrCreate( ['slug' => 'professional-acknowledgement'], [ 'category_id' => null, 'team_id' => null, 'name' => 'Professional acknowledgement', 'slug' => 'professional-acknowledgement', 'visibility' => 'agents', 'subject' => null, 'body' => '

Hello {{ requester.name }},

Thank you for the update on {{ ticket.reference }}. I am reviewing this now and will come back with the next action shortly.

Regards,
{{ agent.name }}

', 'is_active' => true, 'sort_order' => 10, ], ); ChecklistTemplate::query()->updateOrCreate( ['slug' => 'bug-triage-checklist'], [ 'category_id' => $bug?->id, 'project_id' => null, 'name' => 'Bug triage checklist', 'slug' => 'bug-triage-checklist', 'items' => ['Confirm reproduction steps', 'Check recent deployment/build', 'Identify affected account', 'Record fix or workaround'], 'is_active' => true, ], ); foreach ([ ['name' => 'Escalated', 'slug' => 'escalated', 'color' => 'red'], ['name' => 'Waiting on customer', 'slug' => 'waiting-on-customer', 'color' => 'amber'], ] as $tag) { Tag::query()->updateOrCreate( ['slug' => $tag['slug']], $tag + [], ); } if (Schema::hasColumn('helpdesk_tags', 'is_default')) { Tag::query() ->where('is_default', true) ->update(['is_default' => false]); } Product::query()->updateOrCreate( ['slug' => 'thredary'], [ 'name' => 'Thredary', 'slug' => 'thredary', 'type' => 'service', 'version' => null, 'release_channel' => 'core', 'description' => 'Default service record for Thredary platform support tickets.', 'is_active' => true, ], ); } }