lesli 5.0.23 → 5.0.24

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/lesli/abouts_controller.rb +1 -1
  3. data/app/controllers/lesli/{items → item}/activities_controller.rb +1 -1
  4. data/app/controllers/lesli/item/discussions_controller.rb +126 -0
  5. data/app/controllers/lesli/item/tasks_controller.rb +126 -0
  6. data/app/models/concerns/lesli/item/activities.rb +106 -0
  7. data/app/models/concerns/lesli/item/discussions.rb +92 -0
  8. data/app/models/concerns/lesli/item/tasks.rb +95 -0
  9. data/app/models/lesli/account.rb +1 -0
  10. data/app/models/lesli/{items → item}/activity.rb +5 -13
  11. data/app/models/lesli/item/discussion.rb +10 -0
  12. data/{lib/tasks/lesli/docs.rake → app/models/lesli/item/task.rb} +9 -14
  13. data/app/views/lesli/partials/_application-lesli-header.html.erb +12 -0
  14. data/config/initializers/lesli_migration_helpers.rb +2 -2
  15. data/db/migrate/v1/0000000210_create_lesli_users.rb +1 -1
  16. data/lib/generators/lesli/install/install_generator.rb +1 -1
  17. data/lib/lesli/engine.rb +1 -1
  18. data/lib/lesli/router.rb +42 -43
  19. data/lib/lesli/version.rb +2 -2
  20. data/lib/migrate/common.rb +1 -1
  21. data/lib/migrate/items/activity_structure.rb +11 -5
  22. data/lib/migrate/items/discussion_structure.rb +9 -3
  23. data/lib/migrate/items/{action_structure.rb → task_structure.rb} +12 -6
  24. data/lib/migrate/shared/catalog_structure.rb +16 -0
  25. data/lib/tasks/lesli/db.rake +9 -0
  26. data/readme.md +1 -1
  27. metadata +15 -30
  28. data/app/controllers/lesli/items/actions_controller.rb +0 -122
  29. data/app/controllers/lesli/items/discussions_controller.rb +0 -93
  30. data/app/models/lesli/items/action.rb +0 -15
  31. data/app/models/lesli/items/discussion.rb +0 -15
  32. data/db/structure/00000000_locations.json +0 -32
  33. data/db/structure/00000020_catalogs.json +0 -0
  34. data/db/structure/00000201_workflows.json +0 -17
  35. data/db/structure/00000202_workflow_statuses.json +0 -24
  36. data/db/structure/00000203_workflow_associations.json +0 -14
  37. data/db/structure/00000204_workflow_actions.json +0 -39
  38. data/db/structure/00000205_workflow_checks.json +0 -27
  39. data/db/structure/00000300_custom_fields.json +0 -8
  40. data/db/structure/00000301_custom_fields.json +0 -38
  41. data/db/structure/00000401_custom_validations.json +0 -14
  42. data/db/structure/00000402_custom_validation_rules.json +0 -23
  43. data/db/structure/00000403_custom_validation_fields.json +0 -14
  44. data/lib/tasks/lesli/git.rake +0 -70
  45. data/lib/tasks/lesli/github.rake +0 -89
  46. data/lib/test/config.rb +0 -111
  47. data/lib/test/helpers/response_integration_helper.rb +0 -46
  48. data/lib/test/lesli.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd0c72054c9e183cd20bb799ce466d3e7726a169a27d25c74f629dd18456a756
4
- data.tar.gz: 4a06f9ec53949acea25626f80a57c2f7a200949847c1588263ed501b4e8958e3
3
+ metadata.gz: a56fbd90769c845789e9fc2097da330344938d31db26be4da238adae6e18ded8
4
+ data.tar.gz: 840585ccd69d395bde16bbd9b41e4b33e4cd41343e09f35b12fe7f5452e6b513
5
5
  SHA512:
