spree_cm_commissioner 2.6.2.pre.pre1 → 2.6.2.pre.pre.4
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +0 -29
- data/app/controllers/concerns/spree/admin/service_calendars_concern.rb +1 -3
- data/app/controllers/spree/admin/product_service_calendars_controller.rb +0 -1
- data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +50 -0
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +54 -0
- data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +36 -0
- data/app/controllers/spree/api/v2/tenant/shows_controller.rb +39 -0
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +45 -0
- data/app/helpers/spree_cm_commissioner/admin/homepage_segment_helper.rb +2 -0
- data/app/interactors/spree_cm_commissioner/create_vendor.rb +0 -2
- data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +1 -2
- data/app/interactors/spree_cm_commissioner/sms.rb +2 -3
- data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
- data/app/jobs/spree_cm_commissioner/voting_credit_allocation_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/voting_credit_de_allocation_job.rb +10 -0
- data/app/models/concerns/spree_cm_commissioner/homepage_section_bitwise.rb +2 -1
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +2 -1
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +10 -0
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
- data/app/models/spree_cm_commissioner/pin_code.rb +1 -1
- data/app/models/spree_cm_commissioner/role_decorator.rb +0 -3
- data/app/models/spree_cm_commissioner/show.rb +140 -0
- data/app/models/spree_cm_commissioner/show_contestant.rb +29 -0
- data/app/models/spree_cm_commissioner/show_contestant_image.rb +11 -0
- data/app/models/spree_cm_commissioner/show_episode.rb +70 -0
- data/app/models/spree_cm_commissioner/show_person.rb +15 -0
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +20 -0
- data/app/models/spree_cm_commissioner/show_person_image.rb +11 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +3 -0
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +10 -1
- data/app/models/spree_cm_commissioner/tenant.rb +0 -1
- data/app/models/spree_cm_commissioner/user_decorator.rb +0 -1
- data/app/models/spree_cm_commissioner/variant_options.rb +4 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +23 -0
- data/app/models/spree_cm_commissioner/voting_credit.rb +67 -0
- data/app/models/spree_cm_commissioner/voting_credit_transaction.rb +31 -0
- data/app/models/spree_cm_commissioner/voting_session.rb +97 -0
- data/app/serializers/spree/v2/tenant/line_item_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +19 -0
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +19 -0
- data/app/serializers/spree/v2/tenant/show_person_assignment_serializer.rb +16 -0
- data/app/serializers/spree/v2/tenant/show_person_serializer.rb +13 -0
- data/app/serializers/spree/v2/tenant/show_serializer.rb +25 -0
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +17 -0
- data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +13 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vehicle_type_serializer.rb +1 -1
- data/app/services/spree_cm_commissioner/agency_categories/create.rb +4 -1
- data/app/services/spree_cm_commissioner/api_caches/invalidate.rb +33 -51
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +80 -0
- data/app/services/spree_cm_commissioner/voting_credits/credit_calculator.rb +35 -0
- data/app/services/spree_cm_commissioner/voting_credits/de_allocate.rb +88 -0
- data/app/views/spree/admin/exports/index.html.erb +10 -0
- data/app/views/spree/admin/product_service_calendars/index.html.erb +0 -1
- data/app/views/spree/admin/shared/service_calendars/_exception_rules.html.erb +7 -20
- data/config/initializers/spree_permitted_attributes.rb +3 -0
- data/config/locales/en.yml +0 -6
- data/config/locales/km.yml +0 -5
- data/config/routes.rb +12 -3
- data/db/migrate/20260309230148_create_cm_show_people.rb +14 -0
- data/db/migrate/20260309230149_create_cm_show_people_assignments.rb +16 -0
- data/db/migrate/20260310082711_create_cm_show_contestants.rb +28 -0
- data/db/migrate/20260310082720_create_cm_voting_sessions.rb +21 -0
- data/db/migrate/20260310082721_create_cm_voting_contestants.rb +23 -0
- data/db/migrate/20260310082734_add_voting_fields_to_spree_taxons.rb +9 -0
- data/db/migrate/20260310082735_add_type_to_spree_products.rb +6 -0
- data/db/migrate/20260310082749_create_cm_voting_credits.rb +27 -0
- data/db/migrate/20260326080200_create_cm_voting_credit_transactions.rb +27 -0
- data/db/migrate/20260402000001_add_voting_credit_scope_to_spree_taxons.rb +6 -0
- data/db/migrate/20260402000002_rename_scopeable_to_votable_in_cm_voting_credits.rb +12 -0
- data/docs/sql/jsonb_query_guide.md +57 -0
- data/lib/spree_cm_commissioner/test_helper/factories/show_episode_factory.rb +12 -0
- data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +92 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vote_credit_factory.rb +38 -0
- data/lib/spree_cm_commissioner/test_helper/factories/voting_session_factory.rb +11 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +46 -15
- data/app/controllers/concerns/spree_cm_commissioner/turnstile_protectable.rb +0 -42
- data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +0 -91
- data/app/controllers/spree/api/v2/storefront/saved_guests_controller.rb +0 -77
- data/app/interactors/spree_cm_commissioner/turnstile_token_validator.rb +0 -55
- data/app/jobs/spree_cm_commissioner/cleanup_expired_access_tokens_job.rb +0 -9
- data/app/models/spree_cm_commissioner/agency.rb +0 -12
- data/app/serializers/spree/v2/organizer/invite_guest_serializer.rb +0 -13
- data/app/services/spree_cm_commissioner/cleanup_expired_access_tokens.rb +0 -52
- data/app/views/spree/admin/product_service_calendars/edit.html.erb +0 -9
- data/db/migrate/20260311105437_add_tenant_to_cm_sms_logs.rb +0 -5
- data/db/migrate/20260318081516_create_cm_agencies.rb +0 -18
- data/db/migrate/20260319090000_add_role_type_to_spree_roles.rb +0 -5
- data/db/migrate/20260320103313_add_index_to_spree_oauth_access_tokens_created_at.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4c381df113afbf82a9586168ede0e86f1bfee87849e50d3f9aed7a4b5455c2ab
|
|
4
|
+
data.tar.gz: 8466ba5865693c20fe012ca0463b584c9be3fe1aed6e25f3d37d31ef3ad76121
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e8ad8ac4e47e7a75a68f60244bf4033fb5d035bbd722e7f7d8ecebad7f81d08634990087a47e8702d47fb919bea1c60e3ba81f35fc1f772c2d0e0efa41c59b2f
|
|
7
|
+
data.tar.gz: 4a0ae2cd87ccca4f91cd2604a979771192cabffaf63978290a86dae624e25e18c1cf581f2d09a5f9805fa32f159b6e7f4b1982b3bc85958dd53da3b1385764c3
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -153,37 +153,8 @@ PIN_CODE_DEBUG_NOTIFIY_TELEGRAM_ENABLE="yes"
|
|
|
153
153
|
EXCEPTION_NOTIFY_ENABLE="yes" # yes or no
|
|
154
154
|
EXCEPTION_TELEGRAM_BOT_TOKEN=""
|
|
155
155
|
EXCEPTION_NOTIFIER_TELEGRAM_CHANNEL_ID=""
|
|
156
|
-
|
|
157
|
-
TURNSTILE_SECRET_KEY="" # Cloudflare Turnstile secret key (server-side verification)
|
|
158
156
|
```
|
|
159
157
|
|
|
160
|
-
### Cloudflare Turnstile
|
|
161
|
-
|
|
162
|
-
Cloudflare Turnstile is used to protect sensitive API endpoints from bots. The server-side validation is handled by `SpreeCmCommissioner::TurnstileTokenValidator` and the concern `SpreeCmCommissioner::TurnstileProtectable`.
|
|
163
|
-
|
|
164
|
-
**Protected endpoints:**
|
|
165
|
-
|
|
166
|
-
- `POST /api/v2/storefront/pin_code_generators`
|
|
167
|
-
- `POST /api/v2/storefront/pin_code_otp_generators`
|
|
168
|
-
- `POST /api/v2/storefront/user_registration_with_pin_codes`
|
|
169
|
-
- `PUT /api/v2/storefront/reset_passwords`
|
|
170
|
-
- `PATCH /api/v2/storefront/checkout/complete`
|
|
171
|
-
|
|
172
|
-
**How it works:**
|
|
173
|
-
|
|
174
|
-
1. The client sends a Turnstile token via the `X-Turnstile-Token` HTTP header
|
|
175
|
-
2. `TurnstileProtectable` reads the header and calls `TurnstileTokenValidator`
|
|
176
|
-
3. The validator POSTs to Cloudflare's siteverify API with the token and `TURNSTILE_SECRET_KEY`
|
|
177
|
-
4. Returns 403 if verification fails
|
|
178
|
-
|
|
179
|
-
**Configuration:**
|
|
180
|
-
|
|
181
|
-
1. Set `TURNSTILE_SECRET_KEY` in `.env` (obtained from [Cloudflare Turnstile dashboard](https://dash.cloudflare.com/))
|
|
182
|
-
2. For local development testing, use Cloudflare's test keys:
|
|
183
|
-
- Always pass: `1x0000000000000000000000000000000AA`
|
|
184
|
-
- Always fail: `2x0000000000000000000000000000000AA`
|
|
185
|
-
- Token spent: `3x0000000000000000000000000000000AA`
|
|
186
|
-
|
|
187
158
|
## JSON Format Examples For Store and Tenant Preferences
|
|
188
159
|
|
|
189
160
|
### Asset Links Format
|
|
@@ -44,8 +44,6 @@ module Spree
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
46
|
def build_exception_rules(exception_rules)
|
|
47
|
-
return [] if exception_rules.nil?
|
|
48
|
-
|
|
49
47
|
exception_rules.values.reject! { |rule| rule['from'].blank? || rule['to'].blank? || rule['type'].blank? } || exception_rules.values
|
|
50
48
|
end
|
|
51
49
|
|
|
@@ -59,7 +57,7 @@ module Spree
|
|
|
59
57
|
end
|
|
60
58
|
|
|
61
59
|
def set_exception_rules
|
|
62
|
-
@exception_rules =
|
|
60
|
+
@exception_rules = [{ from: DateTime.now, to: DateTime.now, type: 'exclusion', reason: nil }]
|
|
63
61
|
end
|
|
64
62
|
|
|
65
63
|
def build_resource
|
|
@@ -6,7 +6,6 @@ module Spree
|
|
|
6
6
|
before_action :load_product
|
|
7
7
|
before_action :ensure_product_type_supports_calendar
|
|
8
8
|
before_action :ensure_product_has_no_calendar, only: %i[new create]
|
|
9
|
-
before_action :set_exception_rules, only: %i[edit update]
|
|
10
9
|
|
|
11
10
|
create.before :set_calendarable
|
|
12
11
|
update.before :set_calendarable
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class ShowContestantsController < BaseController
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# override
|
|
9
|
+
def model_class
|
|
10
|
+
SpreeCmCommissioner::ShowContestant
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# override
|
|
14
|
+
def scope
|
|
15
|
+
return model_class.none unless current_show
|
|
16
|
+
|
|
17
|
+
model_class
|
|
18
|
+
.where(show_id: current_show.id)
|
|
19
|
+
.includes(
|
|
20
|
+
:show_contestant_images,
|
|
21
|
+
:current_voting_session,
|
|
22
|
+
assigned_show_person: :show_person_images,
|
|
23
|
+
show: [
|
|
24
|
+
:parent,
|
|
25
|
+
{ episodes: :voting_sessions },
|
|
26
|
+
{ seasons: { episodes: :voting_sessions } }
|
|
27
|
+
]
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def current_show
|
|
32
|
+
@current_show ||= show_scope.find_by!(slug: params[:show_id])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def show_scope
|
|
36
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
37
|
+
return SpreeCmCommissioner::Show.none if vendor_ids.blank?
|
|
38
|
+
|
|
39
|
+
SpreeCmCommissioner::Show.where(vendor_id: vendor_ids)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# override
|
|
43
|
+
def resource_serializer
|
|
44
|
+
Spree::V2::Tenant::ShowContestantSerializer
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class ShowPeopleController < BaseController
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# override
|
|
9
|
+
def model_class
|
|
10
|
+
SpreeCmCommissioner::ShowPerson
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# override
|
|
14
|
+
def scope
|
|
15
|
+
scope = current_show.show_people
|
|
16
|
+
.joins(:assignments)
|
|
17
|
+
.distinct
|
|
18
|
+
.includes(
|
|
19
|
+
:assignments,
|
|
20
|
+
assigned_contestants: %i[show_contestant_images current_voting_session]
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
role = params[:role].presence
|
|
24
|
+
return scope if role.blank?
|
|
25
|
+
|
|
26
|
+
role_value = SpreeCmCommissioner::ShowPersonAssignment.roles[role.to_s]
|
|
27
|
+
return scope.none if role_value.nil?
|
|
28
|
+
|
|
29
|
+
scope.where(cm_show_people_assignments: { role: role_value })
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# override
|
|
33
|
+
def resource_serializer
|
|
34
|
+
Spree::V2::Tenant::ShowPersonSerializer
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# override
|
|
38
|
+
def collection_serializer
|
|
39
|
+
Spree::V2::Tenant::ShowPersonSerializer
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def current_show
|
|
43
|
+
@current_show ||= show_scope.find_by!(slug: params[:show_id])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def show_scope
|
|
47
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
48
|
+
SpreeCmCommissioner::Show.where(vendor_id: vendor_ids)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class ShowPersonAssignmentsController < BaseController
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def model_class
|
|
9
|
+
SpreeCmCommissioner::ShowPersonAssignment
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def scope
|
|
13
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
14
|
+
show_ids = SpreeCmCommissioner::Show.where(vendor_id: vendor_ids).select(:id)
|
|
15
|
+
|
|
16
|
+
model_class.where(show_id: show_ids)
|
|
17
|
+
.where(show_person_id: params[:person_id], show_id: current_show.id)
|
|
18
|
+
.includes(:show_person, :show)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def current_show
|
|
22
|
+
@current_show ||= SpreeCmCommissioner::Show.find_by!(slug: params[:show_id])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resource_serializer
|
|
26
|
+
Spree::V2::Tenant::ShowPersonAssignmentSerializer
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def collection_serializer
|
|
30
|
+
Spree::V2::Tenant::ShowPersonAssignmentSerializer
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class ShowsController < BaseController
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# override
|
|
9
|
+
def model_class
|
|
10
|
+
SpreeCmCommissioner::Show
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def resource
|
|
14
|
+
@resource ||= scope.find_by!(slug: params[:id])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# override
|
|
18
|
+
def scope
|
|
19
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
20
|
+
return model_class.none if vendor_ids.blank?
|
|
21
|
+
|
|
22
|
+
model_class.where(vendor_id: vendor_ids)
|
|
23
|
+
.includes(:parent, :app_banner, episodes: :voting_sessions, seasons: { episodes: :voting_sessions })
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# override
|
|
27
|
+
def resource_serializer
|
|
28
|
+
Spree::V2::Tenant::ShowSerializer
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# override
|
|
32
|
+
def collection_serializer
|
|
33
|
+
Spree::V2::Tenant::ShowSerializer
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class VotingContestantsController < BaseController
|
|
6
|
+
before_action :load_voting_session, only: %i[index]
|
|
7
|
+
|
|
8
|
+
# override
|
|
9
|
+
def collection
|
|
10
|
+
@collection ||= @voting_session
|
|
11
|
+
.voting_contestants
|
|
12
|
+
.includes(show_contestant: :show_contestant_images)
|
|
13
|
+
.order(:id)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# override
|
|
17
|
+
def collection_serializer
|
|
18
|
+
Spree::V2::Tenant::VotingContestantSerializer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# override
|
|
24
|
+
def model_class
|
|
25
|
+
SpreeCmCommissioner::VotingSession
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# override
|
|
29
|
+
def scope
|
|
30
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
31
|
+
show_ids = SpreeCmCommissioner::Show.where(vendor_id: vendor_ids).select(:id)
|
|
32
|
+
episode_ids = Spree::Product.where(event_id: show_ids, type: 'SpreeCmCommissioner::ShowEpisode').select(:id)
|
|
33
|
+
model_class
|
|
34
|
+
.where(episode_id: episode_ids)
|
|
35
|
+
.includes(:episode)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def load_voting_session
|
|
39
|
+
@voting_session = scope.find(params[:voting_session_id])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -20,8 +20,7 @@ module SpreeCmCommissioner
|
|
|
20
20
|
options = {
|
|
21
21
|
from: context.pin_code&.application&.sms_sender_id,
|
|
22
22
|
to: context.pin_code.contact,
|
|
23
|
-
body: I18n.t('pincode_sender.sms.body', code: context.pin_code.code, readable_type: context.pin_code.readable_type)
|
|
24
|
-
tenant_id: context.pin_code&.application&.tenant_id
|
|
23
|
+
body: I18n.t('pincode_sender.sms.body', code: context.pin_code.code, readable_type: context.pin_code.readable_type)
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
SpreeCmCommissioner::SmsPinCodeJob.perform_later(options)
|
|
@@ -36,13 +36,12 @@ module SpreeCmCommissioner
|
|
|
36
36
|
from_number: sms_options[:from],
|
|
37
37
|
to_number: sms_options[:to],
|
|
38
38
|
body: sms_options[:body],
|
|
39
|
-
adapter_name: adapter.class.name.demodulize
|
|
40
|
-
tenant_id: sms_options[:tenant_id]
|
|
39
|
+
adapter_name: adapter.class.name.demodulize
|
|
41
40
|
)
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def sms_options
|
|
45
|
-
opts = { to: context.to, body: context.body
|
|
44
|
+
opts = { to: context.to, body: context.body }
|
|
46
45
|
opts[:to] = sanitize(opts[:to]) if opts[:to].present?
|
|
47
46
|
opts[:from] = from_number
|
|
48
47
|
opts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class SmsPinCodeJob < SpreeCmCommissioner::SmsJob
|
|
3
|
-
# options = { from: xxxx, to: xxxx, body: xxxx
|
|
3
|
+
# options = { from: xxxx, to: xxxx, body: xxxx }
|
|
4
4
|
def perform(options = {})
|
|
5
5
|
SpreeCmCommissioner::Sms.call(options)
|
|
6
6
|
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class VotingCreditAllocationJob < ApplicationUniqueJob
|
|
3
|
+
def perform(options = {})
|
|
4
|
+
order = Spree::Order.find_by(id: options[:order_id])
|
|
5
|
+
return if order.nil?
|
|
6
|
+
|
|
7
|
+
SpreeCmCommissioner::VotingCredits::Allocate.new(order).call
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class VotingCreditDeAllocationJob < ApplicationUniqueJob
|
|
3
|
+
def perform(options = {})
|
|
4
|
+
order = Spree::Order.find_by(id: options[:order_id])
|
|
5
|
+
return if order.nil?
|
|
6
|
+
|
|
7
|
+
SpreeCmCommissioner::VotingCredits::DeAllocate.new(order).call
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -27,8 +27,10 @@ module SpreeCmCommissioner
|
|
|
27
27
|
|
|
28
28
|
state_machine.after_transition to: :canceled, do: :precalculate_conversion
|
|
29
29
|
state_machine.after_transition to: :canceled, do: :restock_inventory!
|
|
30
|
+
state_machine.after_transition to: :canceled, do: :de_allocate_resources
|
|
30
31
|
|
|
31
32
|
state_machine.after_transition to: :complete, do: :increment_route_fulfilled_order_count
|
|
33
|
+
state_machine.after_transition to: :complete, do: :allocate_resources
|
|
32
34
|
|
|
33
35
|
scope :accepted, -> { where(request_state: 'accepted') }
|
|
34
36
|
|
|
@@ -322,5 +324,13 @@ module SpreeCmCommissioner
|
|
|
322
324
|
factory = OrderTelegramMessageFactory.new(title: title, order: self)
|
|
323
325
|
TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
|
|
324
326
|
end
|
|
327
|
+
|
|
328
|
+
def allocate_resources
|
|
329
|
+
SpreeCmCommissioner::VotingCreditAllocationJob.perform_later(order_id: id)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def de_allocate_resources
|
|
333
|
+
SpreeCmCommissioner::VotingCreditDeAllocationJob.perform_later(order_id: id)
|
|
334
|
+
end
|
|
325
335
|
end
|
|
326
336
|
end
|
|
@@ -5,7 +5,7 @@ module SpreeCmCommissioner
|
|
|
5
5
|
module ProductType
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
|
-
PRODUCT_TYPES = %i[accommodation service ecommerce transit].freeze
|
|
8
|
+
PRODUCT_TYPES = %i[accommodation service ecommerce transit vote_package].freeze
|
|
9
9
|
PERMANENT_STOCK_PRODUCT_TYPES = %w[accommodation service transit].freeze
|
|
10
10
|
PRE_INVENTORY_DAYS = { 'transit' => 90, 'accommodation' => 365, 'service' => 30 }.freeze
|
|
11
11
|
|
|
@@ -132,7 +132,7 @@ module SpreeCmCommissioner
|
|
|
132
132
|
'SpreeCmCommissioner::PinCodeMobileConfirm' => I18n.t('pincode.readable_type.confirmation_code'),
|
|
133
133
|
'SpreeCmCommissioner::PinCodeUpdateUserLogin' => I18n.t('pincode.readable_type.update_user_login'),
|
|
134
134
|
'SpreeCmCommissioner::PinCodeEmailConfirm' => I18n.t('pincode.readable_type.confirmation_code'),
|
|
135
|
-
'SpreeCmCommissioner::
|
|
135
|
+
'SpreeCmCommissioner::OtpCode' => I18n.t('pincode.readable_type.otp_code'),
|
|
136
136
|
'SpreeCmCommissioner::PinCodeTelegram' => I18n.t('pincode.readable_type.telegram_verification')
|
|
137
137
|
}
|
|
138
138
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module RoleDecorator
|
|
3
3
|
def self.prepended(base)
|
|
4
|
-
base.enum role_type: { internal: 0, external: 1 }
|
|
5
|
-
|
|
6
4
|
base.has_many :role_permissions, class_name: 'SpreeCmCommissioner::RolePermission'
|
|
7
5
|
base.has_many :permissions, through: :role_permissions, class_name: 'SpreeCmCommissioner::Permission'
|
|
8
6
|
|
|
@@ -12,7 +10,6 @@ module SpreeCmCommissioner
|
|
|
12
10
|
base.scope :filter_by_vendor, lambda { |vendor|
|
|
13
11
|
where(vendor_id: vendor)
|
|
14
12
|
}
|
|
15
|
-
base.scope :filter_external, -> { where(role_type: :external) }
|
|
16
13
|
|
|
17
14
|
base.accepts_nested_attributes_for :role_permissions, allow_destroy: true
|
|
18
15
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class Show < Spree::Taxon
|
|
3
|
+
include SpreeCmCommissioner::StoreMetadata
|
|
4
|
+
|
|
5
|
+
has_many :seasons, class_name: 'SpreeCmCommissioner::Show', foreign_key: :parent_id, inverse_of: :parent
|
|
6
|
+
has_many :show_contestants, class_name: 'SpreeCmCommissioner::ShowContestant', inverse_of: :show, dependent: :destroy
|
|
7
|
+
has_many :show_people_assignments, class_name: 'SpreeCmCommissioner::ShowPersonAssignment', dependent: :destroy
|
|
8
|
+
has_many :show_people, through: :show_people_assignments, source: :show_person
|
|
9
|
+
has_many :episodes, class_name: 'SpreeCmCommissioner::ShowEpisode', foreign_key: :event_id
|
|
10
|
+
has_one :current_episode, -> { current_or_next_upcoming }, class_name: 'SpreeCmCommissioner::ShowEpisode', foreign_key: :event_id
|
|
11
|
+
has_one :current_voting_session, through: :current_episode
|
|
12
|
+
|
|
13
|
+
before_validation { self.type = self.class.name }
|
|
14
|
+
before_validation { self.kind = :event }
|
|
15
|
+
before_validation :assign_taxonomy_and_parent, on: :create
|
|
16
|
+
|
|
17
|
+
store_private_metadata :season_number, :integer
|
|
18
|
+
store_private_metadata :season_year, :integer
|
|
19
|
+
|
|
20
|
+
# Define standard voting configuration keys
|
|
21
|
+
store_accessor :voting_config,
|
|
22
|
+
:free_vote_limit,
|
|
23
|
+
:free_vote_limit_type,
|
|
24
|
+
:paid_vote_enabled,
|
|
25
|
+
:max_paid_votes_per_session,
|
|
26
|
+
:sms_vote_enabled,
|
|
27
|
+
:sms_vote_cost_usd,
|
|
28
|
+
:operator_vote_enabled
|
|
29
|
+
|
|
30
|
+
# voting_credit_scope determines how purchased vote credits are grouped (scoped).
|
|
31
|
+
# Changing this after credits have been allocated will cause inconsistencies:
|
|
32
|
+
# - existing credits are scoped to the old type (e.g. ShowEpisode),
|
|
33
|
+
# but new purchases will create credits under the new type (e.g. Show),
|
|
34
|
+
# leading to split balances that cannot be merged.
|
|
35
|
+
# UI rule: once voting_credit_scope is set and any VotingCredit exists for this show, the field must be read-only — do not allow changes.
|
|
36
|
+
# Note: VoteCredit of user should base on CREDIT_SCOPES
|
|
37
|
+
# - if scope is Show, User's credits should be only 1 per show, and can be used for any episode under the show.
|
|
38
|
+
# - if scope is ShowEpisode, User's credits should be N per show (N is the number of episodes), and can be only used for specific episode.
|
|
39
|
+
# - if scope is VotingSession, User's credits should be N per show (N is the number of voting sessions), and can be only used for specific voting session. # rubocop:disable Layout/LineLength
|
|
40
|
+
CREDIT_SCOPES = %w[Show ShowEpisode VotingSession].freeze
|
|
41
|
+
|
|
42
|
+
def self.polymorphic_name
|
|
43
|
+
name
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
validate :voting_credit_scope_immutable, if: :voting_credit_scope_changed?
|
|
47
|
+
|
|
48
|
+
def credit_votable_type
|
|
49
|
+
voting_credit_scope = self[:voting_credit_scope] || 'ShowEpisode'
|
|
50
|
+
|
|
51
|
+
type = CREDIT_SCOPES.include?(voting_credit_scope) ? voting_credit_scope : 'ShowEpisode'
|
|
52
|
+
"SpreeCmCommissioner::#{type}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Define standard fraud configuration keys
|
|
56
|
+
store_accessor :fraud_config,
|
|
57
|
+
:max_votes_per_minute_per_user,
|
|
58
|
+
:max_votes_per_minute_per_ip,
|
|
59
|
+
:max_accounts_per_device,
|
|
60
|
+
:block_vpn
|
|
61
|
+
|
|
62
|
+
def show?
|
|
63
|
+
depth == 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def season?
|
|
67
|
+
depth == 2
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def display_name
|
|
71
|
+
if season? && parent.present?
|
|
72
|
+
"#{parent.name} #{name}"
|
|
73
|
+
else
|
|
74
|
+
name
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def contestants
|
|
79
|
+
show_contestants
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def effective_voting_config
|
|
83
|
+
config = parse_json_config(voting_config)
|
|
84
|
+
return config if show?
|
|
85
|
+
|
|
86
|
+
config.reverse_merge(parent&.effective_voting_config || {})
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def effective_fraud_config
|
|
90
|
+
config = parse_json_config(fraud_config)
|
|
91
|
+
return config if show?
|
|
92
|
+
|
|
93
|
+
config.reverse_merge(parent&.effective_fraud_config || {})
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def build_next_season(attributes = {})
|
|
97
|
+
last_season = seasons.order(created_at: :desc).first
|
|
98
|
+
|
|
99
|
+
default_number = (last_season&.season_number || 0) + 1
|
|
100
|
+
default_year = last_season&.season_year || Time.current.year
|
|
101
|
+
|
|
102
|
+
seasons.new(
|
|
103
|
+
{
|
|
104
|
+
season_number: default_number,
|
|
105
|
+
season_year: default_year
|
|
106
|
+
}.merge(attributes)
|
|
107
|
+
)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def assign_taxonomy_and_parent
|
|
113
|
+
if parent.present?
|
|
114
|
+
self.taxonomy ||= parent.taxonomy
|
|
115
|
+
elsif taxonomy_id.blank?
|
|
116
|
+
self.taxonomy = Spree::Taxonomy.shows
|
|
117
|
+
self.parent = taxonomy.root
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def voting_credit_scope_immutable
|
|
122
|
+
show_has_credits = SpreeCmCommissioner::VotingCredit.exists?(votable_type: 'SpreeCmCommissioner::Show', votable_id: id)
|
|
123
|
+
episode_has_credits = SpreeCmCommissioner::VotingCredit.exists?(votable_type: 'SpreeCmCommissioner::ShowEpisode',
|
|
124
|
+
votable_id: episodes.select(:id)
|
|
125
|
+
)
|
|
126
|
+
return unless show_has_credits || episode_has_credits
|
|
127
|
+
|
|
128
|
+
errors.add(:voting_credit_scope, 'cannot be changed after voting credits have been allocated')
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def parse_json_config(value)
|
|
132
|
+
return {} if value.nil? || value == ''
|
|
133
|
+
return value if value.is_a?(Hash)
|
|
134
|
+
|
|
135
|
+
JSON.parse(value)
|
|
136
|
+
rescue JSON::ParserError
|
|
137
|
+
{}
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class ShowContestant < SpreeCmCommissioner::Base
|
|
3
|
+
belongs_to :show, class_name: 'SpreeCmCommissioner::Show', optional: false
|
|
4
|
+
belongs_to :assigned_show_person, class_name: 'SpreeCmCommissioner::ShowPerson', optional: true
|
|
5
|
+
belongs_to :user, class_name: 'Spree::User', optional: true
|
|
6
|
+
has_many :show_contestant_images, lambda {
|
|
7
|
+
order(:position)
|
|
8
|
+
}, as: :viewable, class_name: 'SpreeCmCommissioner::ShowContestantImage', dependent: :destroy
|
|
9
|
+
has_one :show_person_images, -> { order(:position) }, as: :viewable, class_name: 'SpreeCmCommissioner::ShowPersonImage', dependent: :destroy
|
|
10
|
+
|
|
11
|
+
has_many :voting_contestants, class_name: 'SpreeCmCommissioner::VotingContestant', dependent: :destroy
|
|
12
|
+
has_one :current_voting_session, through: :show
|
|
13
|
+
|
|
14
|
+
enum status: { active: 0, eliminated: 1, advanced: 2, winner: 3, withdrawn: 4 }
|
|
15
|
+
enum gender: { :other => 0, :male => 1, :female => 2 }
|
|
16
|
+
|
|
17
|
+
enum category: { boys: 0, girls: 1, groups: 2, overs: 3 }
|
|
18
|
+
|
|
19
|
+
# Define standard Social Link Keys
|
|
20
|
+
store_accessor :social_links, :facebook, :instagram, :twitter, :linkedin, :youtube, :tiktok, :telegram
|
|
21
|
+
|
|
22
|
+
validates :name, presence: true
|
|
23
|
+
validates :contestant_number, uniqueness: { scope: :show_id }, allow_nil: true
|
|
24
|
+
|
|
25
|
+
scope :ordered, -> { order(:position, :id) }
|
|
26
|
+
|
|
27
|
+
self.whitelisted_ransackable_attributes = %w[name contestant_number status gender category]
|
|
28
|
+
end
|
|
29
|
+
end
|