escalated 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +302 -0
  4. data/app/controllers/escalated/admin/bulk_actions_controller.rb +42 -0
  5. data/app/controllers/escalated/admin/canned_responses_controller.rb +73 -0
  6. data/app/controllers/escalated/admin/departments_controller.rb +135 -0
  7. data/app/controllers/escalated/admin/escalation_rules_controller.rb +121 -0
  8. data/app/controllers/escalated/admin/macros_controller.rb +73 -0
  9. data/app/controllers/escalated/admin/reports_controller.rb +152 -0
  10. data/app/controllers/escalated/admin/settings_controller.rb +111 -0
  11. data/app/controllers/escalated/admin/sla_policies_controller.rb +109 -0
  12. data/app/controllers/escalated/admin/tags_controller.rb +67 -0
  13. data/app/controllers/escalated/admin/tickets_controller.rb +299 -0
  14. data/app/controllers/escalated/agent/bulk_actions_controller.rb +42 -0
  15. data/app/controllers/escalated/agent/dashboard_controller.rb +94 -0
  16. data/app/controllers/escalated/agent/tickets_controller.rb +330 -0
  17. data/app/controllers/escalated/application_controller.rb +110 -0
  18. data/app/controllers/escalated/customer/satisfaction_ratings_controller.rb +44 -0
  19. data/app/controllers/escalated/customer/tickets_controller.rb +169 -0
  20. data/app/controllers/escalated/guest/tickets_controller.rb +231 -0
  21. data/app/controllers/escalated/inbound_controller.rb +79 -0
  22. data/app/jobs/escalated/check_sla_job.rb +36 -0
  23. data/app/jobs/escalated/close_resolved_job.rb +51 -0
  24. data/app/jobs/escalated/evaluate_escalations_job.rb +24 -0
  25. data/app/jobs/escalated/poll_imap_job.rb +74 -0
  26. data/app/jobs/escalated/purge_activities_job.rb +24 -0
  27. data/app/mailers/escalated/application_mailer.rb +6 -0
  28. data/app/mailers/escalated/ticket_mailer.rb +93 -0
  29. data/app/models/escalated/application_record.rb +5 -0
  30. data/app/models/escalated/attachment.rb +46 -0
  31. data/app/models/escalated/canned_response.rb +45 -0
  32. data/app/models/escalated/department.rb +43 -0
  33. data/app/models/escalated/escalated_setting.rb +43 -0
  34. data/app/models/escalated/escalation_rule.rb +96 -0
  35. data/app/models/escalated/inbound_email.rb +60 -0
  36. data/app/models/escalated/macro.rb +18 -0
  37. data/app/models/escalated/reply.rb +42 -0
  38. data/app/models/escalated/satisfaction_rating.rb +21 -0
  39. data/app/models/escalated/sla_policy.rb +54 -0
  40. data/app/models/escalated/tag.rb +28 -0
  41. data/app/models/escalated/ticket.rb +166 -0
  42. data/app/models/escalated/ticket_activity.rb +60 -0
  43. data/app/policies/escalated/canned_response_policy.rb +40 -0
  44. data/app/policies/escalated/department_policy.rb +36 -0
  45. data/app/policies/escalated/escalation_rule_policy.rb +36 -0
  46. data/app/policies/escalated/sla_policy_policy.rb +36 -0
  47. data/app/policies/escalated/tag_policy.rb +36 -0
  48. data/app/policies/escalated/ticket_policy.rb +111 -0
  49. data/config/routes.rb +81 -0
  50. data/db/migrate/001_create_escalated_departments.rb +18 -0
  51. data/db/migrate/002_create_escalated_sla_policies.rb +23 -0
  52. data/db/migrate/003_create_escalated_tags.rb +15 -0
  53. data/db/migrate/004_create_escalated_tickets.rb +48 -0
  54. data/db/migrate/005_create_escalated_replies.rb +21 -0
  55. data/db/migrate/006_create_escalated_attachments.rb +17 -0
  56. data/db/migrate/007_create_escalated_ticket_tags.rb +13 -0
  57. data/db/migrate/008_create_escalated_support_tables.rb +49 -0
  58. data/db/migrate/009_create_escalated_ticket_activities.rb +20 -0
  59. data/db/migrate/010_create_escalated_settings.rb +29 -0
  60. data/db/migrate/011_add_guest_fields_to_escalated_tickets.rb +28 -0
  61. data/db/migrate/012_create_escalated_inbound_emails.rb +30 -0
  62. data/db/migrate/013_create_escalated_macros.rb +18 -0
  63. data/db/migrate/014_create_escalated_ticket_followers.rb +18 -0
  64. data/db/migrate/015_create_escalated_satisfaction_ratings.rb +21 -0
  65. data/db/migrate/016_add_is_pinned_to_escalated_replies.rb +6 -0
  66. data/lib/escalated/configuration.rb +111 -0
  67. data/lib/escalated/drivers/cloud_driver.rb +134 -0
  68. data/lib/escalated/drivers/hosted_api_client.rb +166 -0
  69. data/lib/escalated/drivers/local_driver.rb +341 -0
  70. data/lib/escalated/drivers/synced_driver.rb +124 -0
  71. data/lib/escalated/engine.rb +45 -0
  72. data/lib/escalated/mail/adapters/base_adapter.rb +60 -0
  73. data/lib/escalated/mail/adapters/imap_adapter.rb +209 -0
  74. data/lib/escalated/mail/adapters/mailgun_adapter.rb +93 -0
  75. data/lib/escalated/mail/adapters/postmark_adapter.rb +94 -0
  76. data/lib/escalated/mail/adapters/ses_adapter.rb +179 -0
  77. data/lib/escalated/mail/inbound_message.rb +78 -0
  78. data/lib/escalated/manager.rb +33 -0
  79. data/lib/escalated/services/assignment_service.rb +85 -0
  80. data/lib/escalated/services/attachment_service.rb +110 -0
  81. data/lib/escalated/services/escalation_service.rb +159 -0
  82. data/lib/escalated/services/inbound_email_service.rb +255 -0
  83. data/lib/escalated/services/macro_service.rb +49 -0
  84. data/lib/escalated/services/notification_service.rb +157 -0
  85. data/lib/escalated/services/sla_service.rb +203 -0
  86. data/lib/escalated/services/ticket_service.rb +113 -0
  87. data/lib/escalated.rb +25 -0
  88. data/lib/generators/escalated/install_generator.rb +75 -0
  89. data/lib/generators/escalated/templates/initializer.rb +89 -0
  90. metadata +227 -0
