spree_cm_commissioner 2.8.16 → 2.9.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.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/Gemfile.lock +1 -1
- data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +2 -0
- data/app/controllers/spree/admin/homepage_section_controller.rb +4 -1
- data/app/controllers/spree/admin/taxons_controller_decorator.rb +19 -0
- data/app/controllers/spree/api/v2/storefront/homepage_sections_controller.rb +1 -0
- data/app/controllers/spree/api/v2/storefront/preview_products_controller.rb +48 -0
- data/app/controllers/spree/api/v2/storefront/preview_sections_controller.rb +27 -0
- data/app/controllers/spree/api/v2/storefront/preview_taxons_controller.rb +18 -0
- data/app/controllers/spree/api/v2/storefront/products_controller_decorator.rb +15 -0
- data/app/controllers/spree/api/v2/storefront/taxons_controller_decorator.rb +15 -0
- data/app/controllers/spree/api/v2/tenant/ad_campaigns_controller.rb +25 -0
- data/app/controllers/spree/api/v2/tenant/base_controller.rb +4 -0
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +38 -0
- data/app/controllers/spree/api/v2/tenant/homepage_sections_controller.rb +1 -0
- data/app/controllers/spree/api/v2/tenant/preview_products_controller.rb +47 -0
- data/app/controllers/spree/api/v2/tenant/preview_sections_controller.rb +26 -0
- data/app/controllers/spree/api/v2/tenant/preview_shows_controller.rb +19 -0
- data/app/controllers/spree/api/v2/tenant/preview_taxons_controller.rb +19 -0
- data/app/controllers/spree/api/v2/tenant/products_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +52 -0
- data/app/controllers/spree/api/v2/tenant/show_elimination_sessions_controller.rb +57 -0
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +49 -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 +36 -0
- data/app/controllers/spree/api/v2/tenant/taxons_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/vote_packages_controller.rb +81 -0
- data/app/controllers/spree/api/v2/tenant/votes_controller.rb +94 -0
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +43 -0
- data/app/controllers/spree/api/v2/tenant/voting_credit_transactions_controller.rb +41 -0
- data/app/controllers/spree/api/v2/tenant/voting_credits_controller.rb +31 -0
- data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +19 -0
- data/app/finders/spree_cm_commissioner/events/find_matches.rb +1 -0
- data/app/helpers/spree_cm_commissioner/admin/homepage_segment_helper.rb +2 -0
- data/app/jobs/spree_cm_commissioner/show_contestants/import_job.rb +9 -0
- data/app/jobs/spree_cm_commissioner/vote_fraud_event_job.rb +9 -0
- 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 +11 -1
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/store_metadata.rb +3 -0
- data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +3 -1
- data/app/models/concerns/spree_cm_commissioner/voting_session_live_stream_concern.rb +41 -0
- data/app/models/spree_cm_commissioner/claim.rb +27 -0
- data/app/models/spree_cm_commissioner/import.rb +1 -1
- data/app/models/spree_cm_commissioner/imports/import_contestant.rb +7 -0
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +26 -0
- data/app/models/spree_cm_commissioner/maintenance_tasks/voting_session.rb +36 -0
- data/app/models/spree_cm_commissioner/preview_role.rb +8 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +52 -0
- data/app/models/spree_cm_commissioner/role_decorator.rb +4 -1
- data/app/models/spree_cm_commissioner/role_user_decorator.rb +8 -0
- data/app/models/spree_cm_commissioner/show.rb +171 -0
- data/app/models/spree_cm_commissioner/show_contestant.rb +39 -0
- data/app/models/spree_cm_commissioner/show_contestant_image.rb +11 -0
- data/app/models/spree_cm_commissioner/show_contestant_video.rb +15 -0
- data/app/models/spree_cm_commissioner/show_episode.rb +122 -0
- data/app/models/spree_cm_commissioner/show_person.rb +15 -0
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +21 -0
- data/app/models/spree_cm_commissioner/show_person_image.rb +11 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +23 -0
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +19 -1
- data/app/models/spree_cm_commissioner/tenant.rb +9 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +5 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/variant_options.rb +4 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +5 -0
- data/app/models/spree_cm_commissioner/vote.rb +16 -0
- data/app/models/spree_cm_commissioner/vote_fraud_event.rb +20 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +100 -0
- data/app/models/spree_cm_commissioner/voting_credit.rb +84 -0
- data/app/models/spree_cm_commissioner/voting_credit_transaction.rb +55 -0
- data/app/models/spree_cm_commissioner/voting_session.rb +217 -0
- data/app/models/spree_cm_commissioner/voting_session_stat.rb +8 -0
- data/app/overrides/spree/admin/products/_form/preview_checkbox.html.erb.deface +9 -0
- data/app/overrides/spree/admin/taxons/_form/preview_checkbox.html.erb.deface +7 -0
- data/app/serializers/spree/v2/storefront/homepage_section_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/storefront/role_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/tenant/ad_campaign_serializer.rb +13 -0
- data/app/serializers/spree/v2/tenant/advertisement_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/homepage_section_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/role_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +21 -0
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +20 -0
- data/app/serializers/spree/v2/tenant/show_parent_serializer.rb +13 -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 +23 -0
- data/app/serializers/spree/v2/tenant/video_serializer.rb +9 -0
- data/app/serializers/spree/v2/tenant/vote_package_serializer.rb +15 -0
- data/app/serializers/spree/v2/tenant/vote_serializer.rb +14 -0
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +23 -0
- data/app/serializers/spree/v2/tenant/voting_credit_serializer.rb +10 -0
- data/app/serializers/spree/v2/tenant/voting_credit_transaction_serializer.rb +14 -0
- data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +21 -0
- data/app/services/spree_cm_commissioner/api_caches/invalidate.rb +12 -0
- data/app/services/spree_cm_commissioner/fraud_check.rb +308 -0
- data/app/services/spree_cm_commissioner/imports/contestants/create.rb +153 -0
- data/app/services/spree_cm_commissioner/show_contestants/normalize_video_highlights.rb +57 -0
- data/app/services/spree_cm_commissioner/show_persons/contestant_assigner.rb +51 -0
- data/app/services/spree_cm_commissioner/url_embed/youtube_embed.rb +44 -0
- data/app/services/spree_cm_commissioner/vote_counters/audit_counters.rb +43 -0
- data/app/services/spree_cm_commissioner/vote_counters/base.rb +31 -0
- data/app/services/spree_cm_commissioner/vote_counters/increment.rb +44 -0
- data/app/services/spree_cm_commissioner/vote_counters/per_contestant_counter.rb +68 -0
- data/app/services/spree_cm_commissioner/vote_counters/rebuild_from_db.rb +70 -0
- data/app/services/spree_cm_commissioner/vote_counters/snapshot_to_db.rb +113 -0
- data/app/services/spree_cm_commissioner/vote_credit_deductor.rb +68 -0
- data/app/services/spree_cm_commissioner/vote_package/create.rb +150 -0
- data/app/services/spree_cm_commissioner/vote_package/update.rb +97 -0
- data/app/services/spree_cm_commissioner/vote_processor.rb +144 -0
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +335 -0
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +40 -0
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +109 -0
- data/app/services/spree_cm_commissioner/voting_credits/admin_grant.rb +37 -0
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +123 -0
- data/app/services/spree_cm_commissioner/voting_credits/claimable_scope_resolver.rb +64 -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 +87 -0
- data/app/services/spree_cm_commissioner/voting_leaderboards/calculate_score.rb +67 -0
- data/app/services/spree_cm_commissioner/voting_leaderboards/combined_result.rb +190 -0
- data/app/services/spree_cm_commissioner/voting_sessions/finalize.rb +105 -0
- data/app/views/spree/admin/homepage_section/_form.html.erb +5 -0
- data/config/initializers/spree_permitted_attributes.rb +8 -0
- data/config/locales/en.yml +53 -5
- data/config/locales/km.yml +38 -1
- data/config/routes.rb +30 -0
- 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/20260330160000_create_cm_votes.rb +25 -0
- data/db/migrate/20260401072500_add_advanced_from_to_cm_voting_contestants.rb +7 -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/db/migrate/20260403070000_add_name_to_cm_voting_sessions.rb +5 -0
- data/db/migrate/20260406000001_add_vendor_id_to_voting_tables.rb +6 -0
- data/db/migrate/20260406000001_rename_votes_remaining_to_amount_in_cm_voting_credits.rb +11 -0
- data/db/migrate/20260408085255_add_show_id_and_vendor_id_to_cm_voting_sessions.rb +9 -0
- data/db/migrate/20260420000001_rename_type_to_credit_type_in_cm_voting_credits.rb +25 -0
- data/db/migrate/20260422000001_create_cm_vote_fraud_events.rb +23 -0
- data/db/migrate/20260423000001_add_preview_to_taxons_products_and_sections.rb +11 -0
- data/db/migrate/20260423000002_create_preview_roles.rb +24 -0
- data/db/migrate/20260515120000_add_public_metadata_to_cm_voting_sessions.rb +5 -0
- data/db/migrate/20260518090920_add_unique_voter_count_to_voting_contestants.rb +5 -0
- data/db/migrate/20260518094322_create_cm_voting_session_stats.rb +17 -0
- data/db/migrate/20260520000001_add_scoring_model_to_cm_voting_sessions.rb +5 -0
- data/db/migrate/20260520000001_optimize_cm_votes_indexes.rb +22 -0
- data/db/migrate/20260525042257_add_vote_number_to_cm_voting_contestants.rb +18 -0
- data/db/migrate/20260527035430_add_confirmed_rank_to_cm_voting_contestants.rb +5 -0
- data/db/migrate/20260527062005_add_eliminated_at_to_cm_show_contestants.rb +5 -0
- data/db/migrate/20260603063652_add_parent_to_voting_sessions.rb +9 -0
- data/db/migrate/20260603090000_add_session_type_to_cm_voting_sessions.rb +6 -0
- data/db/migrate/20260608000000_add_display_to_cm_voting_sessions.rb +5 -0
- data/db/migrate/20260623082233_create_cm_claims.rb +14 -0
- data/db/migrate/20260624175658_add_unique_index_to_cm_claims.rb +11 -0
- data/docs/sql/jsonb_query_guide.md +57 -0
- data/lib/spree_cm_commissioner/test_helper/factories/claim_factory.rb +14 -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 +120 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vote_credit_factory.rb +37 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vote_factory.rb +28 -0
- data/lib/spree_cm_commissioner/test_helper/factories/voting_credit_transaction_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/voting_session_factory.rb +11 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +7 -1
- data/spree_cm_commissioner.gemspec +1 -1
- metadata +134 -2
|
@@ -0,0 +1,36 @@
|
|
|
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, preview: false)
|
|
23
|
+
.includes(:parent, :app_banner, show_people: :show_person_images,
|
|
24
|
+
episodes: :voting_sessions, seasons: { episodes: :voting_sessions }
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# override
|
|
29
|
+
def resource_serializer
|
|
30
|
+
Spree::V2::Tenant::ShowSerializer
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class VotePackagesController < BaseController
|
|
6
|
+
before_action :require_spree_current_user, only: :claim_status
|
|
7
|
+
before_action :require_votable_params, only: :index
|
|
8
|
+
|
|
9
|
+
# Overrided
|
|
10
|
+
def index
|
|
11
|
+
render_serialized_payload { serialize_collection(sorted_collection) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def claim_status
|
|
15
|
+
product = current_season.vote_packages.find(params[:id])
|
|
16
|
+
|
|
17
|
+
result = SpreeCmCommissioner::VotingCredits::ClaimableScopeResolver.new(
|
|
18
|
+
product: product,
|
|
19
|
+
voting_session_id: params[:voting_session_id]
|
|
20
|
+
).call
|
|
21
|
+
|
|
22
|
+
return render_error_payload(result.error, 422) if result.failure?
|
|
23
|
+
|
|
24
|
+
scope = result.value
|
|
25
|
+
|
|
26
|
+
claimed = SpreeCmCommissioner::Claim.free_claimed?(
|
|
27
|
+
user_id: spree_current_user.id,
|
|
28
|
+
product_id: product.id,
|
|
29
|
+
claimable_id: scope[:claimable_id],
|
|
30
|
+
claimable_type: scope[:claimable_type]
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
render_serialized_payload { { claimed: claimed }.merge(scope) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# Overrided
|
|
39
|
+
def collection
|
|
40
|
+
current_vendor.vote_packages
|
|
41
|
+
.where(status: :active, event_id: current_season.id)
|
|
42
|
+
.by_votable(params[:votable_type], params[:votable_id])
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Overrided
|
|
46
|
+
def sorted_collection
|
|
47
|
+
packages = current_season.allow_free_vote? ? collection.to_a : collection.reject(&:free?)
|
|
48
|
+
packages.sort_by { |p| [p.free? ? 0 : 1, p.vote_credits.to_i] }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Overrided
|
|
52
|
+
def serialize_collection(collection)
|
|
53
|
+
collection_serializer.new(
|
|
54
|
+
collection,
|
|
55
|
+
include: resource_includes
|
|
56
|
+
).serializable_hash
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Overrided
|
|
60
|
+
def collection_serializer
|
|
61
|
+
Spree::V2::Tenant::VotePackageSerializer
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def current_season
|
|
65
|
+
@current_season ||= current_vendor.shows
|
|
66
|
+
.where.not(parent_id: nil)
|
|
67
|
+
.find_by!(slug: params[:show_id])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# We need to require votable_type and votable_id params because we are filtering VotePackages by ShowEpisode.
|
|
71
|
+
# VotePackage Metadata(votable_type and votable_id) are important when allocating voting credits to users.
|
|
72
|
+
def require_votable_params
|
|
73
|
+
return if params[:votable_type].present? && params[:votable_id].present?
|
|
74
|
+
|
|
75
|
+
render_error_payload('votable_type and votable_id are required', 422)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class VotesController < BaseController
|
|
6
|
+
before_action :require_spree_current_user
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
render_serialized_payload do
|
|
10
|
+
serialize_collection(collection)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create
|
|
15
|
+
voting_session = current_vendor.voting_sessions.find(params[:voting_session_id])
|
|
16
|
+
contestant = voting_session.voting_contestants.find(params[:contestant_id])
|
|
17
|
+
|
|
18
|
+
processor_params = vote_params.merge(
|
|
19
|
+
device_fingerprint: device_params[:fingerprint],
|
|
20
|
+
voter_identifier: device_params[:identifier],
|
|
21
|
+
public_metadata: params[:public_metadata] || {},
|
|
22
|
+
tenant_id: MultiTenant.current_tenant_id,
|
|
23
|
+
vendor_id: current_vendor.id
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
result = SpreeCmCommissioner::VoteProcessor.call(
|
|
27
|
+
voting_session: voting_session,
|
|
28
|
+
contestant: contestant,
|
|
29
|
+
user: spree_current_user,
|
|
30
|
+
params: processor_params,
|
|
31
|
+
request: request
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if result.success?
|
|
35
|
+
render_serialized_payload(201) { serialize_resource(result.value) }
|
|
36
|
+
else
|
|
37
|
+
render_error_payload(result.error)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def collection
|
|
44
|
+
@collection ||= scope.page(params[:page])
|
|
45
|
+
.per(params[:per_page])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def scope
|
|
49
|
+
MultiTenant.with(@tenant) do
|
|
50
|
+
scope = spree_current_user.votes
|
|
51
|
+
.includes(:contestant, :voting_session, :vote_credit)
|
|
52
|
+
.order(created_at: :desc)
|
|
53
|
+
|
|
54
|
+
scope = scope.for_session(params[:voting_session_id]) if params[:voting_session_id]
|
|
55
|
+
scope
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def model_class
|
|
60
|
+
SpreeCmCommissioner::Vote
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def resource_serializer
|
|
64
|
+
Spree::V2::Tenant::VoteSerializer
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def collection_serializer
|
|
68
|
+
Spree::V2::Tenant::VoteSerializer
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# {
|
|
72
|
+
# "contestant_id": 1,
|
|
73
|
+
# "vote": {
|
|
74
|
+
# "quantity": 1,
|
|
75
|
+
# "channel": "mobile"
|
|
76
|
+
# },
|
|
77
|
+
# "device": {
|
|
78
|
+
# "fingerprint": "fp-xyz",
|
|
79
|
+
# "identifier": "device-abc",
|
|
80
|
+
# "platform": "android"
|
|
81
|
+
# }
|
|
82
|
+
# }
|
|
83
|
+
def vote_params
|
|
84
|
+
params.require(:vote).permit(:quantity, :channel)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def device_params
|
|
88
|
+
params.require(:device).permit(:fingerprint, :identifier, :platform)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
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(:voting_session, :show_contestant,
|
|
13
|
+
:show_contestant_images, :show_contestant_videos,
|
|
14
|
+
:advanced_to, :advanced_from
|
|
15
|
+
)
|
|
16
|
+
.order(:id)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# override
|
|
20
|
+
def collection_serializer
|
|
21
|
+
Spree::V2::Tenant::VotingContestantSerializer
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# override
|
|
27
|
+
def model_class
|
|
28
|
+
SpreeCmCommissioner::VotingSession
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# override
|
|
32
|
+
def scope
|
|
33
|
+
current_vendor.voting_sessions.includes(:episode)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def load_voting_session
|
|
37
|
+
@voting_session = scope.find(params[:voting_session_id])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class VotingCreditTransactionsController < BaseController
|
|
6
|
+
before_action :require_spree_current_user
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
render_serialized_payload do
|
|
10
|
+
serialize_collection(collection)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def collection
|
|
17
|
+
@collection ||= scope.page(params[:page])
|
|
18
|
+
.per(params[:per_page])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scope
|
|
22
|
+
scope = spree_current_user.voting_credit_transactions
|
|
23
|
+
.includes(:vote_credit, :originator)
|
|
24
|
+
.order(created_at: :desc)
|
|
25
|
+
|
|
26
|
+
scope = scope.by_action(params[:actions].split(',')) if params[:actions].present?
|
|
27
|
+
scope
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def model_class
|
|
31
|
+
SpreeCmCommissioner::VotingCreditTransaction
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def collection_serializer
|
|
35
|
+
Spree::V2::Tenant::VotingCreditTransactionSerializer
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class VotingCreditsController < BaseController
|
|
6
|
+
before_action :require_spree_current_user
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
render_serialized_payload do
|
|
10
|
+
serialize_resource(voting_credit)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def voting_credit
|
|
17
|
+
spree_current_user.voting_credits.active.eligible(load_voting_session).first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load_voting_session
|
|
21
|
+
@voting_session ||= SpreeCmCommissioner::VotingSession.find(params[:voting_session_id])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def resource_serializer
|
|
25
|
+
Spree::V2::Tenant::VotingCreditSerializer
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -6,6 +6,7 @@ module SpreeCmCommissioner
|
|
|
6
6
|
base.around_action :set_writing_role, only: %i[index]
|
|
7
7
|
base.after_action :set_tenant_after_update, only: %i[update]
|
|
8
8
|
base.before_action :merge_industry_taxons_into_taxons, only: [:update]
|
|
9
|
+
base.before_action :normalize_sti_product_params, only: %i[create update]
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# Override
|
|
@@ -51,6 +52,24 @@ module SpreeCmCommissioner
|
|
|
51
52
|
|
|
52
53
|
protected
|
|
53
54
|
|
|
55
|
+
# Some admin forms submit STI records under their class key while
|
|
56
|
+
# Spree update reads :product. Merge both into :product so all edited
|
|
57
|
+
# fields are persisted for STI product subclasses.
|
|
58
|
+
def normalize_sti_product_params
|
|
59
|
+
return unless @product
|
|
60
|
+
|
|
61
|
+
sti_key = @product.class.model_name.param_key.to_sym
|
|
62
|
+
sti_params = params[sti_key]
|
|
63
|
+
return unless sti_params.is_a?(::ActionController::Parameters)
|
|
64
|
+
|
|
65
|
+
base_params = params[:product]
|
|
66
|
+
base_hash = base_params.is_a?(::ActionController::Parameters) ? base_params.to_unsafe_h : {}
|
|
67
|
+
sti_hash = sti_params.to_unsafe_h
|
|
68
|
+
merged_params = ::ActionController::Parameters.new(base_hash.merge(sti_hash))
|
|
69
|
+
|
|
70
|
+
params[:product] = merged_params
|
|
71
|
+
end
|
|
72
|
+
|
|
54
73
|
def merge_industry_taxons_into_taxons
|
|
55
74
|
return if params[:product].blank?
|
|
56
75
|
|
|
@@ -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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Make sure to put this concern below other concern or methods that generating additional order info like guests, seat number, etc.
|
|
2
2
|
# This will ensure that when each notification is sent with neccessary data.
|
|
3
3
|
module SpreeCmCommissioner
|
|
4
|
-
module OrderStateMachine
|
|
4
|
+
module OrderStateMachine # rubocop:disable Metrics/ModuleLength
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
included do # rubocop:disable Metrics/BlockLength
|
|
@@ -26,8 +26,10 @@ module SpreeCmCommissioner
|
|
|
26
26
|
|
|
27
27
|
state_machine.after_transition to: :canceled, do: :precalculate_conversion
|
|
28
28
|
state_machine.after_transition to: :canceled, do: :restock_inventory!
|
|
29
|
+
state_machine.after_transition to: :canceled, do: :de_allocate_resources
|
|
29
30
|
|
|
30
31
|
state_machine.after_transition to: :complete, do: :increment_route_fulfilled_order_count
|
|
32
|
+
state_machine.after_transition to: :complete, do: :allocate_resources
|
|
31
33
|
state_machine.after_transition to: :complete, do: :run_order_complete_alerts
|
|
32
34
|
|
|
33
35
|
scope :accepted, -> { where(request_state: 'accepted') }
|
|
@@ -360,5 +362,13 @@ module SpreeCmCommissioner
|
|
|
360
362
|
factory = OrderTelegramMessageFactory.new(title: title, order: self)
|
|
361
363
|
TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
|
|
362
364
|
end
|
|
365
|
+
|
|
366
|
+
def allocate_resources
|
|
367
|
+
SpreeCmCommissioner::VotingCreditAllocationJob.perform_later(order_id: id)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def de_allocate_resources
|
|
371
|
+
SpreeCmCommissioner::VotingCreditDeAllocationJob.perform_later(order_id: id)
|
|
372
|
+
end
|
|
363
373
|
end
|
|
364
374
|
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 show_episode vote_package advertisement].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
|
|
|
@@ -49,6 +49,9 @@ module SpreeCmCommissioner
|
|
|
49
49
|
def self.load(json)
|
|
50
50
|
return {} if json.blank?
|
|
51
51
|
|
|
52
|
+
# jsonb columns are already parsed to a Hash by ActiveRecord — return as-is.
|
|
53
|
+
return json if json.is_a?(Hash) || json.is_a?(Array)
|
|
54
|
+
|
|
52
55
|
begin
|
|
53
56
|
JSON.parse(json)
|
|
54
57
|
rescue JSON::ParserError, TypeError
|
|
@@ -3,7 +3,9 @@ module SpreeCmCommissioner
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
|
-
enum kind: { category: 0, cms: 1, event: 2, occupation: 3, nationality: 4, organization: 5, transit: 6, industry: 7, agency_category: 8
|
|
6
|
+
enum kind: { category: 0, cms: 1, event: 2, occupation: 3, nationality: 4, organization: 5, transit: 6, industry: 7, agency_category: 8,
|
|
7
|
+
ads: 9
|
|
8
|
+
}
|
|
7
9
|
end
|
|
8
10
|
end
|
|
9
11
|
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module VotingSessionLiveStreamConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
store_public_metadata :live_stream_url, :string
|
|
7
|
+
store_public_metadata :live_stream_enabled, :boolean
|
|
8
|
+
store_public_metadata :live_stream_thumbnail, :string
|
|
9
|
+
store_public_metadata :live_stream_title, :string
|
|
10
|
+
store_public_metadata :live_stream_description, :text
|
|
11
|
+
|
|
12
|
+
validate :validate_live_stream_url, if: :live_stream_url_changed?
|
|
13
|
+
before_save :update_live_stream_thumbnail
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def embedded_live_stream_url
|
|
17
|
+
return nil if live_stream_url.blank?
|
|
18
|
+
|
|
19
|
+
result = SpreeCmCommissioner::UrlEmbed::YoutubeEmbed.call(url: live_stream_url)
|
|
20
|
+
result.success? ? result.value : nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def validate_live_stream_url
|
|
26
|
+
return if live_stream_url.blank?
|
|
27
|
+
|
|
28
|
+
result = SpreeCmCommissioner::UrlEmbed::YoutubeEmbed.call(url: live_stream_url)
|
|
29
|
+
return if result.success?
|
|
30
|
+
|
|
31
|
+
errors.add(:live_stream_url, result.error)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def update_live_stream_thumbnail
|
|
35
|
+
return if live_stream_url.blank?
|
|
36
|
+
|
|
37
|
+
video_id = SpreeCmCommissioner::UrlEmbed::YoutubeEmbed.extract_video_id(live_stream_url)
|
|
38
|
+
self.live_stream_thumbnail = "https://img.youtube.com/vi/#{video_id}/hqdefault.jpg" if video_id
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class Claim < SpreeCmCommissioner::Base
|
|
3
|
+
belongs_to :user, class_name: 'Spree::User'
|
|
4
|
+
belongs_to :product, class_name: 'Spree::Product'
|
|
5
|
+
belongs_to :claimable, polymorphic: true
|
|
6
|
+
|
|
7
|
+
validates :tenant_id, presence: true
|
|
8
|
+
validates :user_id,
|
|
9
|
+
uniqueness: {
|
|
10
|
+
scope: %i[product_id claimable_id claimable_type],
|
|
11
|
+
conditions: -> { where(free: true) },
|
|
12
|
+
message: 'has already been claimed for this scope' # rubocop:disable Rails/I18nLocaleTexts
|
|
13
|
+
},
|
|
14
|
+
if: :free?
|
|
15
|
+
|
|
16
|
+
scope :free_claims, -> { where(free: true) }
|
|
17
|
+
|
|
18
|
+
def self.free_claimed?(user_id:, product_id:, claimable_id:, claimable_type:)
|
|
19
|
+
free_claims.exists?(
|
|
20
|
+
user_id: user_id,
|
|
21
|
+
product_id: product_id,
|
|
22
|
+
claimable_id: claimable_id,
|
|
23
|
+
claimable_type: claimable_type
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -3,7 +3,7 @@ module SpreeCmCommissioner
|
|
|
3
3
|
extend FriendlyId
|
|
4
4
|
|
|
5
5
|
enum :status, { :queue => 0, :progress => 1, :done => 2, :failed => 3, :canceling => 4, :canceled => 5 }
|
|
6
|
-
enum :import_type, { :new_order => 0, :existing_order => 1, :aba_payment_reference => 2 }
|
|
6
|
+
enum :import_type, { :new_order => 0, :existing_order => 1, :aba_payment_reference => 2, :contestant_import => 3 }
|
|
7
7
|
has_one_attached :imported_file
|
|
8
8
|
friendly_id :name, use: :slugged
|
|
9
9
|
|
|
@@ -121,6 +121,7 @@ module SpreeCmCommissioner
|
|
|
121
121
|
def update_price
|
|
122
122
|
# Skip price updates for ticket transfer orders to preserve custom transfer pricing
|
|
123
123
|
return if order&.ticket_transfer?
|
|
124
|
+
return self.price = 0 if eligible_for_free_claim?
|
|
124
125
|
|
|
125
126
|
base_price = variant.price_in(order.currency)
|
|
126
127
|
self.price = if permanent_stock?
|
|
@@ -276,6 +277,17 @@ module SpreeCmCommissioner
|
|
|
276
277
|
SpreeCmCommissioner::OrderJwtToken.encode(payload, order.token)
|
|
277
278
|
end
|
|
278
279
|
|
|
280
|
+
# Returns { claimable_id:, claimable_type: } or nil if unresolvable.
|
|
281
|
+
# Scope is determined by the Show's free_vote_limit_type from voting_config.
|
|
282
|
+
def claim_scope
|
|
283
|
+
result = SpreeCmCommissioner::VotingCredits::ClaimableScopeResolver.new(
|
|
284
|
+
product: product,
|
|
285
|
+
voting_session_id: public_metadata&.dig('voting_session_id')
|
|
286
|
+
).call
|
|
287
|
+
|
|
288
|
+
result.success? ? result.value : nil
|
|
289
|
+
end
|
|
290
|
+
|
|
279
291
|
private
|
|
280
292
|
|
|
281
293
|
def ensure_not_exceed_max_quantity_per_order
|
|
@@ -304,6 +316,20 @@ module SpreeCmCommissioner
|
|
|
304
316
|
order.subscription.variant.post_paid?
|
|
305
317
|
end
|
|
306
318
|
|
|
319
|
+
def eligible_for_free_claim?
|
|
320
|
+
return false if order&.user_id.blank?
|
|
321
|
+
|
|
322
|
+
scope = claim_scope
|
|
323
|
+
return false if scope.nil?
|
|
324
|
+
|
|
325
|
+
!SpreeCmCommissioner::Claim.free_claimed?(
|
|
326
|
+
user_id: order.user_id,
|
|
327
|
+
product_id: product_id,
|
|
328
|
+
claimable_id: scope[:claimable_id],
|
|
329
|
+
claimable_type: scope[:claimable_type]
|
|
330
|
+
)
|
|
331
|
+
end
|
|
332
|
+
|
|
307
333
|
def due_days
|
|
308
334
|
variant = order.subscription.variant
|
|
309
335
|
day = variant.due_date
|