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() ->whereNull('company_id') ->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( ['company_id' => null, 'slug' => Str::slug($row['name'])], $row + ['company_id' => null, 'slug' => Str::slug($row['name'])], ); } } /** * Seed the default support team and a default project. */ private function seedTeamsAndProjects(): void { Team::query() ->whereNull('company_id') ->where('is_default', true) ->update(['is_default' => false]); Project::query() ->whereNull('company_id') ->where('is_default', true) ->update(['is_default' => false]); $team = Team::query()->updateOrCreate( ['company_id' => null, 'slug' => 'support'], [ 'company_id' => null, 'name' => 'Support', 'slug' => 'support', 'color' => 'blue', 'description' => 'Default support team for triage, ownership and ticket routing.', 'is_default' => true, ], ); Project::query()->updateOrCreate( ['company_id' => null, 'slug' => 'support-desk'], [ 'company_id' => null, '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( ['company_id' => null, 'slug' => 'standard-support-sla'], [ 'company_id' => null, '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( ['company_id' => null, 'slug' => 'professional-acknowledgement'], [ 'company_id' => null, '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 }}