spree_cm_commissioner 2.8.4.pre.pre3 → 2.8.4.pre.pre4
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/.env.example +5 -0
- data/.github/workflows/test_and_build_gem.yml +1 -2
- data/.gitignore +0 -6
- data/Gemfile.lock +1 -1
- data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +0 -2
- data/app/controllers/spree/admin/homepage_section_controller.rb +1 -4
- data/app/controllers/spree/admin/taxons_controller_decorator.rb +0 -19
- data/app/controllers/spree/api/v2/storefront/homepage_sections_controller.rb +0 -1
- data/app/controllers/spree/api/v2/tenant/base_controller.rb +0 -4
- data/app/controllers/spree/api/v2/tenant/homepage_sections_controller.rb +0 -1
- data/app/controllers/spree/api/v2/tenant/products_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/taxons_controller.rb +1 -1
- data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +0 -19
- data/app/finders/spree_cm_commissioner/events/find_matches.rb +0 -1
- data/app/helpers/spree_cm_commissioner/admin/homepage_segment_helper.rb +0 -2
- data/app/interactors/spree_cm_commissioner/payment_incomplete_notification_sender.rb +25 -0
- data/app/interactors/spree_cm_commissioner/release_inventory_item_notification_sender.rb +24 -0
- data/app/interactors/spree_cm_commissioner/waiting_room_session_creator.rb +23 -6
- data/app/jobs/spree_cm_commissioner/payment_incomplete_notification_job.rb +12 -0
- data/app/jobs/spree_cm_commissioner/waiting_room/stamp_queue_positions_job.rb +21 -2
- data/app/models/concerns/spree_cm_commissioner/homepage_section_bitwise.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -10
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -3
- data/app/models/spree_cm_commissioner/import.rb +1 -1
- data/app/models/spree_cm_commissioner/notification.rb +1 -0
- data/app/models/spree_cm_commissioner/payment_decorator.rb +10 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +0 -52
- data/app/models/spree_cm_commissioner/role_decorator.rb +1 -4
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -23
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +1 -19
- data/app/models/spree_cm_commissioner/tenant.rb +0 -9
- data/app/models/spree_cm_commissioner/user_decorator.rb +0 -17
- data/app/models/spree_cm_commissioner/variant_decorator.rb +0 -4
- data/app/models/spree_cm_commissioner/variant_options.rb +0 -4
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +0 -5
- data/app/notifications/spree_cm_commissioner/order_general_notification.rb +15 -0
- data/app/serializers/spree/v2/storefront/homepage_section_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +1 -2
- data/app/serializers/spree/v2/storefront/role_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +1 -2
- 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/services/spree_cm_commissioner/api_caches/invalidate.rb +0 -12
- data/app/services/spree_cm_commissioner/inventory_holds/release.rb +16 -0
- data/app/services/spree_cm_commissioner/waiting_room_system_metadata_fetcher.rb +9 -7
- data/app/services/spree_cm_commissioner/waiting_room_system_metadata_setter.rb +16 -6
- data/app/views/spree/admin/homepage_section/_form.html.erb +0 -5
- data/config/initializers/spree_permitted_attributes.rb +0 -8
- data/config/locales/en.yml +9 -45
- data/config/locales/km.yml +7 -32
- data/config/routes.rb +0 -29
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +1 -7
- data/spree_cm_commissioner.gemspec +1 -1
- metadata +5 -130
- data/app/controllers/spree/api/v2/storefront/preview_products_controller.rb +0 -48
- data/app/controllers/spree/api/v2/storefront/preview_sections_controller.rb +0 -27
- data/app/controllers/spree/api/v2/storefront/preview_taxons_controller.rb +0 -18
- data/app/controllers/spree/api/v2/storefront/products_controller_decorator.rb +0 -15
- data/app/controllers/spree/api/v2/storefront/taxons_controller_decorator.rb +0 -15
- data/app/controllers/spree/api/v2/tenant/ad_campaigns_controller.rb +0 -25
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +0 -38
- data/app/controllers/spree/api/v2/tenant/free_vote_claim_controller.rb +0 -58
- data/app/controllers/spree/api/v2/tenant/preview_products_controller.rb +0 -47
- data/app/controllers/spree/api/v2/tenant/preview_sections_controller.rb +0 -26
- data/app/controllers/spree/api/v2/tenant/preview_shows_controller.rb +0 -19
- data/app/controllers/spree/api/v2/tenant/preview_taxons_controller.rb +0 -19
- data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +0 -52
- data/app/controllers/spree/api/v2/tenant/show_elimination_sessions_controller.rb +0 -57
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +0 -49
- data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +0 -36
- data/app/controllers/spree/api/v2/tenant/shows_controller.rb +0 -36
- data/app/controllers/spree/api/v2/tenant/vote_packages_controller.rb +0 -33
- data/app/controllers/spree/api/v2/tenant/votes_controller.rb +0 -94
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +0 -43
- data/app/controllers/spree/api/v2/tenant/voting_credit_transactions_controller.rb +0 -41
- data/app/controllers/spree/api/v2/tenant/voting_credits_controller.rb +0 -31
- data/app/jobs/spree_cm_commissioner/show_contestants/import_job.rb +0 -9
- data/app/jobs/spree_cm_commissioner/vote_fraud_event_job.rb +0 -9
- data/app/jobs/spree_cm_commissioner/voting_credit_allocation_job.rb +0 -10
- data/app/jobs/spree_cm_commissioner/voting_credit_de_allocation_job.rb +0 -10
- data/app/models/concerns/spree_cm_commissioner/voting_session_live_stream_concern.rb +0 -41
- data/app/models/spree_cm_commissioner/imports/import_contestant.rb +0 -7
- data/app/models/spree_cm_commissioner/maintenance_tasks/voting_session.rb +0 -36
- data/app/models/spree_cm_commissioner/preview_role.rb +0 -8
- data/app/models/spree_cm_commissioner/role_user_decorator.rb +0 -8
- data/app/models/spree_cm_commissioner/show.rb +0 -169
- data/app/models/spree_cm_commissioner/show_contestant.rb +0 -39
- data/app/models/spree_cm_commissioner/show_contestant_image.rb +0 -11
- data/app/models/spree_cm_commissioner/show_contestant_video.rb +0 -15
- data/app/models/spree_cm_commissioner/show_episode.rb +0 -108
- data/app/models/spree_cm_commissioner/show_person.rb +0 -15
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +0 -21
- data/app/models/spree_cm_commissioner/show_person_image.rb +0 -11
- data/app/models/spree_cm_commissioner/vote.rb +0 -16
- data/app/models/spree_cm_commissioner/vote_fraud_event.rb +0 -20
- data/app/models/spree_cm_commissioner/voting_contestant.rb +0 -100
- data/app/models/spree_cm_commissioner/voting_credit.rb +0 -72
- data/app/models/spree_cm_commissioner/voting_credit_transaction.rb +0 -55
- data/app/models/spree_cm_commissioner/voting_session.rb +0 -216
- data/app/models/spree_cm_commissioner/voting_session_stat.rb +0 -8
- data/app/overrides/spree/admin/products/_form/preview_checkbox.html.erb.deface +0 -9
- data/app/overrides/spree/admin/taxons/_form/preview_checkbox.html.erb.deface +0 -7
- data/app/serializers/spree/v2/tenant/ad_campaign_serializer.rb +0 -13
- data/app/serializers/spree/v2/tenant/advertisement_serializer.rb +0 -11
- data/app/serializers/spree/v2/tenant/free_vote_claim_serializer.rb +0 -9
- data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +0 -21
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +0 -20
- data/app/serializers/spree/v2/tenant/show_parent_serializer.rb +0 -13
- data/app/serializers/spree/v2/tenant/show_person_assignment_serializer.rb +0 -16
- data/app/serializers/spree/v2/tenant/show_person_serializer.rb +0 -13
- data/app/serializers/spree/v2/tenant/show_serializer.rb +0 -23
- data/app/serializers/spree/v2/tenant/video_serializer.rb +0 -9
- data/app/serializers/spree/v2/tenant/vote_package_serializer.rb +0 -12
- data/app/serializers/spree/v2/tenant/vote_serializer.rb +0 -14
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +0 -23
- data/app/serializers/spree/v2/tenant/voting_credit_serializer.rb +0 -10
- data/app/serializers/spree/v2/tenant/voting_credit_transaction_serializer.rb +0 -14
- data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +0 -21
- data/app/services/spree_cm_commissioner/fraud_check.rb +0 -299
- data/app/services/spree_cm_commissioner/imports/contestants/create.rb +0 -153
- data/app/services/spree_cm_commissioner/show_contestants/normalize_video_highlights.rb +0 -57
- data/app/services/spree_cm_commissioner/show_persons/contestant_assigner.rb +0 -51
- data/app/services/spree_cm_commissioner/url_embed/youtube_embed.rb +0 -44
- data/app/services/spree_cm_commissioner/vote_counters/audit_counters.rb +0 -43
- data/app/services/spree_cm_commissioner/vote_counters/base.rb +0 -31
- data/app/services/spree_cm_commissioner/vote_counters/increment.rb +0 -44
- data/app/services/spree_cm_commissioner/vote_counters/per_contestant_counter.rb +0 -68
- data/app/services/spree_cm_commissioner/vote_counters/rebuild_from_db.rb +0 -70
- data/app/services/spree_cm_commissioner/vote_counters/snapshot_to_db.rb +0 -113
- data/app/services/spree_cm_commissioner/vote_credit_deductor.rb +0 -68
- data/app/services/spree_cm_commissioner/vote_package/create.rb +0 -145
- data/app/services/spree_cm_commissioner/vote_package/update.rb +0 -91
- data/app/services/spree_cm_commissioner/vote_processor.rb +0 -144
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +0 -335
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +0 -40
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +0 -106
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +0 -77
- data/app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb +0 -116
- data/app/services/spree_cm_commissioner/voting_credits/credit_calculator.rb +0 -35
- data/app/services/spree_cm_commissioner/voting_credits/de_allocate.rb +0 -87
- data/app/services/spree_cm_commissioner/voting_leaderboards/calculate_score.rb +0 -67
- data/app/services/spree_cm_commissioner/voting_leaderboards/combined_result.rb +0 -190
- data/app/services/spree_cm_commissioner/voting_sessions/finalize.rb +0 -105
- data/db/migrate/20260309230148_create_cm_show_people.rb +0 -14
- data/db/migrate/20260309230149_create_cm_show_people_assignments.rb +0 -16
- data/db/migrate/20260310082711_create_cm_show_contestants.rb +0 -28
- data/db/migrate/20260310082720_create_cm_voting_sessions.rb +0 -21
- data/db/migrate/20260310082721_create_cm_voting_contestants.rb +0 -23
- data/db/migrate/20260310082734_add_voting_fields_to_spree_taxons.rb +0 -9
- data/db/migrate/20260310082735_add_type_to_spree_products.rb +0 -6
- data/db/migrate/20260310082749_create_cm_voting_credits.rb +0 -27
- data/db/migrate/20260326080200_create_cm_voting_credit_transactions.rb +0 -27
- data/db/migrate/20260330160000_create_cm_votes.rb +0 -25
- data/db/migrate/20260401072500_add_advanced_from_to_cm_voting_contestants.rb +0 -7
- data/db/migrate/20260402000001_add_voting_credit_scope_to_spree_taxons.rb +0 -6
- data/db/migrate/20260402000002_rename_scopeable_to_votable_in_cm_voting_credits.rb +0 -12
- data/db/migrate/20260403070000_add_name_to_cm_voting_sessions.rb +0 -5
- data/db/migrate/20260406000001_add_vendor_id_to_voting_tables.rb +0 -6
- data/db/migrate/20260406000001_rename_votes_remaining_to_amount_in_cm_voting_credits.rb +0 -11
- data/db/migrate/20260408085255_add_show_id_and_vendor_id_to_cm_voting_sessions.rb +0 -9
- data/db/migrate/20260420000001_rename_type_to_credit_type_in_cm_voting_credits.rb +0 -25
- data/db/migrate/20260422000001_create_cm_vote_fraud_events.rb +0 -23
- data/db/migrate/20260423000001_add_preview_to_taxons_products_and_sections.rb +0 -11
- data/db/migrate/20260423000002_create_preview_roles.rb +0 -24
- data/db/migrate/20260515120000_add_public_metadata_to_cm_voting_sessions.rb +0 -5
- data/db/migrate/20260518090920_add_unique_voter_count_to_voting_contestants.rb +0 -5
- data/db/migrate/20260518094322_create_cm_voting_session_stats.rb +0 -17
- data/db/migrate/20260520000001_add_scoring_model_to_cm_voting_sessions.rb +0 -5
- data/db/migrate/20260520000001_optimize_cm_votes_indexes.rb +0 -22
- data/db/migrate/20260525042257_add_vote_number_to_cm_voting_contestants.rb +0 -18
- data/db/migrate/20260527035430_add_confirmed_rank_to_cm_voting_contestants.rb +0 -5
- data/db/migrate/20260527062005_add_eliminated_at_to_cm_show_contestants.rb +0 -5
- data/db/migrate/20260603063652_add_parent_to_voting_sessions.rb +0 -9
- data/db/migrate/20260603090000_add_session_type_to_cm_voting_sessions.rb +0 -6
- data/db/migrate/20260608000000_add_display_to_cm_voting_sessions.rb +0 -5
- data/docs/sql/jsonb_query_guide.md +0 -57
- data/lib/spree_cm_commissioner/test_helper/factories/show_episode_factory.rb +0 -12
- data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +0 -120
- data/lib/spree_cm_commissioner/test_helper/factories/vote_credit_factory.rb +0 -37
- data/lib/spree_cm_commissioner/test_helper/factories/vote_factory.rb +0 -28
- data/lib/spree_cm_commissioner/test_helper/factories/voting_credit_transaction_factory.rb +0 -11
- data/lib/spree_cm_commissioner/test_helper/factories/voting_session_factory.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20f0a180f0ca53b77ce1c80dd3dc41e0d3049321aa02567ae35f23421828020c
|
|
4
|
+
data.tar.gz: 52f68c03ee83f7b0863ebcda54c301be0f13f1584f026a6f46d574933e0f368e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 64e7b779a99ea18dfc44ecd1953f4e7878087754c55fe13fe741304ca4566b027e301638d2954ebdd19d1dc0e014b5119bb2ca7e73e0a36be05570db66c2eae0
|
|
7
|
+
data.tar.gz: bf170f7c4fdba381ff89bd02393df9b5e8baad1d765d5542804beca8fef87f03088ac0a6903fd62e1017eba367d8653d1f44ad89b7396c91ed9fb1bc5f6c2f68
|
data/.env.example
CHANGED
|
@@ -20,6 +20,8 @@ WAITING_ROOM_SESSION_SIGNATURE="e6b2********************26e3"
|
|
|
20
20
|
WAITING_ROOM_SESSION_EXPIRE_DURATION_IN_SECOND=
|
|
21
21
|
WAITING_ROOM_MIN_SESSIONS_COUNT=5
|
|
22
22
|
WAITING_ROOM_DISABLED=no
|
|
23
|
+
WAITING_ROOM_POSITION_STAMP_LIMIT=1000
|
|
24
|
+
WAITING_ROOM_FIRESTORE_BATCH_SIZE=500
|
|
23
25
|
|
|
24
26
|
# Vattanac Bank
|
|
25
27
|
VATTANAC_AES_SECRET_KEY= ""
|
|
@@ -63,3 +65,6 @@ PAYMENT_LOCK_MIN_DURATION_IN_MINUTES=5 # Minimum remaining hold time requir
|
|
|
63
65
|
MAX_ACTIVE_HOLDS_PER_USER=3 # Max concurrent active holds allowed per user across all orders
|
|
64
66
|
MAX_HOLDS_PER_IP_PER_HOUR=5 # Max hold attempts per IP address within a rolling 1-hour window (abuse prevention)
|
|
65
67
|
HOLD_COOLDOWN_AFTER_EXPIRY_IN_MINUTES=2 # Cooldown period before a user can re-acquire a hold after one expired on them
|
|
68
|
+
|
|
69
|
+
# See: app/models/spree_cm_commissioner/payment_decorator.rb
|
|
70
|
+
PAYMENT_INCOMPLETE_NOTIFICATION_DELAY_IN_MINUTES=5 # Delay before notifying a customer that their order is still unpaid after payment is created
|
|
@@ -164,8 +164,7 @@ jobs:
|
|
|
164
164
|
env:
|
|
165
165
|
DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
|
|
166
166
|
run: |
|
|
167
|
-
|
|
168
|
-
bundle exec brakeman --no-threads --no-exit-on-warn
|
|
167
|
+
bundle exec brakeman --no-exit-on-warn
|
|
169
168
|
|
|
170
169
|
test:
|
|
171
170
|
needs: [setup]
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -16,7 +16,6 @@ module SpreeCmCommissioner
|
|
|
16
16
|
GuestCardClassesController
|
|
17
17
|
SeatLayoutController
|
|
18
18
|
CmsPagesController
|
|
19
|
-
AdvertisementsController
|
|
20
19
|
].freeze
|
|
21
20
|
|
|
22
21
|
# Priority 2: Semi-Static (1 hour)
|
|
@@ -26,7 +25,6 @@ module SpreeCmCommissioner
|
|
|
26
25
|
HomepageDataController
|
|
27
26
|
PopularRoutesController
|
|
28
27
|
RoutePlacesController
|
|
29
|
-
ShowsController
|
|
30
28
|
].freeze
|
|
31
29
|
|
|
32
30
|
# Priority 3: Moderate Freshness (30 minutes)
|
|
@@ -51,10 +51,7 @@ module Spree
|
|
|
51
51
|
def permitted_resource_params
|
|
52
52
|
segment_value = helpers.calculate_segment_value(params[:spree_cm_commissioner_homepage_section])
|
|
53
53
|
|
|
54
|
-
params
|
|
55
|
-
.require(:spree_cm_commissioner_homepage_section)
|
|
56
|
-
.permit(:title, :description, :active, :tenant_id, :preview)
|
|
57
|
-
.merge(segment: segment_value)
|
|
54
|
+
params.require(:spree_cm_commissioner_homepage_section).permit(:title, :description, :active, :tenant_id).merge(segment: segment_value)
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
def load_tenants
|
|
@@ -3,7 +3,6 @@ module Spree
|
|
|
3
3
|
module TaxonsControllerDecorator
|
|
4
4
|
def self.prepended(base)
|
|
5
5
|
base.before_action :build_assets, only: %i[create update]
|
|
6
|
-
base.before_action :normalize_sti_taxon_params, only: %i[create update]
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
# override
|
|
@@ -56,24 +55,6 @@ module Spree
|
|
|
56
55
|
@taxon.build_ad_banner(attachment: permitted_resource_params.delete(:ad_banner)) if permitted_resource_params[:ad_banner]
|
|
57
56
|
@taxon.build_video_banner(attachment: permitted_resource_params.delete(:video_banner)) if permitted_resource_params[:video_banner]
|
|
58
57
|
end
|
|
59
|
-
|
|
60
|
-
# Some admin forms submit STI records under their class key
|
|
61
|
-
# (e.g. :spree_cm_commissioner_show) while Spree update reads :taxon.
|
|
62
|
-
# Merge both into :taxon so all edited fields are persisted.
|
|
63
|
-
def normalize_sti_taxon_params
|
|
64
|
-
return unless @taxon
|
|
65
|
-
|
|
66
|
-
sti_key = @taxon.class.model_name.param_key.to_sym
|
|
67
|
-
sti_params = params[sti_key]
|
|
68
|
-
return unless sti_params.is_a?(::ActionController::Parameters)
|
|
69
|
-
|
|
70
|
-
base_params = params[:taxon]
|
|
71
|
-
base_hash = base_params.is_a?(::ActionController::Parameters) ? base_params.to_unsafe_h : {}
|
|
72
|
-
sti_hash = sti_params.to_unsafe_h
|
|
73
|
-
merged_params = ::ActionController::Parameters.new(base_hash.merge(sti_hash))
|
|
74
|
-
|
|
75
|
-
params[:taxon] = merged_params
|
|
76
|
-
end
|
|
77
58
|
end
|
|
78
59
|
end
|
|
79
60
|
end
|
|
@@ -6,7 +6,6 @@ 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]
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
# Override
|
|
@@ -52,24 +51,6 @@ module SpreeCmCommissioner
|
|
|
52
51
|
|
|
53
52
|
protected
|
|
54
53
|
|
|
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
|
-
|
|
73
54
|
def merge_industry_taxons_into_taxons
|
|
74
55
|
return if params[:product].blank?
|
|
75
56
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class PaymentIncompleteNotificationSender < BaseInteractor
|
|
3
|
+
def call
|
|
4
|
+
order = context.notificable
|
|
5
|
+
return if order.user.blank?
|
|
6
|
+
return if order.reload.payment_fulfilled?
|
|
7
|
+
|
|
8
|
+
SpreeCmCommissioner::OrderGeneralNotification.with(
|
|
9
|
+
notificable: order,
|
|
10
|
+
title: title,
|
|
11
|
+
message: message(order)
|
|
12
|
+
).deliver_later(order.user)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def title
|
|
18
|
+
I18n.t('notifications.spree_cm_commissioner.payment_incomplete_notification.title')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def message(order)
|
|
22
|
+
I18n.t('notifications.spree_cm_commissioner.payment_incomplete_notification.message', order_number: order.number)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class ReleaseInventoryItemNotificationSender < BaseInteractor
|
|
3
|
+
def call
|
|
4
|
+
order = context.notificable
|
|
5
|
+
return if order.user.blank?
|
|
6
|
+
|
|
7
|
+
SpreeCmCommissioner::OrderGeneralNotification.with(
|
|
8
|
+
notificable: order,
|
|
9
|
+
title: title,
|
|
10
|
+
message: message(order)
|
|
11
|
+
).deliver_later(order.user)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def title
|
|
17
|
+
I18n.t('notifications.spree_cm_commissioner.release_inventory_item_notification.title')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def message(order)
|
|
21
|
+
I18n.t('notifications.spree_cm_commissioner.release_inventory_item_notification.message', order_number: order.number)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -4,13 +4,20 @@ module SpreeCmCommissioner
|
|
|
4
4
|
class WaitingRoomSessionCreator < BaseInteractor
|
|
5
5
|
delegate :remote_ip, :waiting_guest_firebase_doc_id, :page_path, :tenant_id, to: :context
|
|
6
6
|
|
|
7
|
+
SESSION_CREATION_LOCK_KEY = 7_331_001
|
|
8
|
+
|
|
7
9
|
def call
|
|
8
10
|
return context.fail!(message: 'must_provide_waiting_guest_firebase_doc_id') if waiting_guest_firebase_doc_id.blank?
|
|
9
11
|
return context.fail!(message: 'must_provide_remote_ip') if remote_ip.blank?
|
|
10
|
-
return context.fail!(message: 'sessions_reach_it_maximum') if full?
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
# Advisory lock ensures the capacity check and session creation are atomic across all app instances.
|
|
14
|
+
with_session_creation_lock do
|
|
15
|
+
return context.fail!(message: 'sessions_reach_it_maximum') if full?
|
|
16
|
+
|
|
17
|
+
generate_jwt_token
|
|
18
|
+
assign_token_and_create_session_to_db
|
|
19
|
+
end
|
|
20
|
+
|
|
14
21
|
log_to_firebase
|
|
15
22
|
|
|
16
23
|
# commented because of following bug: https://github.com/channainfo/commissioner/issues/2185
|
|
@@ -19,10 +26,20 @@ module SpreeCmCommissioner
|
|
|
19
26
|
end
|
|
20
27
|
|
|
21
28
|
def full?
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
max = Rails.cache.fetch('waiting_room/max_sessions_count', expires_in: 1.hour) do
|
|
30
|
+
fetcher = SpreeCmCommissioner::WaitingRoomSystemMetadataFetcher.new(firestore: firestore)
|
|
31
|
+
fetcher.load_document_data
|
|
32
|
+
fetcher.max_sessions_count_with_min
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
SpreeCmCommissioner::WaitingRoomSession.active.count >= max
|
|
36
|
+
end
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
def with_session_creation_lock
|
|
39
|
+
SpreeCmCommissioner::WaitingRoomSession.transaction do
|
|
40
|
+
SpreeCmCommissioner::WaitingRoomSession.connection.execute("SELECT pg_advisory_xact_lock(#{SESSION_CREATION_LOCK_KEY})")
|
|
41
|
+
yield
|
|
42
|
+
end
|
|
26
43
|
end
|
|
27
44
|
|
|
28
45
|
def generate_jwt_token
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class PaymentIncompleteNotificationJob < ApplicationUniqueJob
|
|
3
|
+
queue_as :default
|
|
4
|
+
|
|
5
|
+
def perform(options = {})
|
|
6
|
+
order = Spree::Order.find_by(id: options[:order_id])
|
|
7
|
+
return unless order
|
|
8
|
+
|
|
9
|
+
SpreeCmCommissioner::PaymentIncompleteNotificationSender.call(notificable: order)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -7,6 +7,9 @@ module SpreeCmCommissioner
|
|
|
7
7
|
|
|
8
8
|
STAMP_LIMIT = (ENV['WAITING_ROOM_POSITION_STAMP_LIMIT'] || 1000).to_i
|
|
9
9
|
|
|
10
|
+
# Firestore bounds a batch update by payload size (10 MiB); this batch size leaves 500/commit far under that.
|
|
11
|
+
FIRESTORE_BATCH_SIZE = (ENV['WAITING_ROOM_FIRESTORE_BATCH_SIZE'] || 500).to_i
|
|
12
|
+
|
|
10
13
|
def perform
|
|
11
14
|
paths = stamp_paths
|
|
12
15
|
avg_queue_to_enter = lobby_data[:avg_queue_to_enter_seconds].to_i
|
|
@@ -21,16 +24,32 @@ module SpreeCmCommissioner
|
|
|
21
24
|
break if remaining <= 0
|
|
22
25
|
|
|
23
26
|
docs = waiting_query(path).order('queued_at').limit(remaining).get.to_a
|
|
24
|
-
|
|
27
|
+
|
|
28
|
+
# Stamp the docs in chunks: each_slice splits them into groups of at most
|
|
29
|
+
# FIRESTORE_BATCH_SIZE, and each group is written in one firestore.batch commit
|
|
30
|
+
# (so e.g. 1000 docs = 2 commits, not 1000 round-trips).
|
|
31
|
+
docs.each_slice(FIRESTORE_BATCH_SIZE) do |slice|
|
|
25
32
|
firestore.batch do |b|
|
|
26
33
|
slice.each do |doc|
|
|
27
34
|
global += 1
|
|
35
|
+
|
|
36
|
+
# The app shows a progress bar via (queue_total - position + 1) / queue_total.
|
|
37
|
+
# `position` only ever counts down toward 1, so we keep `queue_total` from ever
|
|
38
|
+
# going down either (max of its old value and the current position) — it becomes
|
|
39
|
+
# the guest's starting depth. That keeps the bar moving only forward, reaching
|
|
40
|
+
# 100% at position 1, instead of jumping as the live waiting count shrinks.
|
|
41
|
+
#
|
|
42
|
+
# Example — a guest who started 8th, with the line draining from 8 to 4 people:
|
|
43
|
+
# live total: position 6 / total 8 = 38%, then position 4 / total 4 = 25% (drops!) ❌
|
|
44
|
+
# this fix: position 6 / total 8 = 38%, then position 4 / total 8 = 63% (climbs) ✅
|
|
45
|
+
# ...continuing to position 1 / total 8 = 100% at the front.
|
|
28
46
|
data = {
|
|
29
47
|
position: global,
|
|
30
|
-
queue_total:
|
|
48
|
+
queue_total: [doc.data[:queue_total].to_i, global].max,
|
|
31
49
|
estimated_wait_seconds: avg_queue_to_enter,
|
|
32
50
|
status_updated_at: stamped_at
|
|
33
51
|
}
|
|
52
|
+
|
|
34
53
|
data[:position_set_at] = stamped_at unless doc.data[:position_set_at]
|
|
35
54
|
b.update(doc.ref, data)
|
|
36
55
|
end
|
|
@@ -26,10 +26,8 @@ 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
|
|
30
29
|
|
|
31
30
|
state_machine.after_transition to: :complete, do: :increment_route_fulfilled_order_count
|
|
32
|
-
state_machine.after_transition to: :complete, do: :allocate_resources
|
|
33
31
|
|
|
34
32
|
scope :accepted, -> { where(request_state: 'accepted') }
|
|
35
33
|
|
|
@@ -330,13 +328,5 @@ module SpreeCmCommissioner
|
|
|
330
328
|
factory = OrderTelegramMessageFactory.new(title: title, order: self)
|
|
331
329
|
TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
|
|
332
330
|
end
|
|
333
|
-
|
|
334
|
-
def allocate_resources
|
|
335
|
-
SpreeCmCommissioner::VotingCreditAllocationJob.perform_later(order_id: id)
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
def de_allocate_resources
|
|
339
|
-
SpreeCmCommissioner::VotingCreditDeAllocationJob.perform_later(order_id: id)
|
|
340
|
-
end
|
|
341
331
|
end
|
|
342
332
|
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
|
|
8
|
+
PRODUCT_TYPES = %i[accommodation service ecommerce transit].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
|
|
|
@@ -3,9 +3,7 @@ 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
|
|
7
|
-
ads: 9
|
|
8
|
-
}
|
|
6
|
+
enum kind: { category: 0, cms: 1, event: 2, occupation: 3, nationality: 4, organization: 5, transit: 6, industry: 7, agency_category: 8 }
|
|
9
7
|
end
|
|
10
8
|
end
|
|
11
9
|
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 }
|
|
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 }
|
|
7
7
|
has_one_attached :imported_file
|
|
8
8
|
friendly_id :name, use: :slugged
|
|
9
9
|
|
|
@@ -12,6 +12,7 @@ module SpreeCmCommissioner
|
|
|
12
12
|
# a real payment record permanently exists in the DB. Multiple payments for the
|
|
13
13
|
# same order (retries) each refresh the 5-minute window — LockForPayment is idempotent.
|
|
14
14
|
base.after_commit :lock_holds_for_payment, on: :create
|
|
15
|
+
base.after_commit :schedule_payment_incomplete_notification, on: :create
|
|
15
16
|
|
|
16
17
|
base.whitelisted_ransackable_attributes |= %w[payable_id]
|
|
17
18
|
end
|
|
@@ -56,6 +57,15 @@ module SpreeCmCommissioner
|
|
|
56
57
|
order.lock_order_holds_for_payment
|
|
57
58
|
end
|
|
58
59
|
|
|
60
|
+
def schedule_payment_incomplete_notification
|
|
61
|
+
# Delay gives the user time to finish paying; the job only notifies if the
|
|
62
|
+
# order is still unpaid by then.
|
|
63
|
+
delay = ENV.fetch('PAYMENT_INCOMPLETE_NOTIFICATION_DELAY_IN_MINUTES', '5').to_i.minutes
|
|
64
|
+
SpreeCmCommissioner::PaymentIncompleteNotificationJob
|
|
65
|
+
.set(wait: delay)
|
|
66
|
+
.perform_later(order_id: order.id)
|
|
67
|
+
end
|
|
68
|
+
|
|
59
69
|
def ticket_transfer_completable?
|
|
60
70
|
completed? && order.ticket_transfer? && order.complete? && order.payment_fulfilled?
|
|
61
71
|
end
|
|
@@ -12,10 +12,6 @@ module SpreeCmCommissioner
|
|
|
12
12
|
base.include SpreeCmCommissioner::StoreMetadata
|
|
13
13
|
base.include SpreeCmCommissioner::HomepageSectionRelatableConcern
|
|
14
14
|
|
|
15
|
-
base.delegate :is_open_dated, :is_open_dated?, to: :trip, allow_nil: true
|
|
16
|
-
|
|
17
|
-
base.has_many :voting_sessions, class_name: 'SpreeCmCommissioner::VotingSession', foreign_key: :episode_id, dependent: :destroy
|
|
18
|
-
|
|
19
15
|
base.has_many :variant_kind_option_types, -> { where(kind: :variant).order(:position) },
|
|
20
16
|
through: :product_option_types, source: :option_type
|
|
21
17
|
|
|
@@ -63,45 +59,8 @@ module SpreeCmCommissioner
|
|
|
63
59
|
|
|
64
60
|
base.belongs_to :event, class_name: 'Spree::Taxon', optional: true
|
|
65
61
|
|
|
66
|
-
base.has_many :preview_roles, class_name: 'SpreeCmCommissioner::PreviewRole', as: :previewable
|
|
67
62
|
base.has_many :industry_classifications, -> { joins(:taxon).where(spree_taxons: { kind: :industry }) }, class_name: 'Spree::Classification'
|
|
68
63
|
base.has_many :industry_taxons, through: :industry_classifications, source: :taxon
|
|
69
|
-
base.scope :visible_to, lambda { |user|
|
|
70
|
-
publicly_available = where(status: :active, preview: false)
|
|
71
|
-
|
|
72
|
-
if user
|
|
73
|
-
# Resolved through associations — avoids hardcoding class names.
|
|
74
|
-
taxon_type = reflect_on_association(:taxons).klass.polymorphic_name
|
|
75
|
-
|
|
76
|
-
# IDs of products that have been explicitly assigned their own PreviewRole.
|
|
77
|
-
products_with_own_roles = SpreeCmCommissioner::PreviewRole
|
|
78
|
-
.where(previewable_type: polymorphic_name)
|
|
79
|
-
.select(:previewable_id)
|
|
80
|
-
|
|
81
|
-
# Path A: product has its own PreviewRole → user must hold that role directly.
|
|
82
|
-
# Taxon membership is irrelevant for these products.
|
|
83
|
-
via_product_role = where(status: :active, preview: true)
|
|
84
|
-
.where(id: products_with_own_roles)
|
|
85
|
-
.where(id: user.preview_roles.where(previewable_type: polymorphic_name).select(:previewable_id))
|
|
86
|
-
|
|
87
|
-
# Path B: product has no own PreviewRole → inherit access from its event or taxons.
|
|
88
|
-
# Accessible if the user holds a preview role for the product's event_id or any
|
|
89
|
-
# taxon the product belongs to via the classifications join table.
|
|
90
|
-
allowed_taxon_ids = user.preview_roles.where(previewable_type: taxon_type).select(:previewable_id)
|
|
91
|
-
preview_no_own = where(status: :active, preview: true).where.not(id: products_with_own_roles)
|
|
92
|
-
|
|
93
|
-
via_event_id = preview_no_own.where(event_id: allowed_taxon_ids)
|
|
94
|
-
via_taxon_join = preview_no_own.joins(:taxons).where(spree_taxons: { id: allowed_taxon_ids })
|
|
95
|
-
|
|
96
|
-
publicly_available
|
|
97
|
-
.or(via_product_role)
|
|
98
|
-
.or(where(id: via_event_id.select(:id)))
|
|
99
|
-
.or(where(id: via_taxon_join.select(:id)))
|
|
100
|
-
else
|
|
101
|
-
publicly_available
|
|
102
|
-
end
|
|
103
|
-
}
|
|
104
|
-
|
|
105
64
|
base.scope :min_price, lambda { |vendor|
|
|
106
65
|
joins(:prices_including_master)
|
|
107
66
|
.where(vendor_id: vendor.id, product_type: vendor.primary_product_type)
|
|
@@ -114,12 +73,6 @@ module SpreeCmCommissioner
|
|
|
114
73
|
.maximum('spree_prices.price').to_f
|
|
115
74
|
}
|
|
116
75
|
base.scope :subscribable, -> { where(subscribable: 1) }
|
|
117
|
-
base.scope :advertisements, lambda {
|
|
118
|
-
advertisement
|
|
119
|
-
.available
|
|
120
|
-
.where('spree_products.available_on IS NULL OR spree_products.available_on <= CURRENT_TIMESTAMP')
|
|
121
|
-
.where('spree_products.discontinue_on IS NULL OR spree_products.discontinue_on > CURRENT_TIMESTAMP')
|
|
122
|
-
}
|
|
123
76
|
|
|
124
77
|
base.before_validation :set_event_id
|
|
125
78
|
|
|
@@ -133,11 +86,6 @@ module SpreeCmCommissioner
|
|
|
133
86
|
base.store_public_metadata :open_dated_validity_days, :integer, default: 90
|
|
134
87
|
base.store_public_metadata :enable_inventory_hold, :boolean, default: false
|
|
135
88
|
|
|
136
|
-
base.store_private_metadata :advertise_weight, :integer, default: 1
|
|
137
|
-
base.store_private_metadata :video_url, :string
|
|
138
|
-
base.store_private_metadata :skip_after_seconds, :integer, default: 5
|
|
139
|
-
base.store_private_metadata :duration_seconds, :integer, default: 30
|
|
140
|
-
|
|
141
89
|
base.after_update :update_variants_vendor_id, if: :saved_change_to_vendor_id?
|
|
142
90
|
base.after_update :sync_event_id_to_children, if: :saved_change_to_event_id?
|
|
143
91
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module RoleDecorator
|
|
3
3
|
def self.prepended(base)
|
|
4
|
-
base.enum role_type: { internal: 0, external: 1
|
|
4
|
+
base.enum role_type: { internal: 0, external: 1 }
|
|
5
5
|
|
|
6
6
|
base.has_many :role_permissions, class_name: 'SpreeCmCommissioner::RolePermission'
|
|
7
7
|
base.has_many :permissions, through: :role_permissions, class_name: 'SpreeCmCommissioner::Permission'
|
|
8
|
-
base.has_many :preview_roles, class_name: 'SpreeCmCommissioner::PreviewRole'
|
|
9
8
|
|
|
10
9
|
base.belongs_to :vendor, optional: true
|
|
11
10
|
|
|
@@ -14,8 +13,6 @@ module SpreeCmCommissioner
|
|
|
14
13
|
where(vendor_id: vendor)
|
|
15
14
|
}
|
|
16
15
|
base.scope :filter_external, -> { where(role_type: :external) }
|
|
17
|
-
base.scope :filter_internal, -> { where(role_type: :internal) }
|
|
18
|
-
base.scope :filter_preview, -> { where(role_type: :preview) }
|
|
19
16
|
|
|
20
17
|
base.accepts_nested_attributes_for :role_permissions, allow_destroy: true
|
|
21
18
|
|
|
@@ -84,29 +84,7 @@ module SpreeCmCommissioner
|
|
|
84
84
|
|
|
85
85
|
base.has_many :import_orders, as: :importable, class_name: 'SpreeCmCommissioner::Imports::ImportOrder', dependent: :destroy
|
|
86
86
|
|
|
87
|
-
base.scope :shows, -> { where(taxonomy_id: Spree::Taxonomy.shows.id, depth: 1) }
|
|
88
|
-
base.scope :events, -> { where(taxonomy_id: Spree::Taxonomy.events.id, depth: 1) }
|
|
89
|
-
base.scope :ad_campaigns, -> { where(taxonomy_id: Spree::Taxonomy.ads.id, depth: 1) }
|
|
90
|
-
|
|
91
|
-
base.has_many :advertisements,
|
|
92
|
-
-> { where(product_type: :advertisement, deleted_at: nil) },
|
|
93
|
-
through: :classifications,
|
|
94
|
-
class_name: 'Spree::Product',
|
|
95
|
-
source: :product
|
|
96
|
-
|
|
97
87
|
base.has_many :agencies, class_name: 'SpreeCmCommissioner::Agency', foreign_key: :agency_category_id
|
|
98
|
-
base.has_many :preview_roles, class_name: 'SpreeCmCommissioner::PreviewRole', as: :previewable
|
|
99
|
-
|
|
100
|
-
base.scope :visible_to, lambda { |user|
|
|
101
|
-
publicly_available = where(preview: false)
|
|
102
|
-
|
|
103
|
-
if user
|
|
104
|
-
allowed_ids = user.preview_roles.where(previewable_type: polymorphic_name).select(:previewable_id)
|
|
105
|
-
publicly_available.or(where(preview: true, id: allowed_ids))
|
|
106
|
-
else
|
|
107
|
-
publicly_available
|
|
108
|
-
end
|
|
109
|
-
}
|
|
110
88
|
|
|
111
89
|
# Create maintaining task to purge taxon related caches
|
|
112
90
|
base.after_save { SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: self) }
|
|
@@ -119,7 +97,6 @@ module SpreeCmCommissioner
|
|
|
119
97
|
.joins('INNER JOIN cm_homepage_sections ON cm_homepage_section_relatables.homepage_section_id = cm_homepage_sections.id')
|
|
120
98
|
.where(cm_homepage_sections: { tenant_id: nil, active: true })
|
|
121
99
|
.where(kind: :event)
|
|
122
|
-
.where(preview: false)
|
|
123
100
|
end
|
|
124
101
|
|
|
125
102
|
def base.find_event(id)
|