6
- metadata.gz: 4cb0333bce69463e0b9d5a5087fb132176b8e8824f1d743788325cf42d4b3accb076fb9e6b47336a7601569b7914a052bf19cc98350e28eb9e473e1b93b286f6
7
- data.tar.gz: 52b5932c2c4467fe81cbf7c882be73127f8d8ad55df48f837b79b38bbbee00d6a64cc5a52c4be72d6551434264b8fe3197eb29bddb60775e5b024f61e1fb09c2
6
+ metadata.gz: 20d6570450c48ca8c79132403144d12c7a718dd6b91c03e346899badeacad0d2627543f0f5b5dd98274edbb600b6073c2147ac27ef09a694acd0a3d257466a19
7
+ data.tar.gz: 6ab41da8a99d0b615071dedce1a4f020be93d4ffe85de5ae48a6fd5538182cec1194ff38b2daa79a16d901441463f5e376e67c403baf4a1e09509e1a3539c09c
@@ -50,7 +50,7 @@ module Lesli
50
50
  respond_to do |format|
51
51
  format.html {}
52
52
  format.json do
53
- lesli_engines = LesliSystem.engines.map do |engine, engine_info|
53
+ lesli_engines = ::LesliSystem.engines.map do |engine, engine_info|
54
54
  {
55
55
  :name => engine_info[:name],
56
56
  :code => engine_info[:code],
@@ -31,7 +31,7 @@ Building a better future, one line of code at a time.
31
31
  =end
32
32
 
33
33
  module Lesli
34
- module Items
34
+ module Item
35
35
  class ActivitiesController < ApplicationLesliController
36
36
  end
37
37
  end
@@ -0,0 +1,126 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ class DiscussionsController < ApplicationLesliController
36
+ before_action :set_discussion, only: %i[show update]
37
+ before_action :set_discussable, only: %i[index create]
38
+
39
+ def index
40
+ @discussions = discussion_class
41
+ .where(account: current_user.account)
42
+ .order(created_at: :desc)
43
+ respond_with_lesli(json: @discussions)
44
+ end
45
+
46
+ def show
47
+ end
48
+
49
+ def create
50
+ discussion = discussion_class.new(discussion_params)
51
+
52
+ discussion.user = current_user
53
+ discussion.account = current_user.account
54
+ discussion.discussable = @discussable if @discussable
55
+
56
+ if discussion.save
57
+ respond_with_lesli(:turbo => [
58
+ stream_notification_success("Discussion created"),
59
+ turbo_stream.prepend("#{scope_key}-lesli-items-discussions-list") do
60
+ LesliView::Item::Discussion.new(discussion).render_in(view_context)
61
+ end
62
+ ])
63
+ else
64
+ respond_with_lesli(
65
+ :turbo => stream_notification_danger(discussion.errors.full_messages)
66
+ )
67
+ end
68
+ end
69
+
70
+ def update
71
+ @discussion.done = true
72
+ @discussion.save
73
+ respond_with_lesli(:turbo => [
74
+ stream_notification_success("Discussion updated #{@discussable}"),
75
+ turbo_stream.replace(helpers.dom_id(@discussion, scope_key)) do
76
+ LesliView::Item::Discussion.new(@discussion, scope_key).render_in(view_context)
77
+ end
78
+ ])
79
+ end
80
+
81
+ private
82
+
83
+ # return a key to identify the engine where the tasks are running
84
+ def scope_key = ActiveSupport::Inflector.underscore(discussion_class.name).tr("/", "_")
85
+
86
+ # return the discussion class including the engine where the tasks are running
87
+ def discussion_class = self.class.module_parent.const_get("Discussion")
88
+
89
+ # validate we invoke only models that implements Lesli::Item::Discussions concern
90
+ def validate_discussable discussable
91
+
92
+ # 1. Attempt to resolve the class safely
93
+ klass = discussable.safe_constantize
94
+
95
+ # 2. VALIDATION: Check if the class is allowed to be discussable
96
+ # We check if the class exists AND if it includes your specific discussable trait
97
+ unless klass && klass.respond_to?(:is_lesli_taskable?) && klass.is_lesli_commentable?
98
+ render json: { error: "Unauthorized discussable type" }, status: :forbidden and return
99
+ end
100
+
101
+ klass
102
+ end
103
+
104
+ def set_discussion
105
+ @discussion = discussion_class.where(account: current_user.account).find(params[:id])
106
+ end
107
+
108
+ # Permite filtrar/crear para un actionable específico:
109
+ # params: actionable_type=LesliSupport::Ticket&actionable_id=123
110
+ def set_discussable
111
+ type = params[:discussable_type].presence
112
+ id = params[:discussable_id].presence
113
+ return if type.blank? || id.blank?
114
+
115
+ discussable = validate_discussable(type)
116
+
117
+ # 3. Execution: Now it is safe to query
118
+ @discussable = discussable.where(account: current_user.account).find_by(id: id)
119
+ end
120
+
121
+ def discussion_params
122
+ params.require(scope_key.to_sym).permit(:message)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,126 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ class TasksController < ApplicationLesliController
36
+ before_action :set_task, only: %i[show update]
37
+ before_action :set_taskable, only: %i[index create]
38
+
39
+ def index
40
+ @tasks = task_class
41
+ .where(account: current_user.account)
42
+ .order(created_at: :desc)
43
+ respond_with_lesli(json: @tasks)
44
+ end
45
+
46
+ def show
47
+ end
48
+
49
+ def create
50
+ task = task_class.new(task_params)
51
+
52
+ task.user = current_user
53
+ task.account = current_user.account
54
+ task.taskable = @taskable if @taskable
55
+
56
+ if task.save
57
+ respond_with_lesli(:turbo => [
58
+ stream_notification_success("Task created"),
59
+ turbo_stream.prepend("#{scope_key}-lesli-items-tasks-list") do
60
+ LesliView::Item::Task.new(task, scope_key).render_in(view_context)
61
+ end
62
+ ])
63
+ else
64
+ respond_with_lesli(
65
+ :turbo => stream_notification_danger(task.errors.full_messages)
66
+ )
67
+ end
68
+ end
69
+
70
+ def update
71
+ @task.done = true
72
+ @task.save
73
+ respond_with_lesli(:turbo => [
74
+ stream_notification_success("Task updated #{@taskable}"),
75
+ turbo_stream.replace(helpers.dom_id(@task, scope_key)) do
76
+ LesliView::Item::Task.new(@task, scope_key).render_in(view_context)
77
+ end
78
+ ])
79
+ end
80
+
81
+ private
82
+
83
+ # return a key to identify the engine where the tasks are running
84
+ def scope_key = ActiveSupport::Inflector.underscore(task_class.name).tr("/", "_")
85
+
86
+ # return the task class including the engine where the tasks are running
87
+ def task_class = self.class.module_parent.const_get("Task")
88
+
89
+ # validate we invoke only models that implements Lesli::Item::Tasks concern
90
+ def validate_taskable taskable
91
+
92
+ # 1. Attempt to resolve the class safely
93
+ klass = taskable.safe_constantize
94
+
95
+ # 2. VALIDATION: Check if the class is allowed to be taskable
96
+ # We check if the class exists AND if it includes your specific taskable trait
97
+ unless klass && klass.respond_to?(:is_lesli_taskable?) && klass.is_lesli_taskable?
98
+ render json: { error: "Unauthorized taskable type" }, status: :forbidden and return
99
+ end
100
+
101
+ klass
102
+ end
103
+
104
+ def set_task
105
+ @task = task_class.where(account: current_user.account).find(params[:id])
106
+ end
107
+
108
+ # Permite filtrar/crear para un actionable específico:
109
+ # params: actionable_type=LesliSupport::Ticket&actionable_id=123
110
+ def set_taskable
111
+ type = params[:taskable_type].presence
112
+ id = params[:taskable_id].presence
113
+ return if type.blank? || id.blank?
114
+
115
+ taskable = validate_taskable(type)
116
+
117
+ # 3. Execution: Now it is safe to query
118
+ @taskable = taskable.where(account: current_user.account).find_by(id: id)
119
+ end
120
+
121
+ def task_params
122
+ params.require(scope_key.to_sym).permit(:title)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,106 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ module Activities
36
+ extend ActiveSupport::Concern
37
+
38
+ included do
39
+ class_attribute :lesli_activities_class, instance_accessor: false
40
+ lesli_activities_setup
41
+ end
42
+
43
+ class_methods do
44
+
45
+ # Automatically sets the associations to the
46
+ # engine model that is implementing the task items
47
+ def lesli_activities_setup(use: nil, as: :subject, association_name: :activities)
48
+ klass = if use
49
+ use.to_s.constantize
50
+ else
51
+ "#{name.deconstantize}::Item::Activity".constantize
52
+ end
53
+
54
+ self.lesli_activities_class = klass
55
+
56
+ # ✅ Auto-fix table name (works even when engine defines table_name_prefix)
57
+ expected_table = lesli_expected_activity_table_name_for(klass)
58
+
59
+ if klass.table_name != expected_table
60
+ klass.table_name = expected_table
61
+ end
62
+
63
+ # Set associations
64
+ # Example:
65
+ # class LesliSupport::Ticket
66
+ # has_many :activities, class_name: "LesliSupport::Items::Activity"
67
+ # end
68
+ has_many(association_name,
69
+ -> { where(deleted_at: nil).order(created_at: :desc) },
70
+ as: as,
71
+ class_name: klass.name,
72
+ dependent: :destroy
73
+ )
74
+
75
+ # rescue NameError
76
+ # raise NameError,
77
+ # "Task class not found for #{name}. Expected #{name.deconstantize}::Activity or pass `use:`"
78
+ end
79
+
80
+ private
81
+
82
+ # Build: "lesli_support_item_activities" from "LesliSupport::Item::Activity"
83
+ #
84
+ # We DO NOT rely on ActiveRecord's table_name_prefix, because that’s what breaks your case.
85
+ def lesli_expected_activity_table_name_for(klass)
86
+ parts = klass.name.split("::").map(&:underscore) # ["lesli_support", "item", "activity"]
87
+ "#{parts.join('_').pluralize}" # "lesli_support_item_activities"
88
+ end
89
+ end
90
+
91
+ def after_save_activities
92
+ L2.warn "You need to define your activity methods in your model"
93
+ end
94
+
95
+ def activities_create **resource
96
+ self.activities.create(
97
+ subject_type: self.class.name,
98
+ subject_id: self.id,
99
+ user_id:self.user_id,
100
+ account_id:self.account_id,
101
+ **resource
102
+ )
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,92 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ module Discussions
36
+ extend ActiveSupport::Concern
37
+
38
+ included do
39
+ class_attribute :lesli_discussions_class, instance_accessor: false
40
+ lesli_discussions_setup
41
+ end
42
+
43
+ class_methods do
44
+
45
+ # This acts as our allowlist flag
46
+ def is_lesli_commentable?
47
+ true
48
+ end
49
+
50
+ # Automatically sets the associations to the
51
+ # engine model that is implementing the task items
52
+ def lesli_discussions_setup(use: nil, as: :discussable, association_name: :discussions)
53
+ klass = if use
54
+ use.to_s.constantize
55
+ else
56
+ "#{name.deconstantize}::Item::Discussion".constantize
57
+ end
58
+
59
+ self.lesli_discussions_class = klass
60
+
61
+ # ✅ Auto-fix table name (works even when engine defines table_name_prefix)
62
+ expected_table = lesli_expected_discussions_table_name_for(klass)
63
+
64
+ if klass.table_name != expected_table
65
+ klass.table_name = expected_table
66
+ end
67
+
68
+ # Set associations
69
+ # Example:
70
+ # class LesliSupport::Ticket
71
+ # has_many :lesli_support_tasks
72
+ # end
73
+ has_many(association_name,
74
+ -> { where(deleted_at: nil).order(created_at: :desc) },
75
+ as: as,
76
+ class_name: klass.name,
77
+ dependent: :destroy)
78
+ end
79
+
80
+ private
81
+
82
+ # Build: "lesli_support_item_activities" from "LesliSupport::Item::Activity"
83
+ #
84
+ # We DO NOT rely on ActiveRecord's table_name_prefix, because that’s what breaks your case.
85
+ def lesli_expected_discussions_table_name_for(klass)
86
+ parts = klass.name.split("::").map(&:underscore) # ["lesli_support", "item", "discussion"]
87
+ "#{parts.join('_').pluralize}" # "lesli_support_item_discussions"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,95 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ module Tasks
36
+ extend ActiveSupport::Concern
37
+
38
+ included do
39
+ class_attribute :lesli_tasks_class, instance_accessor: false
40
+ lesli_tasks_setup
41
+ end
42
+
43
+ class_methods do
44
+
45
+ # This acts as our allowlist flag
46
+ def is_lesli_taskable?
47
+ true
48
+ end
49
+
50
+ # Automatically sets the associations to the
51
+ # engine model that is implementing the task items
52
+ def lesli_tasks_setup(use: nil, as: :taskable, association_name: :tasks)
53
+ klass = if use
54
+ use.to_s.constantize
55
+ else
56
+ "#{name.deconstantize}::Item::Task".constantize
57
+ end
58
+
59
+ self.lesli_tasks_class = klass
60
+
61
+ # ✅ Auto-fix table name (works even when engine defines table_name_prefix)
62
+ expected_table = lesli_expected_task_table_name_for(klass)
63
+
64
+ if klass.table_name != expected_table
65
+ klass.table_name = expected_table
66
+ end
67
+
68
+ # Set associations
69
+ # Example:
70
+ # class LesliSupport::Ticket
71
+ # has_many :lesli_support_tasks
72
+ # end
73
+ has_many(association_name,
74
+ -> { where(deleted_at: nil).order(created_at: :desc) },
75
+ as: as,
76
+ class_name: klass.name,
77
+ dependent: :destroy)
78
+ rescue NameError
79
+ raise NameError,
80
+ "Task class not found for #{name}. Expected #{name.deconstantize}::Task or pass `use:`"
81
+ end
82
+
83
+ private
84
+
85
+ # Build: "lesli_support_item_activities" from "LesliSupport::Item::Activity"
86
+ #
87
+ # We DO NOT rely on ActiveRecord's table_name_prefix, because that’s what breaks your case.
88
+ def lesli_expected_task_table_name_for(klass)
89
+ parts = klass.name.split("::").map(&:underscore) # ["lesli_support", "item", "task"]
90
+ "#{parts.join('_').pluralize}" # "lesli_support_item_tasks"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -64,6 +64,7 @@ module Lesli
64
64
  has_one :dashboard, class_name: "LesliDashboard::Account"
65
65
 
66
66
 
67
+ validates :status, presence: true
67
68
 
68
69
  # account statuses
69
70
  enum :status, {
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lesli
4
4
 
5
- Copyright (c) 2025, Lesli Technologies, S. A.
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
6
 
7
7
  This program is free software: you can redistribute it and/or modify
8
8
  it under the terms of the GNU General Public License as published by
@@ -31,20 +31,12 @@ Building a better future, one line of code at a time.
31
31
  =end
32
32
 
33
33
  module Lesli
34
- module Items
34
+ module Item
35
35
  class Activity < ApplicationRecord
36
36
  self.abstract_class = true
37
-
38
- # activity is for user
39
- # system is for jobs
40
- enum :activity_type, {
41
- activity: "activity",
42
- system: "system"
43
- }
44
-
45
- # if needed should be defined
46
- # by the user at resource level
47
- # enum activity_code: { }
37
+ belongs_to :user, class_name: "Lesli::User"
38
+ belongs_to :account, class_name: "Lesli::Account"
39
+ belongs_to :subject, polymorphic: true
48
40
  end
49
41
  end
50
42
  end
@@ -0,0 +1,10 @@
1
+ module Lesli
2
+ module Item
3
+ class Discussion < ApplicationRecord
4
+ self.abstract_class = true
5
+ belongs_to :user, class_name: "Lesli::User"
6
+ belongs_to :account, class_name: "Lesli::Account"
7
+ belongs_to :discussable, polymorphic: true
8
+ end
9
+ end
10
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lesli
4
4
 
5
- Copyright (c) 2023, Lesli Technologies, S. A.
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
6
 
7
7
  This program is free software: you can redistribute it and/or modify
8
8
  it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@ along with this program. If not, see http://www.gnu.org/licenses/.
19
19
 
20
20
  Lesli · Ruby on Rails SaaS Development Framework.
21
21
 
22
- Made with ♥ by https://www.lesli.tech
22
+ Made with ♥ by LesliTech
23
23
  Building a better future, one line of code at a time.
24
24
 
25
25
  @contact hello@lesli.tech
@@ -30,18 +30,13 @@ Building a better future, one line of code at a time.
30
30
  // ·
31
31
  =end
32
32
 
33
- # ·
34
- namespace :lesli do
35
- namespace :docs do
36
-
37
- desc "Drop, create, migrate, seed & prepare the Lesli database (development only)"
38
- task :build => :environment do |task, args|
39
- build()
33
+ module Lesli
34
+ module Item
35
+ class Task < ApplicationRecord
36
+ self.abstract_class = true
37
+ belongs_to :user, class_name: "Lesli::User"
38
+ belongs_to :account, class_name: "Lesli::Account"
39
+ belongs_to :taskable, polymorphic: true
40
40
  end
41
41
  end
42
-
43
- # Drop the Lesli database (development only)
44
- def build
45
-
46
- end
47
42
  end