spree_cm_commissioner 2.8.1.pre.pre.4 → 2.8.2.pre.pre.1
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/app/controllers/spree/api/v2/tenant/show_elimination_sessions_controller.rb +57 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +8 -0
- data/app/models/concerns/spree_cm_commissioner/service_origin.rb +22 -0
- data/app/models/spree_cm_commissioner/route.rb +6 -1
- data/app/models/spree_cm_commissioner/show_contestant.rb +2 -9
- data/app/models/spree_cm_commissioner/trip.rb +5 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +1 -1
- data/app/models/spree_cm_commissioner/voting_session.rb +4 -1
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +5 -1
- data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +4 -1
- data/app/services/spree_cm_commissioner/pricing_models/preview.rb +15 -6
- data/app/services/spree_cm_commissioner/routes/create.rb +0 -5
- data/app/services/spree_cm_commissioner/trips/create_multi_leg.rb +5 -16
- data/app/services/spree_cm_commissioner/trips/create_single_leg.rb +0 -1
- data/app/services/spree_cm_commissioner/vote_counters/per_contestant_counter.rb +2 -0
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +2 -1
- data/app/services/spree_cm_commissioner/voting_sessions/finalize.rb +66 -0
- data/config/locales/en.yml +2 -0
- data/config/locales/km.yml +4 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20260527035430_add_confirmed_rank_to_cm_voting_contestants.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +16 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +6 -3
- data/app/controllers/spree/api/v2/tenant/eliminated_contestants_controller.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 595e82de2ef3a0ab170476a3ad96ab5d25d3d501916fa7b740d4d3d50f11193f
|
|
4
|
+
data.tar.gz: fb43eb4f67c1dc65ea1833f90f51624595122a6555c5099ac153a6abf20a1d3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a63ca4741ece801cadde290f28f810bcc7143a320201af0d1a074b2a9ae380b7307807d06eac856d01d062eb27b149efaf9e70e87c6853008d2bf667d852d3d1
|
|
7
|
+
data.tar.gz: d6cbf032196337ad97649cc72a4f2d1a7a0426224498cd0e2df492e4251a67ed00a7876e9719a66296b8ff9f168be7fa4c991e91a7d318f71eeab08802ae377f
|
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class ShowEliminationSessionsController < BaseController
|
|
6
|
+
# override
|
|
7
|
+
def collection
|
|
8
|
+
@collection ||= scope
|
|
9
|
+
.includes(
|
|
10
|
+
:episode,
|
|
11
|
+
:show,
|
|
12
|
+
eliminated_voting_contestants: [
|
|
13
|
+
:show_contestant,
|
|
14
|
+
{ show_contestant: %i[show_contestant_images show_contestant_videos] }
|
|
15
|
+
]
|
|
16
|
+
)
|
|
17
|
+
.order('cm_voting_sessions.closes_at DESC')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# override
|
|
21
|
+
def collection_serializer
|
|
22
|
+
Spree::V2::Tenant::VotingSessionSerializer
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
# override
|
|
28
|
+
def model_class
|
|
29
|
+
SpreeCmCommissioner::VotingSession
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# override
|
|
33
|
+
def scope
|
|
34
|
+
return model_class.none unless current_show
|
|
35
|
+
|
|
36
|
+
current_show.voting_sessions
|
|
37
|
+
.joins(:episode)
|
|
38
|
+
.joins(:voting_contestants)
|
|
39
|
+
.where(voting_contestants: { eliminated: true })
|
|
40
|
+
.distinct
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def current_show
|
|
44
|
+
@current_show ||= show_scope.find_by!(slug: params[:show_id])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def show_scope
|
|
48
|
+
vendor_ids = @tenant.vendors.select(:id)
|
|
49
|
+
return SpreeCmCommissioner::Show.none if vendor_ids.blank?
|
|
50
|
+
|
|
51
|
+
SpreeCmCommissioner::Show.where(vendor_id: vendor_ids)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -23,6 +23,8 @@ module SpreeCmCommissioner
|
|
|
23
23
|
TripKey = Struct.new(:trip_id, :direction, :boarding_trip_stop_id, :drop_off_trip_stop_id)
|
|
24
24
|
|
|
25
25
|
included do
|
|
26
|
+
include SpreeCmCommissioner::ServiceOrigin
|
|
27
|
+
|
|
26
28
|
validates :direction, inclusion: { in: DIRECTION }, allow_nil: true
|
|
27
29
|
validates :trip_id, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
|
|
28
30
|
validates :service_origin_id, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
|
|
@@ -125,6 +127,12 @@ module SpreeCmCommissioner
|
|
|
125
127
|
|
|
126
128
|
private
|
|
127
129
|
|
|
130
|
+
def resolve_service_origin_id
|
|
131
|
+
return nil if trip_id.blank?
|
|
132
|
+
|
|
133
|
+
SpreeCmCommissioner::Trip.find_by(id: trip_id)&.service_origin_id
|
|
134
|
+
end
|
|
135
|
+
|
|
128
136
|
def validate_trip_stops_for_scheduled_trips
|
|
129
137
|
return if trip_id.blank? || trip_id.zero?
|
|
130
138
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
# Defaults service_origin (nationality) from parent associations during validation (on create).
|
|
3
|
+
# Vendor → Route → Trip → LineItem.
|
|
4
|
+
# Pricing rules use this to determine local vs foreigner rates.
|
|
5
|
+
module ServiceOrigin
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
before_validation :assign_service_origin_id, on: :create
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def assign_service_origin_id
|
|
15
|
+
self.service_origin_id ||= resolve_service_origin_id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def resolve_service_origin_id
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -2,8 +2,9 @@ module SpreeCmCommissioner
|
|
|
2
2
|
class Route < Base
|
|
3
3
|
include SpreeCmCommissioner::RouteType
|
|
4
4
|
include SpreeCmCommissioner::StoreMetadata
|
|
5
|
+
include SpreeCmCommissioner::ServiceOrigin
|
|
5
6
|
|
|
6
|
-
belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
|
|
7
|
+
belongs_to :vendor, class_name: 'Spree::Vendor', inverse_of: :routes, optional: false
|
|
7
8
|
belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant', optional: true
|
|
8
9
|
|
|
9
10
|
belongs_to :service_origin, class_name: 'Spree::Taxon', optional: true
|
|
@@ -66,6 +67,10 @@ module SpreeCmCommissioner
|
|
|
66
67
|
|
|
67
68
|
private
|
|
68
69
|
|
|
70
|
+
def resolve_service_origin_id
|
|
71
|
+
vendor&.service_origin_id
|
|
72
|
+
end
|
|
73
|
+
|
|
69
74
|
def validate_route_stops
|
|
70
75
|
return if route_stops.valid?
|
|
71
76
|
|
|
@@ -27,17 +27,10 @@ module SpreeCmCommissioner
|
|
|
27
27
|
validates :name, presence: true
|
|
28
28
|
validates :contestant_number, uniqueness: { scope: :show_id }, allow_nil: true
|
|
29
29
|
|
|
30
|
-
before_save :set_eliminated_at, if: :status_changed_to_eliminated?
|
|
31
|
-
|
|
32
30
|
scope :ordered, -> { order(:position, :id) }
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def status_changed_to_eliminated?
|
|
37
|
-
status_changed? && eliminated?
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def set_eliminated_at
|
|
32
|
+
def eliminate
|
|
33
|
+
self.status = :eliminated
|
|
41
34
|
self.eliminated_at = Time.current
|
|
42
35
|
end
|
|
43
36
|
|
|
@@ -2,6 +2,7 @@ module SpreeCmCommissioner
|
|
|
2
2
|
class Trip < Base
|
|
3
3
|
include SpreeCmCommissioner::StoreMetadata
|
|
4
4
|
include SpreeCmCommissioner::RouteType
|
|
5
|
+
include SpreeCmCommissioner::ServiceOrigin
|
|
5
6
|
|
|
6
7
|
attr_accessor :hours, :minutes, :seconds
|
|
7
8
|
|
|
@@ -133,6 +134,10 @@ module SpreeCmCommissioner
|
|
|
133
134
|
|
|
134
135
|
private
|
|
135
136
|
|
|
137
|
+
def resolve_service_origin_id
|
|
138
|
+
route&.service_origin_id || vendor&.service_origin_id
|
|
139
|
+
end
|
|
140
|
+
|
|
136
141
|
def duplicate_seat_layout_from_vehicle
|
|
137
142
|
# Duplicate the vehicle's seat layout into this trip. Copies nested
|
|
138
143
|
# seat sections and blocks while excluding identifying columns and
|
|
@@ -32,7 +32,7 @@ module SpreeCmCommissioner
|
|
|
32
32
|
# | 1 | 2 | 1 | ✓ OK | Different session |
|
|
33
33
|
validates :vote_number, uniqueness: { scope: %i[show_contestant_id voting_session_id], allow_nil: true }
|
|
34
34
|
|
|
35
|
-
delegate :name, :contestant_number, :category, :gender, to: :show_contestant, allow_nil: true
|
|
35
|
+
delegate :name, :contestant_number, :category, :gender, :eliminated_at, to: :show_contestant, allow_nil: true
|
|
36
36
|
delegate :can_vote?, to: :voting_session, allow_nil: true
|
|
37
37
|
|
|
38
38
|
def special_rule_type=(value)
|
|
@@ -8,6 +8,9 @@ module SpreeCmCommissioner
|
|
|
8
8
|
|
|
9
9
|
has_many :voting_credits, class_name: 'SpreeCmCommissioner::VotingCredit', as: :votable, dependent: :destroy
|
|
10
10
|
has_many :voting_contestants, class_name: 'SpreeCmCommissioner::VotingContestant', dependent: :destroy
|
|
11
|
+
has_many :eliminated_voting_contestants, lambda {
|
|
12
|
+
where(eliminated: true)
|
|
13
|
+
}, class_name: 'SpreeCmCommissioner::VotingContestant', foreign_key: 'voting_session_id'
|
|
11
14
|
has_many :show_contestants, through: :voting_contestants
|
|
12
15
|
has_many :contestants, through: :show, source: :show_contestants
|
|
13
16
|
has_many :votes, class_name: 'SpreeCmCommissioner::Vote', dependent: :destroy
|
|
@@ -15,7 +18,7 @@ module SpreeCmCommissioner
|
|
|
15
18
|
|
|
16
19
|
acts_as_list scope: :episode
|
|
17
20
|
|
|
18
|
-
enum status: { disabled: 0, enabled: 1, closed: 2 }
|
|
21
|
+
enum status: { disabled: 0, enabled: 1, closed: 2, finalized: 3 }
|
|
19
22
|
enum scoring_model: { manual: 0, geometric: 1, harmonic: 2, weighted_sum: 3, arithmetic: 4 }
|
|
20
23
|
|
|
21
24
|
self.whitelisted_ransackable_attributes = %w[name status]
|
|
@@ -4,12 +4,16 @@ module Spree
|
|
|
4
4
|
class VotingContestantSerializer < BaseSerializer
|
|
5
5
|
set_type :voting_contestant
|
|
6
6
|
|
|
7
|
-
attributes :show_contestant_id, :name, :contestant_number, :vote_number, :category, :gender
|
|
7
|
+
attributes :show_id, :show_contestant_id, :name, :contestant_number, :vote_number, :category, :gender,
|
|
8
|
+
:vote_count, :eliminated, :eliminated_via, :eliminated_at, :advanced_to_type, :advanced_to_id, :special_rules,
|
|
9
|
+
:created_at, :updated_at, :advanced_from_type, :advanced_from_id, :unique_voter_count, :preferences
|
|
8
10
|
|
|
9
11
|
attribute :voting_session_id, &:voting_session_id
|
|
10
12
|
|
|
11
13
|
attribute :can_vote, &:can_vote?
|
|
12
14
|
|
|
15
|
+
belongs_to :voting_session, serializer: ::Spree::V2::Tenant::VotingSessionSerializer
|
|
16
|
+
|
|
13
17
|
has_many :show_contestant_images, serializer: ::Spree::V2::Tenant::AssetSerializer
|
|
14
18
|
has_many :show_contestant_videos, serializer: ::Spree::V2::Tenant::VideoSerializer
|
|
15
19
|
end
|
|
@@ -2,13 +2,16 @@ module Spree
|
|
|
2
2
|
module V2
|
|
3
3
|
module Tenant
|
|
4
4
|
class VotingSessionSerializer < BaseSerializer
|
|
5
|
-
attributes :opens_at, :closes_at, :status, :live_stream_enabled, :live_stream_thumbnail, :live_stream_title, :live_stream_description
|
|
5
|
+
attributes :name, :opens_at, :closes_at, :status, :live_stream_enabled, :live_stream_thumbnail, :live_stream_title, :live_stream_description,
|
|
6
|
+
:created_at
|
|
6
7
|
|
|
7
8
|
attribute :live_stream_url, &:embedded_live_stream_url
|
|
8
9
|
attribute :can_vote, &:can_vote?
|
|
9
10
|
|
|
10
11
|
belongs_to :episode, serializer: Spree::V2::Tenant::ShowEpisodeSerializer
|
|
11
12
|
belongs_to :show, serializer: Spree::V2::Tenant::ShowSerializer
|
|
13
|
+
|
|
14
|
+
has_many :eliminated_voting_contestants, serializer: ::Spree::V2::Tenant::VotingContestantSerializer
|
|
12
15
|
end
|
|
13
16
|
end
|
|
14
17
|
end
|
|
@@ -52,12 +52,16 @@ module SpreeCmCommissioner
|
|
|
52
52
|
vendor_ids = transit_contexts.map { |ctx| variant_vendor_id(ctx.variant_id) }.compact.uniq
|
|
53
53
|
return [] if vendor_ids.blank?
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
route_ids = trip_route_ids(transit_contexts)
|
|
56
|
+
|
|
57
|
+
scope = SpreeCmCommissioner::PricingModelRoute
|
|
58
|
+
.active
|
|
59
|
+
.for_origin_destination(origin_place_id, destination_place_id)
|
|
60
|
+
.includes(:pricing_model)
|
|
61
|
+
|
|
62
|
+
scope = scope.where(route_id: route_ids) if route_ids.any?
|
|
63
|
+
|
|
64
|
+
scope.map(&:pricing_model).select { |pm| vendor_ids.include?(pm.vendor_id) }
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
def variant_pricing_models(group_contexts)
|
|
@@ -83,6 +87,11 @@ module SpreeCmCommissioner
|
|
|
83
87
|
end
|
|
84
88
|
end
|
|
85
89
|
|
|
90
|
+
def trip_route_ids(transit_contexts)
|
|
91
|
+
trip_ids = transit_contexts.map(&:trip_id).compact.uniq
|
|
92
|
+
SpreeCmCommissioner::Trip.where(id: trip_ids).where.not(route_id: nil).distinct.pluck(:route_id)
|
|
93
|
+
end
|
|
94
|
+
|
|
86
95
|
def variant_vendor_id(variant_id)
|
|
87
96
|
return nil if variant_id.blank?
|
|
88
97
|
|
|
@@ -19,15 +19,10 @@ module SpreeCmCommissioner
|
|
|
19
19
|
destination_place = find_place_for(route_stops, route_stops.last)
|
|
20
20
|
|
|
21
21
|
return failure(nil, 'Origin or destination place could not be determined') if origin_place.nil? || destination_place.nil?
|
|
22
|
-
return failure(nil, 'Route with origin & destination already exists') if vendor.routes.exists?(
|
|
23
|
-
origin_place_id: origin_place.id,
|
|
24
|
-
destination_place_id: destination_place.id
|
|
25
|
-
)
|
|
26
22
|
|
|
27
23
|
attrs = attrs.merge(
|
|
28
24
|
tenant_id: vendor.tenant_id,
|
|
29
25
|
route_name: attrs[:route_name] || "#{origin_place.name} -> #{destination_place.name}",
|
|
30
|
-
service_origin_id: vendor.service_origin_id,
|
|
31
26
|
origin_place_id: origin_place.id,
|
|
32
27
|
destination_place_id: destination_place.id,
|
|
33
28
|
route_stops: route_stops
|
|
@@ -43,7 +43,7 @@ module SpreeCmCommissioner
|
|
|
43
43
|
leg_trips_by_branch_id = find_all_leg_trips(vendor: @vendor, trip_stop_forms: @branch_stops)
|
|
44
44
|
|
|
45
45
|
ApplicationRecord.transaction do
|
|
46
|
-
@parent_route = load_parent_route!(vendor: @vendor,
|
|
46
|
+
@parent_route = load_parent_route!(vendor: @vendor, trip_form: @trip_form)
|
|
47
47
|
|
|
48
48
|
# Collect offset_days from input (relative: layover days at each branch)
|
|
49
49
|
# Will be stored in parent_trip metadata for reference
|
|
@@ -128,21 +128,11 @@ module SpreeCmCommissioner
|
|
|
128
128
|
.index_by(&:id)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
# Find parent route by route_id
|
|
131
|
+
# Find parent route by route_id
|
|
132
132
|
#
|
|
133
133
|
# @return [Route] Route from origin to destination place
|
|
134
|
-
def load_parent_route!(vendor:,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
origin_place_id = locations[branch_stops.first.location_id.to_i]&.place_id
|
|
138
|
-
destination_place_id = locations[branch_stops.last.location_id.to_i]&.place_id
|
|
139
|
-
route_type = trip_form.route_type.presence || 'bus'
|
|
140
|
-
|
|
141
|
-
vendor.routes.find_by(
|
|
142
|
-
origin_place_id: origin_place_id,
|
|
143
|
-
destination_place_id: destination_place_id,
|
|
144
|
-
route_type: route_type
|
|
145
|
-
) or raise StandardError, "Route not found for #{origin_place_id} → #{destination_place_id}"
|
|
134
|
+
def load_parent_route!(vendor:, trip_form:)
|
|
135
|
+
vendor.routes.find(trip_form.route_id)
|
|
146
136
|
end
|
|
147
137
|
|
|
148
138
|
# Find leg trips and map by stop ID (skip final destination)
|
|
@@ -199,8 +189,7 @@ module SpreeCmCommissioner
|
|
|
199
189
|
allow_booking: true,
|
|
200
190
|
trip_type: :multi_leg,
|
|
201
191
|
allow_seat_selection: false,
|
|
202
|
-
route_type: route_type
|
|
203
|
-
service_origin_id: @parent_route.service_origin_id || @vendor.service_origin_id
|
|
192
|
+
route_type: route_type
|
|
204
193
|
)
|
|
205
194
|
|
|
206
195
|
# Store relative offset_days (layover days) as metadata
|
|
@@ -80,7 +80,6 @@ module SpreeCmCommissioner
|
|
|
80
80
|
vehicle: SpreeCmCommissioner::Vehicle.find_by(id: first_stop.vehicle_id),
|
|
81
81
|
origin_place_id: locations[first_stop.location_id.to_i].place_id,
|
|
82
82
|
destination_place_id: locations[last_stop.location_id.to_i].place_id,
|
|
83
|
-
service_origin_id: route.service_origin_id || vendor.service_origin_id,
|
|
84
83
|
route: route,
|
|
85
84
|
departure_time: first_stop.departure_time,
|
|
86
85
|
duration: trip_form.total_duration_seconds,
|
|
@@ -51,7 +51,8 @@ module SpreeCmCommissioner
|
|
|
51
51
|
return unless attributes.key?(:eliminated)
|
|
52
52
|
return unless attributes[:eliminated]
|
|
53
53
|
|
|
54
|
-
voting_contestant.show_contestant.
|
|
54
|
+
voting_contestant.show_contestant.eliminate
|
|
55
|
+
voting_contestant.show_contestant.save!
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
# Normalizes raw params into a safe attributes hash.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module VotingSessions
|
|
3
|
+
class Finalize
|
|
4
|
+
prepend ::Spree::ServiceModule::Base
|
|
5
|
+
|
|
6
|
+
def call(voting_session:)
|
|
7
|
+
ApplicationRecord.transaction do
|
|
8
|
+
validate_confirmed_ranks!(voting_session)
|
|
9
|
+
advance_confirmed_winners(voting_session) if next_session?(voting_session)
|
|
10
|
+
voting_session.update!(status: :finalized)
|
|
11
|
+
success(voting_session: voting_session)
|
|
12
|
+
end
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
failure(nil, e.message)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def validate_confirmed_ranks!(voting_session)
|
|
20
|
+
if next_session?(voting_session)
|
|
21
|
+
raise I18n.t('voting.errors.no_winners_confirmed') if voting_session.voting_contestants.where.not(confirmed_rank: nil).none?
|
|
22
|
+
else
|
|
23
|
+
unranked = voting_session.voting_contestants.where(eliminated: false, confirmed_rank: nil)
|
|
24
|
+
raise I18n.t('voting.errors.all_contestants_must_be_ranked') if unranked.any?
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Re-syncs advancement on every call — handles first finalize and re-finalize.
|
|
29
|
+
# Contestants without a confirmed_rank get their advanced_to cleared.
|
|
30
|
+
def advance_confirmed_winners(voting_session)
|
|
31
|
+
next_session = resolve_next_session(voting_session)
|
|
32
|
+
|
|
33
|
+
# Reset soft eliminations from previous finalize so re-finalize can re-evaluate them.
|
|
34
|
+
# rubocop:disable Rails/SkipsModelValidations
|
|
35
|
+
voting_session.voting_contestants
|
|
36
|
+
.where(eliminated: true, eliminated_via: :public_vote)
|
|
37
|
+
.update_all(eliminated: false, eliminated_via: nil)
|
|
38
|
+
# rubocop:enable Rails/SkipsModelValidations
|
|
39
|
+
|
|
40
|
+
voting_session.voting_contestants.reload.each do |voting_contestant|
|
|
41
|
+
if voting_contestant.confirmed_rank.present?
|
|
42
|
+
SpreeCmCommissioner::VotingContestants::Advancer.call(
|
|
43
|
+
voting_contestant: voting_contestant,
|
|
44
|
+
attributes: { advanced_to: next_session }
|
|
45
|
+
)
|
|
46
|
+
else
|
|
47
|
+
SpreeCmCommissioner::VotingContestants::Advancer.call(
|
|
48
|
+
voting_contestant: voting_contestant,
|
|
49
|
+
attributes: { eliminated: true, eliminated_via: :public_vote, advanced_to_type: nil, advanced_to_id: nil }
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def next_session?(voting_session)
|
|
56
|
+
resolve_next_session(voting_session).present?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def resolve_next_session(voting_session)
|
|
60
|
+
return @resolved_next_session if defined?(@resolved_next_session)
|
|
61
|
+
|
|
62
|
+
@resolved_next_session = voting_session.next_in_episode || voting_session.episode.next_episode_first_session
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/config/locales/en.yml
CHANGED
|
@@ -767,4 +767,6 @@ en:
|
|
|
767
767
|
rate_limit_ip: "Too many votes from your network. Please try again shortly."
|
|
768
768
|
device_account_limit: "This device has been used by too many accounts."
|
|
769
769
|
vpn_blocked: "Voting is not allowed from VPN or proxy connections."
|
|
770
|
+
no_winners_confirmed: "No winners confirmed"
|
|
771
|
+
all_contestants_must_be_ranked: "All non-eliminated contestants must be ranked"
|
|
770
772
|
|
data/config/locales/km.yml
CHANGED
|
@@ -605,4 +605,8 @@ km:
|
|
|
605
605
|
token_missing: "សញ្ញាណផ្ទៀងផ្ទាត់គឺបាត់"
|
|
606
606
|
verification_failed: "ការផ្ទៀងផ្ទាត់បានបរាជ័យ"
|
|
607
607
|
service_unavailable: "សេវាកម្មពេលនេះមិនមានការផ្ទៀងផ្ទាត់"
|
|
608
|
+
voting:
|
|
609
|
+
errors:
|
|
610
|
+
no_winners_confirmed: "មិនមានអ្នកឈ្នះត្រូវបានបញ្ជាក់"
|
|
611
|
+
all_contestants_must_be_ranked: "អ្នកចូលរួមទាំងអស់ដែលមិនត្រូវបានលុបចោលត្រូវតែមានចំណាត់ថ្នាក់"
|
|
608
612
|
|
data/config/routes.rb
CHANGED
|
@@ -592,7 +592,7 @@ Spree::Core::Engine.add_routes do
|
|
|
592
592
|
resources :assignments, controller: :show_person_assignments, only: %i[index]
|
|
593
593
|
end
|
|
594
594
|
resources :contestants, controller: :show_contestants, only: %i[show]
|
|
595
|
-
resources :
|
|
595
|
+
resources :elimination_sessions, controller: :show_elimination_sessions, only: %i[index]
|
|
596
596
|
resources :free_vote_claims, only: :create
|
|
597
597
|
end
|
|
598
598
|
|
|
@@ -100,5 +100,21 @@ FactoryBot.define do
|
|
|
100
100
|
show_contestant { create(:cm_show_contestant, show: show) }
|
|
101
101
|
voting_session { create(:cm_voting_session, episode: create(:cm_show_episode, event: show), show: show, vendor: show.vendor) }
|
|
102
102
|
show_id { show.id }
|
|
103
|
+
eliminated { false }
|
|
104
|
+
|
|
105
|
+
trait :eliminated do
|
|
106
|
+
eliminated { true }
|
|
107
|
+
eliminated_via { :public_vote }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
trait :eliminated_by_judges do
|
|
111
|
+
eliminated { true }
|
|
112
|
+
eliminated_via { :judges_deadlock }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
trait :eliminated_by_coach do
|
|
116
|
+
eliminated { true }
|
|
117
|
+
eliminated_via { :coach_decision }
|
|
118
|
+
end
|
|
103
119
|
end
|
|
104
120
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_cm_commissioner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.8.
|
|
4
|
+
version: 2.8.2.pre.pre.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: spree
|
|
@@ -1044,7 +1044,6 @@ files:
|
|
|
1044
1044
|
- app/controllers/spree/api/v2/tenant/cms_pages_controller.rb
|
|
1045
1045
|
- app/controllers/spree/api/v2/tenant/customer_notifications_controller.rb
|
|
1046
1046
|
- app/controllers/spree/api/v2/tenant/dynamic_field_options_controller.rb
|
|
1047
|
-
- app/controllers/spree/api/v2/tenant/eliminated_contestants_controller.rb
|
|
1048
1047
|
- app/controllers/spree/api/v2/tenant/free_vote_claims_controller.rb
|
|
1049
1048
|
- app/controllers/spree/api/v2/tenant/guests_controller.rb
|
|
1050
1049
|
- app/controllers/spree/api/v2/tenant/homepage_sections_controller.rb
|
|
@@ -1069,6 +1068,7 @@ files:
|
|
|
1069
1068
|
- app/controllers/spree/api/v2/tenant/routes_controller.rb
|
|
1070
1069
|
- app/controllers/spree/api/v2/tenant/s3_signed_urls_controller.rb
|
|
1071
1070
|
- app/controllers/spree/api/v2/tenant/show_contestants_controller.rb
|
|
1071
|
+
- app/controllers/spree/api/v2/tenant/show_elimination_sessions_controller.rb
|
|
1072
1072
|
- app/controllers/spree/api/v2/tenant/show_people_controller.rb
|
|
1073
1073
|
- app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb
|
|
1074
1074
|
- app/controllers/spree/api/v2/tenant/shows_controller.rb
|
|
@@ -1442,6 +1442,7 @@ files:
|
|
|
1442
1442
|
- app/models/concerns/spree_cm_commissioner/route_order_countable.rb
|
|
1443
1443
|
- app/models/concerns/spree_cm_commissioner/route_type.rb
|
|
1444
1444
|
- app/models/concerns/spree_cm_commissioner/service_calendar_type.rb
|
|
1445
|
+
- app/models/concerns/spree_cm_commissioner/service_origin.rb
|
|
1445
1446
|
- app/models/concerns/spree_cm_commissioner/service_recommendations.rb
|
|
1446
1447
|
- app/models/concerns/spree_cm_commissioner/service_type.rb
|
|
1447
1448
|
- app/models/concerns/spree_cm_commissioner/store_metadata.rb
|
|
@@ -2285,6 +2286,7 @@ files:
|
|
|
2285
2286
|
- app/services/spree_cm_commissioner/voting_credits/credit_calculator.rb
|
|
2286
2287
|
- app/services/spree_cm_commissioner/voting_credits/de_allocate.rb
|
|
2287
2288
|
- app/services/spree_cm_commissioner/voting_leaderboards/calculate_score.rb
|
|
2289
|
+
- app/services/spree_cm_commissioner/voting_sessions/finalize.rb
|
|
2288
2290
|
- app/services/spree_cm_commissioner/waiting_room_system_metadata_fetcher.rb
|
|
2289
2291
|
- app/services/spree_cm_commissioner/waiting_room_system_metadata_setter.rb
|
|
2290
2292
|
- app/services/spree_cm_commissioner/webhooks/subscribers/handle_request_decorator.rb
|
|
@@ -3271,6 +3273,7 @@ files:
|
|
|
3271
3273
|
- db/migrate/20260520000001_add_scoring_model_to_cm_voting_sessions.rb
|
|
3272
3274
|
- db/migrate/20260520000001_optimize_cm_votes_indexes.rb
|
|
3273
3275
|
- db/migrate/20260525042257_add_vote_number_to_cm_voting_contestants.rb
|
|
3276
|
+
- db/migrate/20260527035430_add_confirmed_rank_to_cm_voting_contestants.rb
|
|
3274
3277
|
- db/migrate/20260527062005_add_eliminated_at_to_cm_show_contestants.rb
|
|
3275
3278
|
- docker-compose.yml
|
|
3276
3279
|
- docs/api/scoped-access-token-endpoints.md
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Api
|
|
3
|
-
module V2
|
|
4
|
-
module Tenant
|
|
5
|
-
class EliminatedContestantsController < ShowContestantsController
|
|
6
|
-
private
|
|
7
|
-
|
|
8
|
-
def scope
|
|
9
|
-
super.eliminated
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def collection_serializer
|
|
13
|
-
Spree::V2::Tenant::ShowContestantSerializer
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|