@@ -0,0 +1,40 @@
1
+ module Escalated
2
+ class CannedResponsePolicy
3
+ attr_reader :user, :canned_response
4
+
5
+ def initialize(user, canned_response)
6
+ @user = user
7
+ @canned_response = canned_response
8
+ end
9
+
10
+ def index?
11
+ agent? || admin?
12
+ end
13
+
14
+ def create?
15
+ agent? || admin?
16
+ end
17
+
18
+ def update?
19
+ owner? || admin?
20
+ end
21
+
22
+ def destroy?
23
+ owner? || admin?
24
+ end
25
+
26
+ private
27
+
28
+ def owner?
29
+ canned_response.created_by == user.id
30
+ end
31
+
32
+ def agent?
33
+ user.respond_to?(:escalated_agent?) && user.escalated_agent?
34
+ end
35
+
36
+ def admin?
37
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ module Escalated
2
+ class DepartmentPolicy
3
+ attr_reader :user, :department
4
+
5
+ def initialize(user, department)
6
+ @user = user
7
+ @department = department
8
+ end
9
+
10
+ def index?
11
+ admin?
12
+ end
13
+
14
+ def show?
15
+ admin?
16
+ end
17
+
18
+ def create?
19
+ admin?
20
+ end
21
+
22
+ def update?
23
+ admin?
24
+ end
25
+
26
+ def destroy?
27
+ admin?
28
+ end
29
+
30
+ private
31
+
32
+ def admin?
33
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Escalated
2
+ class EscalationRulePolicy
3
+ attr_reader :user, :escalation_rule
4
+
5
+ def initialize(user, escalation_rule)
6
+ @user = user
7
+ @escalation_rule = escalation_rule
8
+ end
9
+
10
+ def index?
11
+ admin?
12
+ end
13
+
14
+ def show?
15
+ admin?
16
+ end
17
+
18
+ def create?
19
+ admin?
20
+ end
21
+
22
+ def update?
23
+ admin?
24
+ end
25
+
26
+ def destroy?
27
+ admin?
28
+ end
29
+
30
+ private
31
+
32
+ def admin?
33
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Escalated
2
+ class SlaPolicyPolicy
3
+ attr_reader :user, :sla_policy
4
+
5
+ def initialize(user, sla_policy)
6
+ @user = user
7
+ @sla_policy = sla_policy
8
+ end
9
+
10
+ def index?
11
+ admin?
12
+ end
13
+
14
+ def show?
15
+ admin?
16
+ end
17
+
18
+ def create?
19
+ admin?
20
+ end
21
+
22
+ def update?
23
+ admin?
24
+ end
25
+
26
+ def destroy?
27
+ admin?
28
+ end
29
+
30
+ private
31
+
32
+ def admin?
33
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ module Escalated
2
+ class TagPolicy
3
+ attr_reader :user, :tag
4
+
5
+ def initialize(user, tag)
6
+ @user = user
7
+ @tag = tag
8
+ end
9
+
10
+ def index?
11
+ agent? || admin?
12
+ end
13
+
14
+ def create?
15
+ admin?
16
+ end
17
+
18
+ def update?
19
+ admin?
20
+ end
21
+
22
+ def destroy?
23
+ admin?
24
+ end
25
+
26
+ private
27
+
28
+ def agent?
29
+ user.respond_to?(:escalated_agent?) && user.escalated_agent?
30
+ end
31
+
32
+ def admin?
33
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,111 @@
1
+ module Escalated
2
+ class TicketPolicy
3
+ attr_reader :user, :ticket
4
+
5
+ def initialize(user, ticket)
6
+ @user = user
7
+ @ticket = ticket
8
+ end
9
+
10
+ def index?
11
+ true
12
+ end
13
+
14
+ def show?
15
+ owner? || agent? || admin?
16
+ end
17
+
18
+ def create?
19
+ true
20
+ end
21
+
22
+ def update?
23
+ agent? || admin?
24
+ end
25
+
26
+ def destroy?
27
+ admin?
28
+ end
29
+
30
+ def reply?
31
+ owner? || agent? || admin?
32
+ end
33
+
34
+ def note?
35
+ agent? || admin?
36
+ end
37
+
38
+ def assign?
39
+ agent? || admin?
40
+ end
41
+
42
+ def status?
43
+ agent? || admin?
44
+ end
45
+
46
+ def priority?
47
+ agent? || admin?
48
+ end
49
+
50
+ def tags?
51
+ agent? || admin?
52
+ end
53
+
54
+ def department?
55
+ agent? || admin?
56
+ end
57
+
58
+ def close?
59
+ if Escalated.configuration.allow_customer_close
60
+ owner? || agent? || admin?
61
+ else
62
+ agent? || admin?
63
+ end
64
+ end
65
+
66
+ def reopen?
67
+ owner? || agent? || admin?
68
+ end
69
+
70
+ class Scope
71
+ attr_reader :user, :scope
72
+
73
+ def initialize(user, scope)
74
+ @user = user
75
+ @scope = scope
76
+ end
77
+
78
+ def resolve
79
+ if admin? || agent?
80
+ scope.all
81
+ else
82
+ scope.where(requester: user)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def admin?
89
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
90
+ end
91
+
92
+ def agent?
93
+ user.respond_to?(:escalated_agent?) && user.escalated_agent?
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def owner?
100
+ ticket.requester == user
101
+ end
102
+
103
+ def agent?
104
+ user.respond_to?(:escalated_agent?) && user.escalated_agent?
105
+ end
106
+
107
+ def admin?
108
+ user.respond_to?(:escalated_admin?) && user.escalated_admin?
109
+ end
110
+ end
111
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,81 @@
1
+ Escalated::Engine.routes.draw do
2
+ # Customer-facing routes
3
+ namespace :customer do
4
+ resources :tickets, only: [:index, :create, :show] do
5
+ member do
6
+ post :reply
7
+ post :close
8
+ post :reopen
9
+ post :rate, to: "satisfaction_ratings#create"
10
+ end
11
+ collection do
12
+ get :new, action: :create, as: :new
13
+ end
14
+ end
15
+ end
16
+
17
+ # Agent routes
18
+ namespace :agent do
19
+ get "/", to: "dashboard#index", as: :dashboard
20
+ post "tickets/bulk", to: "bulk_actions#create", as: :tickets_bulk
21
+ resources :tickets, only: [:index, :show, :update] do
22
+ member do
23
+ post :reply
24
+ post :note
25
+ post :assign
26
+ post :status
27
+ post :priority
28
+ post :tags
29
+ post :department
30
+ post :macro, action: :apply_macro
31
+ post :follow
32
+ post :presence
33
+ post "replies/:reply_id/pin", action: :pin, as: :reply_pin
34
+ end
35
+ end
36
+ end
37
+
38
+ # Admin routes
39
+ namespace :admin do
40
+ post "tickets/bulk", to: "bulk_actions#create", as: :tickets_bulk
41
+ resources :tickets, only: [:index, :show] do
42
+ member do
43
+ post :reply
44
+ post :note
45
+ post :assign
46
+ post :status
47
+ post :priority
48
+ post :tags
49
+ post :department
50
+ post :macro, action: :apply_macro
51
+ post :follow
52
+ post :presence
53
+ post "replies/:reply_id/pin", action: :pin, as: :reply_pin
54
+ end
55
+ end
56
+ resources :departments
57
+ resources :sla_policies
58
+ resources :escalation_rules
59
+ resources :tags, only: [:index, :create, :update, :destroy]
60
+ resources :canned_responses, only: [:index, :create, :update, :destroy]
61
+ resources :macros, only: [:index, :create, :update, :destroy]
62
+ get :reports, to: "reports#index"
63
+ get :settings, to: "settings#index"
64
+ post :settings, to: "settings#update"
65
+ end
66
+
67
+ # Guest routes (no authentication required)
68
+ namespace :guest do
69
+ get "create", to: "tickets#create"
70
+ post "/", to: "tickets#store", as: :tickets
71
+ get ":token", to: "tickets#show", as: :ticket
72
+ post ":token/reply", to: "tickets#reply", as: :ticket_reply
73
+ post ":token/rate", to: "tickets#rate", as: :ticket_rate
74
+ end
75
+
76
+ # Inbound email webhook (no authentication -- verified by adapter)
77
+ post "inbound/:adapter", to: "inbound#webhook", as: :inbound_webhook
78
+
79
+ # Root redirect to customer tickets
80
+ root to: "customer/tickets#index"
81
+ end
@@ -0,0 +1,18 @@
1
+ class CreateEscalatedDepartments < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("departments") do |t|
4
+ t.string :name, null: false
5
+ t.string :slug, null: false
6
+ t.text :description
7
+ t.string :email
8
+ t.boolean :is_active, default: true, null: false
9
+ t.bigint :default_sla_policy_id
10
+
11
+ t.timestamps
12
+ end
13
+
14
+ add_index Escalated.table_name("departments"), :slug, unique: true
15
+ add_index Escalated.table_name("departments"), :is_active
16
+ add_index Escalated.table_name("departments"), :name, unique: true
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ class CreateEscalatedSlaPolicies < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("sla_policies") do |t|
4
+ t.string :name, null: false
5
+ t.text :description
6
+ t.json :first_response_hours, null: false
7
+ t.json :resolution_hours, null: false
8
+ t.boolean :is_active, default: true, null: false
9
+ t.boolean :is_default, default: false, null: false
10
+
11
+ t.timestamps
12
+ end
13
+
14
+ add_index Escalated.table_name("sla_policies"), :name, unique: true
15
+ add_index Escalated.table_name("sla_policies"), :is_active
16
+ add_index Escalated.table_name("sla_policies"), :is_default
17
+
18
+ add_foreign_key Escalated.table_name("departments"),
19
+ Escalated.table_name("sla_policies"),
20
+ column: :default_sla_policy_id,
21
+ on_delete: :nullify
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ class CreateEscalatedTags < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("tags") do |t|
4
+ t.string :name, null: false
5
+ t.string :slug, null: false
6
+ t.string :color
7
+ t.text :description
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index Escalated.table_name("tags"), :name, unique: true
13
+ add_index Escalated.table_name("tags"), :slug, unique: true
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ class CreateEscalatedTickets < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("tickets") do |t|
4
+ t.string :reference, null: false
5
+ t.string :subject, null: false
6
+ t.text :description, null: false
7
+ t.integer :status, default: 0, null: false
8
+ t.integer :priority, default: 1, null: false
9
+
10
+ # Polymorphic requester
11
+ t.string :requester_type, null: false
12
+ t.bigint :requester_id, null: false
13
+
14
+ # Assignee (agent user)
15
+ t.bigint :assigned_to
16
+
17
+ # Department
18
+ t.references :department, foreign_key: { to_table: Escalated.table_name("departments") }, null: true
19
+
20
+ # SLA
21
+ t.references :sla_policy, foreign_key: { to_table: Escalated.table_name("sla_policies") }, null: true
22
+ t.datetime :sla_first_response_due_at
23
+ t.datetime :sla_resolution_due_at
24
+ t.boolean :sla_breached, default: false, null: false
25
+
26
+ # Timestamps
27
+ t.datetime :first_response_at
28
+ t.datetime :resolved_at
29
+ t.datetime :closed_at
30
+
31
+ # Metadata
32
+ t.json :metadata, default: {}
33
+
34
+ t.timestamps
35
+ end
36
+
37
+ add_index Escalated.table_name("tickets"), :reference, unique: true
38
+ add_index Escalated.table_name("tickets"), :status
39
+ add_index Escalated.table_name("tickets"), :priority
40
+ add_index Escalated.table_name("tickets"), [:requester_type, :requester_id]
41
+ add_index Escalated.table_name("tickets"), :assigned_to
42
+ add_index Escalated.table_name("tickets"), :sla_breached
43
+ add_index Escalated.table_name("tickets"), :sla_first_response_due_at
44
+ add_index Escalated.table_name("tickets"), :sla_resolution_due_at
45
+ add_index Escalated.table_name("tickets"), :created_at
46
+ add_index Escalated.table_name("tickets"), :resolved_at
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ class CreateEscalatedReplies < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("replies") do |t|
4
+ t.references :ticket, null: false, foreign_key: { to_table: Escalated.table_name("tickets") }
5
+ t.text :body, null: false
6
+
7
+ # Polymorphic author
8
+ t.string :author_type
9
+ t.bigint :author_id
10
+
11
+ t.boolean :is_internal, default: false, null: false
12
+ t.boolean :is_system, default: false, null: false
13
+
14
+ t.timestamps
15
+ end
16
+
17
+ add_index Escalated.table_name("replies"), [:author_type, :author_id]
18
+ add_index Escalated.table_name("replies"), :is_internal
19
+ add_index Escalated.table_name("replies"), :created_at
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ class CreateEscalatedAttachments < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("attachments") do |t|
4
+ # Polymorphic - can attach to tickets or replies
5
+ t.string :attachable_type, null: false
6
+ t.bigint :attachable_id, null: false
7
+
8
+ t.string :filename, null: false
9
+ t.string :content_type, null: false
10
+ t.bigint :byte_size, null: false, default: 0
11
+
12
+ t.timestamps
13
+ end
14
+
15
+ add_index Escalated.table_name("attachments"), [:attachable_type, :attachable_id]
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ class CreateEscalatedTicketTags < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("ticket_tags"), id: false do |t|
4
+ t.references :ticket, null: false, foreign_key: { to_table: Escalated.table_name("tickets") }
5
+ t.references :tag, null: false, foreign_key: { to_table: Escalated.table_name("tags") }
6
+ end
7
+
8
+ add_index Escalated.table_name("ticket_tags"),
9
+ [:ticket_id, :tag_id],
10
+ unique: true,
11
+ name: "idx_escalated_ticket_tags_unique"
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ class CreateEscalatedSupportTables < ActiveRecord::Migration[7.0]
2
+ def change
3
+ # Department-Agent join table
4
+ create_table Escalated.table_name("department_agents"), id: false do |t|
5
+ t.bigint :department_id, null: false
6
+ t.bigint :agent_id, null: false
7
+ end
8
+
9
+ add_index Escalated.table_name("department_agents"),
10
+ [:department_id, :agent_id],
11
+ unique: true,
12
+ name: "idx_escalated_dept_agents_unique"
13
+ add_foreign_key Escalated.table_name("department_agents"),
14
+ Escalated.table_name("departments"),
15
+ column: :department_id
16
+
17
+ # Escalation Rules
18
+ create_table Escalated.table_name("escalation_rules") do |t|
19
+ t.string :name, null: false
20
+ t.text :description
21
+ t.json :conditions, null: false
22
+ t.json :actions, null: false
23
+ t.integer :priority, default: 0, null: false
24
+ t.boolean :is_active, default: true, null: false
25
+
26
+ t.timestamps
27
+ end
28
+
29
+ add_index Escalated.table_name("escalation_rules"), :is_active
30
+ add_index Escalated.table_name("escalation_rules"), :priority
31
+
32
+ # Canned Responses
33
+ create_table Escalated.table_name("canned_responses") do |t|
34
+ t.string :title, null: false
35
+ t.text :body, null: false
36
+ t.string :shortcode
37
+ t.string :category
38
+ t.boolean :is_shared, default: false, null: false
39
+ t.bigint :created_by, null: false
40
+
41
+ t.timestamps
42
+ end
43
+
44
+ add_index Escalated.table_name("canned_responses"), :shortcode, unique: true
45
+ add_index Escalated.table_name("canned_responses"), :is_shared
46
+ add_index Escalated.table_name("canned_responses"), :created_by
47
+ add_index Escalated.table_name("canned_responses"), :category
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ class CreateEscalatedTicketActivities < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table Escalated.table_name("ticket_activities") do |t|
4
+ t.references :ticket, null: false, foreign_key: { to_table: Escalated.table_name("tickets") }
5
+ t.string :action, null: false
6
+
7
+ # Polymorphic causer (user or system)
8
+ t.string :causer_type
9
+ t.bigint :causer_id
10
+
11
+ t.json :details, default: {}
12
+
13
+ t.timestamps
14
+ end
15
+
16
+ add_index Escalated.table_name("ticket_activities"), [:causer_type, :causer_id]
17
+ add_index Escalated.table_name("ticket_activities"), :action
18
+ add_index Escalated.table_name("ticket_activities"), :created_at
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ class CreateEscalatedSettings < ActiveRecord::Migration[7.0]
2
+ def up
3
+ table_name = "#{Escalated.configuration.table_prefix}settings"
4
+
5
+ create_table table_name do |t|
6
+ t.string :key, null: false
7
+ t.text :value
8
+ t.timestamps
9
+ end
10
+
11
+ add_index table_name, :key, unique: true
12
+
13
+ # Seed default settings
14
+ now = Time.current
15
+ execute <<-SQL.squish
16
+ INSERT INTO #{table_name} (#{connection.quote_column_name('key')}, value, created_at, updated_at)
17
+ VALUES
18
+ ('guest_tickets_enabled', '1', '#{now.utc.iso8601}', '#{now.utc.iso8601}'),
19
+ ('allow_customer_close', '1', '#{now.utc.iso8601}', '#{now.utc.iso8601}'),
20
+ ('auto_close_resolved_after_days', '7', '#{now.utc.iso8601}', '#{now.utc.iso8601}'),
21
+ ('max_attachments_per_reply', '5', '#{now.utc.iso8601}', '#{now.utc.iso8601}'),
22
+ ('max_attachment_size_kb', '10240', '#{now.utc.iso8601}', '#{now.utc.iso8601}')
23
+ SQL
24
+ end
25
+
26
+ def down
27
+ drop_table "#{Escalated.configuration.table_prefix}settings"
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ class AddGuestFieldsToEscalatedTickets < ActiveRecord::Migration[7.0]
2
+ def up
3
+ table_name = "#{Escalated.configuration.table_prefix}tickets"
4
+
5
+ # Make requester polymorphic fields nullable for guest tickets
6
+ change_column_null table_name, :requester_type, true
7
+ change_column_null table_name, :requester_id, true
8
+
9
+ # Add guest ticket fields
10
+ add_column table_name, :guest_name, :string, null: true
11
+ add_column table_name, :guest_email, :string, null: true
12
+ add_column table_name, :guest_token, :string, limit: 64, null: true
13
+
14
+ add_index table_name, :guest_token, unique: true
15
+ end
16
+
17
+ def down
18
+ table_name = "#{Escalated.configuration.table_prefix}tickets"
19
+
20
+ remove_column table_name, :guest_name
21
+ remove_column table_name, :guest_email
22
+ remove_index table_name, :guest_token
23
+ remove_column table_name, :guest_token
24
+
25
+ change_column_null table_name, :requester_type, false
26
+ change_column_null table_name, :requester_id, false
27
+ end
28
+ end