spree_cm_commissioner 2.8.1.pre.3 → 2.8.1.pre.pre.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.example +1 -0
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +0 -1
- data/app/controllers/spree/api/v2/tenant/eliminated_contestants_controller.rb +19 -0
- data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +1 -0
- data/app/factory/spree_cm_commissioner/event_telegram_message_factory.rb +68 -0
- data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +2 -2
- data/app/jobs/spree_cm_commissioner/event_creation_telegram_alert_sender_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/oauth_access_tokens/cleanup_expired_job.rb +11 -0
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +1 -0
- data/app/models/concerns/spree_cm_commissioner/vehicle_kind.rb +1 -1
- data/app/models/spree_cm_commissioner/integration.rb +0 -31
- data/app/models/spree_cm_commissioner/integrations/stadium_x_v1.rb +10 -4
- data/app/models/spree_cm_commissioner/inventory_item.rb +17 -8
- data/app/models/spree_cm_commissioner/maintenance_tasks/cache_invalidation.rb +2 -0
- data/app/models/spree_cm_commissioner/maintenance_tasks/voting_session.rb +2 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +0 -1
- data/app/models/spree_cm_commissioner/place.rb +0 -2
- data/app/models/spree_cm_commissioner/route.rb +0 -1
- data/app/models/spree_cm_commissioner/seat_layout.rb +0 -2
- data/app/models/spree_cm_commissioner/show.rb +3 -1
- data/app/models/spree_cm_commissioner/show_contestant.rb +12 -0
- data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -7
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +7 -0
- data/app/models/spree_cm_commissioner/trip.rb +1 -2
- data/app/models/spree_cm_commissioner/trip_stop.rb +0 -2
- data/app/models/spree_cm_commissioner/variant_decorator.rb +0 -1
- data/app/models/spree_cm_commissioner/vehicle.rb +0 -3
- data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -1
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +0 -17
- data/app/models/spree_cm_commissioner/vendor_place.rb +0 -2
- data/app/models/spree_cm_commissioner/voting_contestant.rb +12 -0
- data/app/models/spree_cm_commissioner/voting_session.rb +34 -8
- data/app/models/spree_cm_commissioner/voting_session_stat.rb +8 -0
- data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +9 -0
- data/app/queries/spree_cm_commissioner/multi_leg_trips_query.rb +26 -44
- data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +36 -31
- data/app/queries/spree_cm_commissioner/trip_query.rb +2 -4
- data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +1 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +7 -2
- data/app/services/spree_cm_commissioner/integrations/base/sync_manager.rb +2 -1
- data/app/services/spree_cm_commissioner/integrations/base/sync_result.rb +0 -11
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/external_client/client.rb +15 -14
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_matches.rb +4 -7
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_zones.rb +3 -6
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_manager.rb +3 -0
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/full_sync_strategy.rb +3 -1
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/incremental_sync_strategy.rb +3 -1
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/webhook_sync_strategy.rb +2 -1
- data/app/services/spree_cm_commissioner/oauth_access_tokens/cleanup_expired.rb +53 -0
- data/app/services/spree_cm_commissioner/order_holds/hold.rb +0 -17
- data/app/services/spree_cm_commissioner/order_holds/release.rb +0 -17
- data/app/services/spree_cm_commissioner/show_contestants/normalize_video_highlights.rb +2 -1
- data/app/services/spree_cm_commissioner/telegram_alerts/event_creation.rb +35 -0
- data/app/services/spree_cm_commissioner/url_embed/youtube_embed.rb +30 -35
- data/app/services/spree_cm_commissioner/vote_counters/snapshot_to_db.rb +113 -0
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +1 -0
- data/app/services/spree_cm_commissioner/voting_leaderboards/calculate_score.rb +74 -0
- data/app/views/spree/admin/integrations/_form.html.erb +0 -12
- data/app/views/spree/admin/integrations/index.html.erb +1 -1
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +0 -1
- data/config/locales/km.yml +0 -1
- data/config/routes.rb +1 -1
- 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/20260525042257_add_vote_number_to_cm_voting_contestants.rb +18 -0
- data/db/migrate/20260527062005_add_eliminated_at_to_cm_show_contestants.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/integration_factory.rb +0 -11
- data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +8 -0
- data/lib/spree_cm_commissioner/trip_result.rb +48 -21
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/spree_cm_commissioner.gemspec +1 -1
- metadata +17 -118
- data/app/controllers/spree/api/v2/storefront/transit/item_availabilities_controller.rb +0 -66
- data/app/jobs/spree_cm_commissioner/audit_event_job.rb +0 -29
- data/app/jobs/spree_cm_commissioner/cleanup_expired_access_tokens_job.rb +0 -9
- data/app/models/concerns/spree_cm_commissioner/audit_wrapper.rb +0 -139
- data/app/models/concerns/spree_cm_commissioner/integrations/inventory_sync_cachable.rb +0 -9
- data/app/models/concerns/spree_cm_commissioner/variant_metadata.rb +0 -24
- data/app/models/spree_cm_commissioner/audit_event.rb +0 -11
- data/app/models/spree_cm_commissioner/currency_rate.rb +0 -15
- data/app/models/spree_cm_commissioner/integrations/book_me_bus_v1.rb +0 -56
- data/app/models/spree_cm_commissioner/integrations/larryta.rb +0 -81
- data/app/models/spree_cm_commissioner/integrations/vireak_buntham.rb +0 -82
- data/app/serializables/spree_cm_commissioner/item_availability_sync.rb +0 -10
- data/app/serializers/spree_cm_commissioner/v2/storefront/item_availability_sync_serializer.rb +0 -10
- data/app/services/spree_cm_commissioner/audit_logger.rb +0 -59
- data/app/services/spree_cm_commissioner/cleanup_expired_access_tokens.rb +0 -52
- data/app/services/spree_cm_commissioner/currency_converter/create.rb +0 -27
- data/app/services/spree_cm_commissioner/currency_rates/manage.rb +0 -99
- data/app/services/spree_cm_commissioner/google_maps_geocoder.rb +0 -41
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/client.rb +0 -261
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/connection.rb +0 -147
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_item_status.rb +0 -52
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_items.rb +0 -91
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/unstock_inventory.rb +0 -140
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_inventory.rb +0 -52
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_item_availability.rb +0 -249
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_locations.rb +0 -103
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_product.rb +0 -66
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_route_stops.rb +0 -113
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_routes.rb +0 -128
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_seat_layout.rb +0 -342
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_service_calendars.rb +0 -59
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trip_stop.rb +0 -179
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trips.rb +0 -597
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_variant.rb +0 -58
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_vehicle_types.rb +0 -87
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/time_parser.rb +0 -19
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/base.rb +0 -40
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/branch.rb +0 -65
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/direction.rb +0 -51
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/inventory_item_status.rb +0 -148
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/location.rb +0 -55
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/operator.rb +0 -17
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/reservation_cart.rb +0 -85
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat.rb +0 -128
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat_layout.rb +0 -363
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/stop.rb +0 -84
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/trip.rb +0 -199
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/wallet_payment.rb +0 -40
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_manager.rb +0 -22
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/full_sync_strategy.rb +0 -117
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/incremental_sync_strategy.rb +0 -64
- data/app/services/spree_cm_commissioner/integrations/larryta/external_client/client.rb +0 -344
- data/app/services/spree_cm_commissioner/integrations/larryta/external_client/connection.rb +0 -74
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_item_status.rb +0 -53
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_items.rb +0 -106
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/hold_seats.rb +0 -143
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/release_seats.rb +0 -90
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/unstock_inventory.rb +0 -113
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_item_availability.rb +0 -261
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_product.rb +0 -72
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_routes.rb +0 -142
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_seat_layout.rb +0 -255
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_stock_item.rb +0 -55
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trip_stop.rb +0 -167
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trips.rb +0 -320
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_variant.rb +0 -63
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_vehicle_type.rb +0 -79
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/base.rb +0 -39
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking.rb +0 -113
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_session.rb +0 -43
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_transaction.rb +0 -236
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/direction.rb +0 -71
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/passenger.rb +0 -48
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/schedule.rb +0 -150
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat.rb +0 -31
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_availability.rb +0 -49
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_layout.rb +0 -211
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_manager.rb +0 -17
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/full_sync_strategy.rb +0 -79
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/incremental_sync_strategy.rb +0 -58
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/client.rb +0 -206
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/connection.rb +0 -59
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_item_status.rb +0 -48
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_items.rb +0 -97
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/unstock_inventory.rb +0 -208
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb +0 -270
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_locations.rb +0 -96
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_nationality_pricing.rb +0 -76
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_product.rb +0 -69
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_routes.rb +0 -110
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_seat_layout.rb +0 -207
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_stock_item.rb +0 -43
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trip_stop.rb +0 -185
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trips.rb +0 -300
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_variant.rb +0 -56
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_vehicle_type.rb +0 -51
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/base.rb +0 -32
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking.rb +0 -48
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking_transaction.rb +0 -46
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/cell.rb +0 -53
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/confirm_booking_request.rb +0 -43
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/location.rb +0 -37
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/schedule.rb +0 -138
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat.rb +0 -48
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat_layout.rb +0 -79
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_manager.rb +0 -17
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/full_sync_strategy.rb +0 -87
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/incremental_sync_strategy.rb +0 -53
- data/app/services/spree_cm_commissioner/inventory_items/generate_permanent_item.rb +0 -48
- data/app/services/spree_cm_commissioner/place_resolver.rb +0 -95
- data/app/views/spree/admin/integrations/_book_me_bus_v1_fields.html.erb +0 -47
- data/app/views/spree/admin/integrations/_larryta_fields.html.erb +0 -58
- data/app/views/spree/admin/integrations/_vireak_buntham_fields.html.erb +0 -75
- data/db/migrate/20260327143200_create_cm_audit_events.rb +0 -21
- data/db/migrate/20260410045815_create_cm_currency_rates.rb +0 -23
- data/db/migrate/20260411102139_add_metadata_to_cm_inventory_items.rb +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed6326825a04e2ef186e72511e895b9fbf8598858d7d8f8e4358c0dbc0bc6f7e
|
|
4
|
+
data.tar.gz: ee5cdc0fd119a84c4619596f5db5a6a2aef89b39e0be982f71612a68bd8bbd16
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7975ae665f017e022b41297314d72e25ac872241e5e224f5581cea5a736ef7e4e8abee4a8fa71916b038661da894a116c15ceeb71c03e4259627e44fff11222f
|
|
7
|
+
data.tar.gz: 6fa46d5991c849243fdac985bed14ad86d88404adf5880d0e8000c48867f27e6f20c08973bbe41c293e200650ac7b5416a0e4fc0b628a5d1a9b722062101f8c9
|
data/.env.example
CHANGED
|
@@ -34,6 +34,7 @@ DISTANCE_SIGNING_KEY=hei********************VY
|
|
|
34
34
|
|
|
35
35
|
# Cache durations (in seconds) for different content types
|
|
36
36
|
# See: app/controllers/concerns/spree_cm_commissioner/content_cachable.rb
|
|
37
|
+
CACHE_AUTO_INVALIDATION_DISABLED="" # Set to yes to disable CDN cache invalidation entirely (kill switch)
|
|
37
38
|
CACHE_CDN_MAX_AGE=86400 # CDN/server-side cache duration for all responses
|
|
38
39
|
CACHE_STATIC_MAX_AGE=86400 # Static content (countries, provinces, seat layouts, CMS pages) - 1 day
|
|
39
40
|
CACHE_SEMI_STATIC_MAX_AGE=3600 # Semi-static content (menus, homepage backgrounds, routes) - 1 hour
|
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 🎉 ---[Event]---
|
|
2
|
+
#
|
|
3
|
+
# 📋 Event: {{event.name}}
|
|
4
|
+
#
|
|
5
|
+
# 👤 Organizer: {{vendor.name}}
|
|
6
|
+
#
|
|
7
|
+
# 🗓️ Start Date: {{from_date}}
|
|
8
|
+
# 🗓️ End Date: {{to_date}}
|
|
9
|
+
# 🔗 URL: ......
|
|
10
|
+
#
|
|
11
|
+
module SpreeCmCommissioner
|
|
12
|
+
class EventTelegramMessageFactory < TelegramMessageFactory
|
|
13
|
+
attr_reader :event
|
|
14
|
+
|
|
15
|
+
def initialize(event:)
|
|
16
|
+
@event = event
|
|
17
|
+
|
|
18
|
+
title = "✨ #{event.name} ✨"
|
|
19
|
+
|
|
20
|
+
super(title: title)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def body
|
|
24
|
+
[
|
|
25
|
+
event_name_line,
|
|
26
|
+
organizer_line,
|
|
27
|
+
[start_date_line, end_date_line].compact.join("\n"),
|
|
28
|
+
event_url_line
|
|
29
|
+
].compact_blank.join("\n\n")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def event_name_line
|
|
35
|
+
"📋 Event: #{event.name}" if event.name.present?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def organizer_line
|
|
39
|
+
return if event.vendor&.name.blank?
|
|
40
|
+
|
|
41
|
+
"👤 Organizer: #{bold(event.vendor.name)}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def start_date_line
|
|
45
|
+
return if event.from_date.blank?
|
|
46
|
+
|
|
47
|
+
"🗓️ Start Date: #{pretty_datetime(event.from_date)}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def end_date_line
|
|
51
|
+
return if event.to_date.blank?
|
|
52
|
+
|
|
53
|
+
"🗓️ End Date: #{pretty_datetime(event.to_date)}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pretty_datetime(date)
|
|
57
|
+
return '' if date.blank?
|
|
58
|
+
|
|
59
|
+
date.strftime('%b %d, %Y · %H:%M')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def event_url_line
|
|
63
|
+
return if event.event_url.blank?
|
|
64
|
+
|
|
65
|
+
"🔗 URL: #{event.event_url}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -15,8 +15,8 @@ module SpreeCmCommissioner
|
|
|
15
15
|
.joins(:inventory_items)
|
|
16
16
|
.where(vendor_id: vendor_id)
|
|
17
17
|
.where(inventory_items: { inventory_date: stay_dates })
|
|
18
|
-
.where('CAST(
|
|
19
|
-
CAST(
|
|
18
|
+
.where('CAST(public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
|
|
19
|
+
CAST(public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
|
|
20
20
|
)
|
|
21
21
|
.where('inventory_items.quantity_available > 0')
|
|
22
22
|
.distinct
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class EventCreationTelegramAlertSenderJob < ApplicationUniqueJob
|
|
3
|
+
queue_as :telegram_bot
|
|
4
|
+
|
|
5
|
+
def perform(options = {})
|
|
6
|
+
event = Spree::Taxon.find(options[:event_id])
|
|
7
|
+
SpreeCmCommissioner::TelegramAlerts::EventCreation.call(event: event)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -7,6 +7,7 @@ module SpreeCmCommissioner
|
|
|
7
7
|
preference :telegram_order_alert_chat_id, :string
|
|
8
8
|
preference :telegram_order_request_alert_chat_id, :string
|
|
9
9
|
preference :telegram_new_vendor_alert_chat_id, :string
|
|
10
|
+
preference :telegram_new_event_alert_chat_id, :string
|
|
10
11
|
preference :assetlinks, :string, default: ''
|
|
11
12
|
preference :apple_app_site_association, :string, default: ''
|
|
12
13
|
end
|
|
@@ -2,7 +2,7 @@ module SpreeCmCommissioner
|
|
|
2
2
|
module VehicleKind
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
|
-
VEHICLE_KINDS = %i[suv sedan minivan van sleeping_bus luxury_van air_bus bus ferry
|
|
5
|
+
VEHICLE_KINDS = %i[suv sedan minivan van sleeping_bus luxury_van air_bus bus ferry].freeze
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
8
|
enum kind: VEHICLE_KINDS if table_exists? && column_names.include?('kind')
|
|
@@ -25,36 +25,5 @@ module SpreeCmCommissioner
|
|
|
25
25
|
def unstock_external_inventory!(_order, _line_items)
|
|
26
26
|
raise NotImplementedError, 'Subclasses must implement the unstock_external_inventory! method'
|
|
27
27
|
end
|
|
28
|
-
|
|
29
|
-
def sync_item_availability!(_options = {})
|
|
30
|
-
raise NotImplementedError, 'Subclasses must implement the sync_item_availability! method'
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def hold_inventory!(_order, _line_items)
|
|
34
|
-
raise NotImplementedError, 'Subclasses must implement the hold_inventory! method'
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Integrations that manage external inventory reservations should override this to return true
|
|
38
|
-
def supports_external_inventory_holding?
|
|
39
|
-
false
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Integrations that support automatically releasing external inventory
|
|
43
|
-
# after reservation expiration or order cancellation should override this to return true
|
|
44
|
-
def supports_auto_release_inventory?
|
|
45
|
-
false
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def release_inventory!(_order, _line_items)
|
|
49
|
-
raise NotImplementedError, 'Subclasses must implement the release_inventory! method'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def external_inventory_items(_order)
|
|
53
|
-
raise NotImplementedError, 'Subclasses must implement the external_inventory_items method'
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def external_inventory_item_status(_order, _options)
|
|
57
|
-
raise NotImplementedError, 'Subclasses must implement the external_inventory_item_status method'
|
|
58
|
-
end
|
|
59
28
|
end
|
|
60
29
|
end
|
|
@@ -5,7 +5,10 @@ class SpreeCmCommissioner::Integrations::StadiumXV1 < SpreeCmCommissioner::Integ
|
|
|
5
5
|
|
|
6
6
|
# override
|
|
7
7
|
def sync_manager
|
|
8
|
-
SpreeCmCommissioner::Integrations::StadiumXV1::SyncManager.new(
|
|
8
|
+
SpreeCmCommissioner::Integrations::StadiumXV1::SyncManager.new(
|
|
9
|
+
integration: self,
|
|
10
|
+
client: client
|
|
11
|
+
)
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
# override
|
|
@@ -15,6 +18,7 @@ class SpreeCmCommissioner::Integrations::StadiumXV1 < SpreeCmCommissioner::Integ
|
|
|
15
18
|
order: order,
|
|
16
19
|
line_items: line_items
|
|
17
20
|
)
|
|
21
|
+
|
|
18
22
|
raise SpreeCmCommissioner::Integrations::SyncError, result.error unless result.success?
|
|
19
23
|
end
|
|
20
24
|
|
|
@@ -23,9 +27,11 @@ class SpreeCmCommissioner::Integrations::StadiumXV1 < SpreeCmCommissioner::Integ
|
|
|
23
27
|
raise SpreeCmCommissioner::Integrations::SyncError, 'Ticket cannot be cancelled'
|
|
24
28
|
end
|
|
25
29
|
|
|
26
|
-
def sync_item_availability!(_options = {}); end
|
|
27
|
-
|
|
28
30
|
def client
|
|
29
|
-
|
|
31
|
+
SpreeCmCommissioner::Integrations::StadiumXV1::ExternalClient::Client.new(
|
|
32
|
+
public_key: public_key,
|
|
33
|
+
private_key: private_key,
|
|
34
|
+
base_url: base_url
|
|
35
|
+
)
|
|
30
36
|
end
|
|
31
37
|
end
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class InventoryItem < Base
|
|
3
3
|
include SpreeCmCommissioner::ProductType
|
|
4
|
-
include SpreeCmCommissioner::StoreMetadata
|
|
5
|
-
include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
6
4
|
|
|
7
5
|
MAX_DISPLAY_STOCK = 20
|
|
8
6
|
|
|
9
|
-
store_public_metadata :last_synced_at, :datetime
|
|
10
|
-
store_public_metadata :original_price, :integer
|
|
11
|
-
store_public_metadata :currency, :string
|
|
12
|
-
|
|
13
7
|
# Association
|
|
14
8
|
belongs_to :variant, class_name: 'Spree::Variant', optional: false
|
|
15
9
|
|
|
@@ -29,8 +23,23 @@ module SpreeCmCommissioner
|
|
|
29
23
|
|
|
30
24
|
before_save -> { self.product_type = variant.product_type }, if: -> { product_type.nil? }
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
after_commit :schedule_product_cache_invalidation
|
|
27
|
+
|
|
28
|
+
# Only for ecommerce: the app uses product.in_stock? (derived from quantity_available) for product cards.
|
|
29
|
+
# Other types (e.g. accommodation, bus) have many inventory items (including daily-generated ones),
|
|
30
|
+
# so invalidating per item would flood the task queue.
|
|
31
|
+
#
|
|
32
|
+
# This is temporary until we have a more robust cache invalidation strategy in place.
|
|
33
|
+
def schedule_product_cache_invalidation
|
|
34
|
+
return unless ecommerce?
|
|
35
|
+
return unless saved_change_to_quantity_available?
|
|
36
|
+
|
|
37
|
+
# Only fires on in_stock status transition (0 ↔ N); non-zero to non-zero changes are skipped.
|
|
38
|
+
old_val, new_val = saved_change_to_quantity_available
|
|
39
|
+
return if old_val.to_i.positive? && new_val.to_i.positive?
|
|
40
|
+
|
|
41
|
+
SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: variant.product)
|
|
42
|
+
end
|
|
34
43
|
|
|
35
44
|
def public_quantity_available
|
|
36
45
|
[quantity_available, MAX_DISPLAY_STOCK].min
|
|
@@ -3,6 +3,8 @@ module SpreeCmCommissioner
|
|
|
3
3
|
module MaintenanceTasks
|
|
4
4
|
class CacheInvalidation < MaintenanceTask
|
|
5
5
|
def maintain
|
|
6
|
+
return if ENV['CACHE_AUTO_INVALIDATION_DISABLED'] == 'yes'
|
|
7
|
+
|
|
6
8
|
if maintainable.is_a?(SpreeCmCommissioner::HomepageBackground) || maintainable.is_a?(Spree::Menu)
|
|
7
9
|
SpreeCmCommissioner::HomepageDataLoader.clear_cache
|
|
8
10
|
end
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# `maintain` runs three steps in order:
|
|
8
8
|
# 1. RebuildFromDb — overwrites Redis counters with DB totals (source of truth)
|
|
9
9
|
# 2. AuditCounters — logs any remaining mismatches between Redis and DB
|
|
10
|
+
# 3. SnapshotToDb — writes final aggregates to cm_voting_contestants and cm_voting_session_stats
|
|
10
11
|
#
|
|
11
12
|
# maintainable: SpreeCmCommissioner::VotingSession
|
|
12
13
|
#
|
|
@@ -19,6 +20,7 @@ module SpreeCmCommissioner
|
|
|
19
20
|
ttl = rebuild_ttl
|
|
20
21
|
SpreeCmCommissioner::VoteCounters::RebuildFromDb.call(voting_session_id: maintainable.id, ttl: ttl)
|
|
21
22
|
SpreeCmCommissioner::VoteCounters::AuditCounters.call(voting_session_id: maintainable.id)
|
|
23
|
+
SpreeCmCommissioner::VoteCounters::SnapshotToDb.call(voting_session_id: maintainable.id)
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
# For closed sessions use the fixed 24h constant — closes_at is in the past
|
|
@@ -42,7 +42,6 @@ module SpreeCmCommissioner
|
|
|
42
42
|
base.has_many :reserved_blocks, through: :guests, class_name: 'SpreeCmCommissioner::ReservedBlock'
|
|
43
43
|
base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass', through: :variants
|
|
44
44
|
base.has_many :product_completion_steps, class_name: 'SpreeCmCommissioner::ProductCompletionStep', through: :line_items
|
|
45
|
-
base.has_many :audit_events, class_name: 'SpreeCmCommissioner::AuditEvent', as: :auditable
|
|
46
45
|
|
|
47
46
|
base.delegate :customer, to: :user, allow_nil: true
|
|
48
47
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class SeatLayout < Base
|
|
3
|
-
include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
4
|
-
|
|
5
3
|
has_many :seat_sections, class_name: 'SpreeCmCommissioner::SeatSection', dependent: :destroy
|
|
6
4
|
|
|
7
5
|
has_many :blocks, class_name: 'SpreeCmCommissioner::Block'
|
|
@@ -28,7 +28,9 @@ module SpreeCmCommissioner
|
|
|
28
28
|
:max_paid_votes_per_session,
|
|
29
29
|
:sms_vote_enabled,
|
|
30
30
|
:sms_vote_cost_usd,
|
|
31
|
-
:operator_vote_enabled
|
|
31
|
+
:operator_vote_enabled,
|
|
32
|
+
:votes_weight,
|
|
33
|
+
:voters_weight
|
|
32
34
|
|
|
33
35
|
# voting_credit_scope determines how purchased vote credits are grouped (scoped).
|
|
34
36
|
# Changing this after credits have been allocated will cause inconsistencies:
|
|
@@ -27,8 +27,20 @@ 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
|
+
|
|
30
32
|
scope :ordered, -> { order(:position, :id) }
|
|
31
33
|
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def status_changed_to_eliminated?
|
|
37
|
+
status_changed? && eliminated?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def set_eliminated_at
|
|
41
|
+
self.eliminated_at = Time.current
|
|
42
|
+
end
|
|
43
|
+
|
|
32
44
|
self.whitelisted_ransackable_attributes = %w[name contestant_number status gender category origin]
|
|
33
45
|
end
|
|
34
46
|
end
|
|
@@ -6,9 +6,6 @@ module SpreeCmCommissioner
|
|
|
6
6
|
|
|
7
7
|
base.after_commit :create_inventory_items, on: :create
|
|
8
8
|
base.after_commit :adjust_inventory_items_async, on: :destroy
|
|
9
|
-
|
|
10
|
-
# Create maintaining task to purge product related caches
|
|
11
|
-
base.after_commit { SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: variant.product) }
|
|
12
9
|
end
|
|
13
10
|
|
|
14
11
|
def update_vendor_total_inventory
|
|
@@ -18,10 +15,6 @@ module SpreeCmCommissioner
|
|
|
18
15
|
private
|
|
19
16
|
|
|
20
17
|
def create_inventory_items
|
|
21
|
-
# Skip automatic inventory generation when variant has manual_generate_inventory_items set to true
|
|
22
|
-
# Use case: For variants where inventory items need to be manually created/managed (e.g., external integrations)
|
|
23
|
-
return if variant.manual_generate_inventory_items?
|
|
24
|
-
|
|
25
18
|
SpreeCmCommissioner::InventoryItems::GenerateInventoryItemsJob.perform_later(variant_id: variant.id)
|
|
26
19
|
end
|
|
27
20
|
|
|
@@ -74,6 +74,7 @@ module SpreeCmCommissioner
|
|
|
74
74
|
base.has_many :taxon_option_values, class_name: 'SpreeCmCommissioner::TaxonOptionValue'
|
|
75
75
|
|
|
76
76
|
base.after_commit :send_transaction_email_to_organizers, on: :create
|
|
77
|
+
base.after_commit :send_event_creation_telegram_alert, on: :create
|
|
77
78
|
|
|
78
79
|
base.has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
|
|
79
80
|
base.has_many :places, through: :taxon_places
|
|
@@ -154,6 +155,12 @@ module SpreeCmCommissioner
|
|
|
154
155
|
SpreeCmCommissioner::OrganizersTransactionalEmailNotifier.call(event_id: id)
|
|
155
156
|
end
|
|
156
157
|
|
|
158
|
+
def send_event_creation_telegram_alert
|
|
159
|
+
return unless kind == 'event' && depth == 1
|
|
160
|
+
|
|
161
|
+
SpreeCmCommissioner::EventCreationTelegramAlertSenderJob.perform_later(event_id: id)
|
|
162
|
+
end
|
|
163
|
+
|
|
157
164
|
def sync_event_dates_to_line_items
|
|
158
165
|
return unless event? && depth == 1
|
|
159
166
|
|
|
@@ -2,7 +2,6 @@ module SpreeCmCommissioner
|
|
|
2
2
|
class Trip < Base
|
|
3
3
|
include SpreeCmCommissioner::StoreMetadata
|
|
4
4
|
include SpreeCmCommissioner::RouteType
|
|
5
|
-
include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
6
5
|
|
|
7
6
|
attr_accessor :hours, :minutes, :seconds
|
|
8
7
|
|
|
@@ -26,7 +25,7 @@ module SpreeCmCommissioner
|
|
|
26
25
|
after_commit :update_route_price_range, on: %i[create update]
|
|
27
26
|
|
|
28
27
|
belongs_to :vendor, class_name: 'Spree::Vendor', inverse_of: :trips, optional: false
|
|
29
|
-
belongs_to :product, class_name: 'Spree::Product', inverse_of: :trip, optional:
|
|
28
|
+
belongs_to :product, class_name: 'Spree::Product', inverse_of: :trip, optional: false
|
|
30
29
|
|
|
31
30
|
belongs_to :service_origin, class_name: 'Spree::Taxon', optional: true
|
|
32
31
|
|
|
@@ -6,7 +6,6 @@ module SpreeCmCommissioner
|
|
|
6
6
|
base.include SpreeCmCommissioner::VariantOptionsConcern
|
|
7
7
|
base.include SpreeCmCommissioner::KycBitwise
|
|
8
8
|
base.include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
9
|
-
base.include SpreeCmCommissioner::VariantMetadata
|
|
10
9
|
|
|
11
10
|
base.after_commit :update_vendor_price
|
|
12
11
|
base.validate :validate_option_types
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class Vehicle < Base
|
|
3
3
|
include SpreeCmCommissioner::VehicleKind
|
|
4
|
-
include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
5
4
|
|
|
6
5
|
belongs_to :vendor, class_name: 'Spree::Vendor'
|
|
7
6
|
belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType'
|
|
@@ -14,8 +13,6 @@ module SpreeCmCommissioner
|
|
|
14
13
|
validates :name, presence: true
|
|
15
14
|
validates :license_plate, uniqueness: true, allow_blank: true
|
|
16
15
|
|
|
17
|
-
has_one :seat_layout, through: :vehicle_type
|
|
18
|
-
|
|
19
16
|
self.whitelisted_ransackable_attributes = %w[name license_plate kind]
|
|
20
17
|
|
|
21
18
|
def display_name
|
|
@@ -2,7 +2,6 @@ module SpreeCmCommissioner
|
|
|
2
2
|
class VehicleType < Base
|
|
3
3
|
include SpreeCmCommissioner::StoreMetadata
|
|
4
4
|
include SpreeCmCommissioner::VehicleKind
|
|
5
|
-
include SpreeCmCommissioner::Integrations::IntegrationMappable
|
|
6
5
|
|
|
7
6
|
# This model has no seat_layout column (polymorphic association), so we store the preload_seat_layout_id ID in public_metadata.
|
|
8
7
|
# This lets us check if a seat layout exists without triggering a database query.
|
|
@@ -30,7 +30,6 @@ module SpreeCmCommissioner
|
|
|
30
30
|
base.has_many :nearby_places, -> { order(position: :asc) }, class_name: 'SpreeCmCommissioner::VendorPlace', dependent: :destroy
|
|
31
31
|
|
|
32
32
|
base.has_many :stock_items, through: :variants, class_name: 'Spree::StockItem'
|
|
33
|
-
base.has_many :currency_rates, class_name: 'SpreeCmCommissioner::CurrencyRate', dependent: :destroy
|
|
34
33
|
|
|
35
34
|
base.has_many :taxon_vendors, class_name: 'SpreeCmCommissioner::TaxonVendor'
|
|
36
35
|
base.has_many :taxons, through: :taxon_vendors
|
|
@@ -102,7 +101,6 @@ module SpreeCmCommissioner
|
|
|
102
101
|
base.has_many :boarding_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :boarding_trip_stops
|
|
103
102
|
base.has_many :drop_off_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :drop_off_trip_stops
|
|
104
103
|
base.has_many :pricing_models, class_name: 'SpreeCmCommissioner::PricingModel', foreign_key: :vendor_id, dependent: :destroy
|
|
105
|
-
base.has_many :orders, -> { distinct }, through: :variants, source: :orders
|
|
106
104
|
|
|
107
105
|
base.has_many :agency_categories, -> { where(kind: :agency_category) }, class_name: 'Spree::Taxon', foreign_key: :vendor_id
|
|
108
106
|
|
|
@@ -245,21 +243,6 @@ module SpreeCmCommissioner
|
|
|
245
243
|
end
|
|
246
244
|
|
|
247
245
|
delegate :present?, to: :tenant, prefix: true
|
|
248
|
-
|
|
249
|
-
# Returns the exchange rate between two currencies
|
|
250
|
-
# If no direct rate exists, calculates the inverse rate from the reverse pair
|
|
251
|
-
# Returns 1.0 for identical currencies, nil if no rate is found
|
|
252
|
-
def exchange_rate(from_currency, to_currency)
|
|
253
|
-
return 1.0 if from_currency == to_currency
|
|
254
|
-
|
|
255
|
-
pair = currency_rates.by_pair(from_currency, to_currency).first
|
|
256
|
-
return pair.rate if pair.present?
|
|
257
|
-
|
|
258
|
-
reverse_pair = currency_rates.by_pair(to_currency, from_currency).first
|
|
259
|
-
return (1.0 / reverse_pair.rate).round(6) if reverse_pair.present?
|
|
260
|
-
|
|
261
|
-
nil
|
|
262
|
-
end
|
|
263
246
|
end
|
|
264
247
|
end
|
|
265
248
|
|
|
@@ -20,6 +20,18 @@ module SpreeCmCommissioner
|
|
|
20
20
|
|
|
21
21
|
validates :eliminated_via, presence: true, if: :eliminated?
|
|
22
22
|
|
|
23
|
+
# Uniqueness validation: vote_number must be unique per contestant per voting_session
|
|
24
|
+
# Scope: [show_contestant_id, voting_session_id]
|
|
25
|
+
#
|
|
26
|
+
# | contestant_id | session_id | vote_number | Status | Reason |
|
|
27
|
+
# |---------------|-----------|-------------|--------|---------------------------|
|
|
28
|
+
# | 1 | 1 | 1 | ✓ OK | First record |
|
|
29
|
+
# | 1 | 1 | 1 | ✗ FAIL | Duplicate in same scope |
|
|
30
|
+
# | 1 | 1 | 2 | ✓ OK | Can update/change number |
|
|
31
|
+
# | 2 | 1 | 1 | ✓ OK | Different contestant |
|
|
32
|
+
# | 1 | 2 | 1 | ✓ OK | Different session |
|
|
33
|
+
validates :vote_number, uniqueness: { scope: %i[show_contestant_id voting_session_id], allow_nil: true }
|
|
34
|
+
|
|
23
35
|
delegate :name, :contestant_number, :category, :gender, to: :show_contestant, allow_nil: true
|
|
24
36
|
delegate :can_vote?, to: :voting_session, allow_nil: true
|
|
25
37
|
|