spree_cm_commissioner 2.8.3.pre.pre5 โ 2.8.3.pre.pre7
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/admin/guests_controller.rb +1 -1
- data/app/controllers/spree/admin/order_ticket_transfers_controller.rb +25 -0
- data/app/controllers/spree/admin/stock_managements_controller.rb +1 -1
- data/app/controllers/spree/admin/ticket_transfer_rules_controller.rb +47 -0
- data/app/controllers/spree/admin/ticket_transfers_controller.rb +61 -0
- data/app/controllers/spree/api/v2/storefront/account/recipients_controller.rb +32 -0
- data/app/controllers/spree/api/v2/storefront/ticket_transfer_acceptances_controller.rb +32 -0
- data/app/controllers/spree/api/v2/storefront/ticket_transfers_controller.rb +117 -0
- data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +6 -4
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/trips_controller.rb +11 -0
- data/app/controllers/spree_cm_commissioner/admin/orders_controller_decorator.rb +7 -3
- data/app/factory/spree_cm_commissioner/event_telegram_message_factory.rb +68 -0
- data/app/factory/spree_cm_commissioner/order_telegram_message_factory.rb +31 -17
- data/app/factory/spree_cm_commissioner/telegram_message_factory.rb +6 -0
- data/app/helpers/spree_cm_commissioner/admin/guest_helper.rb +10 -0
- data/app/helpers/spree_cm_commissioner/admin/ticket_transfers_helper.rb +32 -0
- data/app/interactors/spree_cm_commissioner/invalidate_cache_request.rb +5 -1
- data/app/jobs/spree_cm_commissioner/event_creation_telegram_alert_sender_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/expire_ticket_transfer_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/invalidate_cache_request_job.rb +4 -1
- data/app/jobs/spree_cm_commissioner/inventory_items/bulk_adjust_quantities_job.rb +4 -2
- data/app/jobs/spree_cm_commissioner/inventory_items/bulk_adjust_quantities_on_hold_job.rb +4 -2
- data/app/jobs/spree_cm_commissioner/oauth_access_tokens/cleanup_expired_job.rb +11 -0
- data/app/jobs/spree_cm_commissioner/route_metrics/decrease_trip_count_job.rb +8 -2
- data/app/jobs/spree_cm_commissioner/route_metrics/increase_trip_count_job.rb +5 -2
- data/app/jobs/spree_cm_commissioner/vendor_route_metrics/decrease_trip_count_job.rb +17 -0
- data/app/jobs/spree_cm_commissioner/vendor_route_metrics/increase_trip_count_job.rb +14 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +8 -0
- data/app/models/concerns/spree_cm_commissioner/line_items_filter_scope.rb +5 -0
- data/app/models/concerns/spree_cm_commissioner/service_origin.rb +22 -0
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +1 -0
- data/app/models/concerns/spree_cm_commissioner/ticket_transferable.rb +15 -0
- data/app/models/spree_cm_commissioner/guest.rb +20 -0
- data/app/models/spree_cm_commissioner/inventory_item.rb +17 -2
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +7 -0
- data/app/models/spree_cm_commissioner/maintenance_tasks/cache_invalidation.rb +2 -0
- data/app/models/spree_cm_commissioner/notification.rb +10 -1
- data/app/models/spree_cm_commissioner/order_decorator.rb +14 -3
- data/app/models/spree_cm_commissioner/payment_decorator.rb +19 -0
- data/app/models/spree_cm_commissioner/payment_method_decorator.rb +8 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/reserved_block.rb +2 -0
- data/app/models/spree_cm_commissioner/route.rb +6 -1
- data/app/models/spree_cm_commissioner/show_episode.rb +6 -8
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +2 -1
- data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +3 -0
- data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -3
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +9 -0
- data/app/models/spree_cm_commissioner/ticket_transfer.rb +191 -0
- data/app/models/spree_cm_commissioner/ticket_transfer_rule.rb +88 -0
- data/app/models/spree_cm_commissioner/trip.rb +46 -2
- data/app/models/spree_cm_commissioner/user_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/vendor_route_metric.rb +25 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +11 -0
- data/app/models/spree_cm_commissioner/voting_session.rb +2 -1
- data/app/notifications/spree_cm_commissioner/ticket_transfer_accepted_notification.rb +48 -0
- data/app/notifications/spree_cm_commissioner/ticket_transfer_completed_notification.rb +48 -0
- data/app/notifications/spree_cm_commissioner/ticket_transfer_expired_notification.rb +46 -0
- data/app/notifications/spree_cm_commissioner/ticket_transfer_received_notification.rb +48 -0
- data/app/notifications/spree_cm_commissioner/ticket_transfer_rejected_notification.rb +48 -0
- data/app/overrides/spree/admin/products/_form/allow_gift_transfer.html.erb.deface +9 -0
- data/app/overrides/spree/admin/products/_form/allow_transfer.html.erb.deface +9 -0
- data/app/overrides/spree/admin/shared/_order_tabs/ticket_transfers.html.erb.deface +10 -0
- data/app/overrides/spree/admin/shared/sub_menu/_product/ticket_transfers_tab.html.erb.deface +3 -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 +77 -50
- data/app/queries/spree_cm_commissioner/recipient_searcher_query.rb +14 -0
- data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +67 -31
- data/app/queries/spree_cm_commissioner/trip_query.rb +2 -4
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +4 -2
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/tenant/campaign_serializer.rb +1 -5
- data/app/serializers/spree/v2/tenant/dynamic_field_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +1 -0
- data/app/serializers/spree/v2/tenant/vote_package_serializer.rb +9 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/amenity_serializer.rb +3 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +1 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_minimal_serializer.rb +30 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/line_item_minimal_serializer.rb +57 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/recipient_serializer.rb +13 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/reserved_block_serializer.rb +1 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_minimal_serializer.rb +17 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_serializer.rb +20 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_query_result_serializer.rb +2 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +8 -3
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_stop_serializer.rb +1 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vehicle_type_serializer.rb +6 -3
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vendor_serializer.rb +6 -2
- data/app/services/spree_cm_commissioner/advertisements/update_campaign_sorted_ads_ids.rb +33 -0
- data/app/services/spree_cm_commissioner/check_ins/create_bulk.rb +11 -5
- data/app/services/spree_cm_commissioner/checkout/complete_decorator.rb +22 -0
- data/app/services/spree_cm_commissioner/inventory_holds/acquire.rb +3 -0
- data/app/services/spree_cm_commissioner/inventory_holds/convert.rb +7 -2
- data/app/services/spree_cm_commissioner/inventory_holds/release.rb +7 -2
- data/app/services/spree_cm_commissioner/inventory_items/bulk_adjust_quantities.rb +36 -4
- data/app/services/spree_cm_commissioner/inventory_items/bulk_adjust_quantities_on_hold.rb +39 -4
- data/app/services/spree_cm_commissioner/inventory_items/bulk_generate_permanent_items.rb +4 -6
- data/app/services/spree_cm_commissioner/inventory_items/reset.rb +1 -1
- data/app/services/spree_cm_commissioner/oauth_access_tokens/cleanup_expired.rb +59 -0
- data/app/services/spree_cm_commissioner/pricing_models/preview.rb +15 -6
- data/app/services/spree_cm_commissioner/redis_stock/base.rb +2 -1
- data/app/services/spree_cm_commissioner/reserved_blocks/reserve.rb +2 -1
- data/app/services/spree_cm_commissioner/route_metrics/decrease_trip_count.rb +3 -15
- data/app/services/spree_cm_commissioner/route_metrics/increase_trip_count.rb +7 -15
- data/app/services/spree_cm_commissioner/routes/create.rb +0 -5
- data/app/services/spree_cm_commissioner/show_persons/contestant_assigner.rb +51 -0
- data/app/services/spree_cm_commissioner/telegram_alerts/event_creation.rb +35 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/accept.rb +132 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/cancel.rb +54 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/complete.rb +68 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/eligibility_checker.rb +99 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/expire.rb +47 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/fee_calculator.rb +57 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/initiate.rb +98 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/preview_rule.rb +38 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/reject.rb +55 -0
- data/app/services/spree_cm_commissioner/ticket_transfers/transfer_guest.rb +29 -0
- data/app/services/spree_cm_commissioner/transit_order/create.rb +8 -2
- data/app/services/spree_cm_commissioner/trips/create_multi_leg.rb +5 -16
- data/app/services/spree_cm_commissioner/trips/create_single_leg.rb +0 -1
- data/app/services/spree_cm_commissioner/vendor_route_metrics/decrease_trip_count.rb +19 -0
- data/app/services/spree_cm_commissioner/vendor_route_metrics/increase_trip_count.rb +24 -0
- data/app/services/spree_cm_commissioner/voting_leaderboards/combined_result.rb +12 -5
- data/app/services/spree_cm_commissioner/voting_sessions/finalize.rb +12 -2
- data/app/views/spree/admin/guests/_table.html.erb +82 -87
- data/app/views/spree/admin/line_items/_form.html.erb +2 -3
- data/app/views/spree/admin/order_ticket_transfers/show.html.erb +7 -0
- data/app/views/spree/admin/shared/_ticket_transfer_details.html.erb +226 -0
- data/app/views/spree/admin/shared/_ticket_transfer_tabs.html.erb +14 -0
- data/app/views/spree/admin/ticket_transfer_rules/_form.html.erb +193 -0
- data/app/views/spree/admin/ticket_transfer_rules/edit.html.erb +11 -0
- data/app/views/spree/admin/ticket_transfer_rules/index.html.erb +79 -0
- data/app/views/spree/admin/ticket_transfer_rules/new.html.erb +11 -0
- data/app/views/spree/admin/ticket_transfers/_search_form.html.erb +70 -0
- data/app/views/spree/admin/ticket_transfers/_tabs.html.erb +14 -0
- data/app/views/spree/admin/ticket_transfers/index.html.erb +74 -0
- data/app/views/spree/admin/ticket_transfers/show.html.erb +13 -0
- data/app/views/spree/admin/ticket_transfers/state_changes.html.erb +47 -0
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +64 -1
- data/config/locales/km.yml +105 -0
- data/config/routes.rb +20 -0
- data/db/migrate/20260303101440_add_allow_transfer_to_spree_products.rb +5 -0
- data/db/migrate/20260303101907_create_cm_ticket_transfers.rb +32 -0
- data/db/migrate/20260303102316_add_state_to_cm_guests.rb +7 -0
- data/db/migrate/20260408100000_create_cm_ticket_transfer_rules.rb +28 -0
- data/db/migrate/20260410120000_add_transfer_type_to_cm_ticket_transfers.rb +5 -0
- data/db/migrate/20260422120000_add_settlement_status_to_cm_ticket_transfers.rb +6 -0
- data/db/migrate/20260507000000_add_index_to_cm_ticket_transfers_completed_at.rb +5 -0
- data/db/migrate/20260520000000_add_number_to_cm_ticket_transfers.rb +6 -0
- data/db/migrate/20260605120908_add_description_to_cm_dynamic_fields.rb +5 -0
- data/db/migrate/20260608000000_add_allow_gift_transfer_to_spree_products.rb +5 -0
- data/db/migrate/20260608000000_create_cm_vendor_route_metrics.rb +25 -0
- data/db/migrate/20260608152251_add_gender_to_cm_reserved_blocks.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/ticket_transfer_factory.rb +18 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_route_metric_factory.rb +10 -0
- data/lib/spree_cm_commissioner/trip_query_result.rb +34 -1
- data/lib/spree_cm_commissioner/trip_result.rb +52 -22
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/tasks/backfill_route_metrics.rake +21 -0
- data/lib/tasks/backfill_vendor_route_metrics.rake +23 -0
- metadata +81 -5
- data/app/jobs/spree_cm_commissioner/cleanup_expired_access_tokens_job.rb +0 -9
- data/app/overrides/spree/layouts/admin/map_head.html.erb.deface +0 -2
- data/app/services/spree_cm_commissioner/cleanup_expired_access_tokens.rb +0 -52
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6453df013c8c48c7750f2c78315a47a008d71d2d08a18a627e6f23d1cb8e0564
|
|
4
|
+
data.tar.gz: d28c67f073a707a50fe3f44a6bb6c9184fe3403ffc6909585137b73ae8305c39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18c051ff735f3af699821c909d430921a245cae3ba50bf798db8a5e7d20decab213b2432855d28ad22283e9fbdc17e45326a78e14e6c6a9f42d332be94a91b45
|
|
7
|
+
data.tar.gz: 37cbb8aea0043989a2eac1ade7f2184aa71d8a57349c1fd9978c2147787a65aa80134be083cf48d3e9074134eccb3e91197694dca20098140340276333b71e5a
|
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,25 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class OrderTicketTransfersController < Spree::Admin::ResourceController
|
|
4
|
+
include Spree::Admin::OrderConcern
|
|
5
|
+
|
|
6
|
+
helper SpreeCmCommissioner::Admin::TicketTransfersHelper
|
|
7
|
+
|
|
8
|
+
before_action :load_order
|
|
9
|
+
|
|
10
|
+
def show
|
|
11
|
+
@ticket_transfer = model_class.includes(:order, from_guest: :event).find(params[:id])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def model_class
|
|
17
|
+
SpreeCmCommissioner::TicketTransfer
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def object_name
|
|
21
|
+
'spree_cm_commissioner_ticket_transfer'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class TicketTransferRulesController < Spree::Admin::ResourceController
|
|
4
|
+
def index
|
|
5
|
+
@search = model_class.ransack(params[:q])
|
|
6
|
+
@ticket_transfer_rules = @search.result
|
|
7
|
+
.order(ruleable_type: :asc, ruleable_id: :asc, currency: :asc)
|
|
8
|
+
.page(params[:page])
|
|
9
|
+
.per(25)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def model_class
|
|
15
|
+
SpreeCmCommissioner::TicketTransferRule
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def object_name
|
|
19
|
+
'spree_cm_commissioner_ticket_transfer_rule'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def collection_url
|
|
23
|
+
admin_ticket_transfer_rules_url
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def location_after_save
|
|
27
|
+
edit_admin_ticket_transfer_rule_path(@object)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def permitted_resource_params
|
|
31
|
+
params.require(:spree_cm_commissioner_ticket_transfer_rule).permit(
|
|
32
|
+
:ruleable_type,
|
|
33
|
+
:ruleable_id,
|
|
34
|
+
:active,
|
|
35
|
+
:currency,
|
|
36
|
+
:fee_percentage,
|
|
37
|
+
:fee_flat_amount,
|
|
38
|
+
:cooldown_hours,
|
|
39
|
+
:max_transfers_per_ticket,
|
|
40
|
+
:event_cutoff_hours,
|
|
41
|
+
:min_price,
|
|
42
|
+
:max_price
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class TicketTransfersController < Spree::Admin::ResourceController
|
|
4
|
+
helper SpreeCmCommissioner::Admin::TicketTransfersHelper
|
|
5
|
+
|
|
6
|
+
def index
|
|
7
|
+
@search = model_class.includes(:from_user, :to_user, :from_guest).ransack(params[:q])
|
|
8
|
+
@ticket_transfers = @search.result.order(created_at: :desc).page(params[:page]).per(15)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def show
|
|
12
|
+
@ticket_transfer = model_class.includes(:order, from_guest: [:event, { line_item: :order }]).find(params[:id])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def state_changes
|
|
16
|
+
@ticket_transfer = model_class.find(params[:id])
|
|
17
|
+
@state_changes = @ticket_transfer.state_changes.includes(:user).order(created_at: :desc)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def cancel
|
|
21
|
+
@ticket_transfer = model_class.find(params[:id])
|
|
22
|
+
result = SpreeCmCommissioner::TicketTransfers::Cancel.call(
|
|
23
|
+
ticket_transfer: @ticket_transfer,
|
|
24
|
+
acting_user: try_spree_current_user
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if result.success?
|
|
28
|
+
flash[:success] = 'Ticket transfer has been cancelled' # rubocop:disable Rails/I18nLocaleTexts
|
|
29
|
+
else
|
|
30
|
+
flash[:error] = result.error.value
|
|
31
|
+
end
|
|
32
|
+
redirect_to admin_ticket_transfer_path(@ticket_transfer)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def update_settlement_status
|
|
36
|
+
@ticket_transfer = model_class.find(params[:id])
|
|
37
|
+
new_status = params[:settlement_status]
|
|
38
|
+
|
|
39
|
+
unless @ticket_transfer.purchase? && @ticket_transfer.completed?
|
|
40
|
+
flash[:error] = 'Settlement status can only be updated for completed purchase transfers' # rubocop:disable Rails/I18nLocaleTexts
|
|
41
|
+
redirect_to admin_ticket_transfer_path(@ticket_transfer)
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if @ticket_transfer.update(settlement_status: new_status)
|
|
46
|
+
@ticket_transfer.log_settlement_status_changes(user_id: try_spree_current_user&.id)
|
|
47
|
+
flash[:success] = "Settlement status updated to #{new_status}"
|
|
48
|
+
else
|
|
49
|
+
flash[:error] = @ticket_transfer.errors.full_messages.to_sentence.presence || 'Failed to update settlement status'
|
|
50
|
+
end
|
|
51
|
+
redirect_to admin_ticket_transfer_path(@ticket_transfer)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def model_class
|
|
57
|
+
SpreeCmCommissioner::TicketTransfer
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
module Account
|
|
6
|
+
class RecipientsController < ::Spree::Api::V2::ResourceController
|
|
7
|
+
before_action :require_spree_current_user
|
|
8
|
+
|
|
9
|
+
def show
|
|
10
|
+
identifier = params[:q].to_s.strip
|
|
11
|
+
return render_error_payload('Missing q parameter', 400) if identifier.blank?
|
|
12
|
+
|
|
13
|
+
user = SpreeCmCommissioner::RecipientSearcherQuery.new(identifier, MultiTenant.current_tenant_id).call
|
|
14
|
+
|
|
15
|
+
if user
|
|
16
|
+
render_serialized_payload { serialize_resource(user) }
|
|
17
|
+
else
|
|
18
|
+
render_error_payload('User not found', 404)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def resource_serializer
|
|
25
|
+
SpreeCmCommissioner::V2::Storefront::RecipientSerializer
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
class TicketTransferAcceptancesController < ::Spree::Api::V2::ResourceController
|
|
6
|
+
before_action :require_spree_current_user
|
|
7
|
+
|
|
8
|
+
def create
|
|
9
|
+
ticket_transfer = SpreeCmCommissioner::TicketTransfer.find_by!(token: params[:ticket_transfer_id])
|
|
10
|
+
|
|
11
|
+
result = SpreeCmCommissioner::TicketTransfers::Accept.call(
|
|
12
|
+
ticket_transfer: ticket_transfer,
|
|
13
|
+
buyer: spree_current_user
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if result.success?
|
|
17
|
+
render_serialized_payload(201) { serialize_resource(result.value[:ticket_transfer]) }
|
|
18
|
+
else
|
|
19
|
+
render_error_payload(result.error)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def resource_serializer
|
|
26
|
+
SpreeCmCommissioner::V2::Storefront::TicketTransferSerializer
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
class TicketTransfersController < ::Spree::Api::V2::ResourceController
|
|
6
|
+
before_action :require_spree_current_user
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
render_serialized_payload do
|
|
10
|
+
serialize_collection(paginated_collection)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show
|
|
15
|
+
ticket_transfer = model_class.includes(:order, from_guest: [:event, { line_item: :product }]).find_by!(token: params[:id])
|
|
16
|
+
return render_error_payload(I18n.t('ticket_transfer.unauthorized_view'), 403) unless authorized_to_view?(ticket_transfer)
|
|
17
|
+
|
|
18
|
+
render_serialized_payload { serialize_resource(ticket_transfer) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def preview_rule
|
|
22
|
+
result = SpreeCmCommissioner::TicketTransfers::PreviewRule.call(
|
|
23
|
+
from_guest_id: params[:guest_id],
|
|
24
|
+
currency: params[:currency] || 'USD'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if result.success?
|
|
28
|
+
render json: { data: result.value }
|
|
29
|
+
else
|
|
30
|
+
render_error_payload(result.error)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create
|
|
35
|
+
result = SpreeCmCommissioner::TicketTransfers::Initiate.call(
|
|
36
|
+
from_user_id: spree_current_user.id,
|
|
37
|
+
to_user_id: ticket_transfer_params[:to_user_id],
|
|
38
|
+
from_guest_id: ticket_transfer_params[:guest_id],
|
|
39
|
+
price: ticket_transfer_params[:price] || 0,
|
|
40
|
+
currency: ticket_transfer_params[:currency] || 'USD',
|
|
41
|
+
expires_at: ticket_transfer_params[:expires_at],
|
|
42
|
+
transfer_type: ticket_transfer_params[:transfer_type] || 'purchase'
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if result.success?
|
|
46
|
+
render_serialized_payload(201) { serialize_resource(result.value[:ticket_transfer]) }
|
|
47
|
+
else
|
|
48
|
+
render_error_payload(result.error)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cancel
|
|
53
|
+
ticket_transfer = model_class.find_by!(token: params[:id])
|
|
54
|
+
|
|
55
|
+
result = SpreeCmCommissioner::TicketTransfers::Cancel.call(
|
|
56
|
+
ticket_transfer: ticket_transfer,
|
|
57
|
+
acting_user: spree_current_user
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if result.success?
|
|
61
|
+
render_serialized_payload { serialize_resource(result.value[:ticket_transfer]) }
|
|
62
|
+
else
|
|
63
|
+
render_error_payload(result.error)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def reject
|
|
68
|
+
ticket_transfer = model_class.find_by!(token: params[:id])
|
|
69
|
+
|
|
70
|
+
result = SpreeCmCommissioner::TicketTransfers::Reject.call(
|
|
71
|
+
ticket_transfer: ticket_transfer,
|
|
72
|
+
acting_user: spree_current_user
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if result.success?
|
|
76
|
+
render_serialized_payload { serialize_resource(result.value[:ticket_transfer]) }
|
|
77
|
+
else
|
|
78
|
+
render_error_payload(result.error)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def model_class
|
|
85
|
+
SpreeCmCommissioner::TicketTransfer
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def collection
|
|
89
|
+
SpreeCmCommissioner::TicketTransfer.includes(:order,
|
|
90
|
+
from_guest: [:event, { line_item: :product }]
|
|
91
|
+
).where(from_user_id: spree_current_user.id)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def resource_serializer
|
|
95
|
+
SpreeCmCommissioner::V2::Storefront::TicketTransferSerializer
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def collection_serializer
|
|
99
|
+
SpreeCmCommissioner::V2::Storefront::TicketTransferSerializer
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def ticket_transfer_params
|
|
103
|
+
params.require(:ticket_transfer).permit(:to_user_id, :guest_id, :price, :currency, :expires_at, :transfer_type)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# When sending to a specific user, only sender and that buyer can access.
|
|
107
|
+
def authorized_to_view?(ticket_transfer)
|
|
108
|
+
return true if ticket_transfer.to_user_id.blank?
|
|
109
|
+
|
|
110
|
+
current_user_id = spree_current_user&.id
|
|
111
|
+
ticket_transfer.from_user_id == current_user_id || ticket_transfer.to_user_id == current_user_id
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -39,7 +39,6 @@ module Spree
|
|
|
39
39
|
params[:date],
|
|
40
40
|
params[:route_type],
|
|
41
41
|
params[:vendor_id],
|
|
42
|
-
params[:featured],
|
|
43
42
|
params[:number_of_guests],
|
|
44
43
|
resource_includes&.sort&.join(','),
|
|
45
44
|
sparse_fields&.sort&.join(','),
|
|
@@ -65,8 +64,7 @@ module Spree
|
|
|
65
64
|
'trips.vendor',
|
|
66
65
|
'trips.vendor.logo',
|
|
67
66
|
'trips.vehicle_type',
|
|
68
|
-
'trips.vehicle_type.vehicle_photos'
|
|
69
|
-
'trips.amenities'
|
|
67
|
+
'trips.vehicle_type.vehicle_photos'
|
|
70
68
|
]
|
|
71
69
|
end
|
|
72
70
|
|
|
@@ -100,7 +98,11 @@ module Spree
|
|
|
100
98
|
|
|
101
99
|
# override
|
|
102
100
|
def serializer_params
|
|
103
|
-
|
|
101
|
+
super.merge(
|
|
102
|
+
exclude_vendor_kind_option_types: true,
|
|
103
|
+
exclude_vendor_kind_option_values: true,
|
|
104
|
+
exclude_vehicle_type_amenities: true
|
|
105
|
+
)
|
|
104
106
|
end
|
|
105
107
|
|
|
106
108
|
# override
|
|
@@ -25,6 +25,17 @@ module Spree
|
|
|
25
25
|
def resource_serializer
|
|
26
26
|
Spree::V2::Tenant::TripSerializer
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
# override
|
|
30
|
+
def serializer_params
|
|
31
|
+
super.merge(
|
|
32
|
+
include_details: include_details?
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def include_details?
|
|
37
|
+
params.fetch(:include_details, 'true') == 'true'
|
|
38
|
+
end
|
|
28
39
|
end
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -40,9 +40,13 @@ module SpreeCmCommissioner
|
|
|
40
40
|
|
|
41
41
|
# override
|
|
42
42
|
def cancel
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
if @order.guests_in_transfer?
|
|
44
|
+
flash[:error] = Spree.t('admin.orders.cannot_cancel_guest_transfer')
|
|
45
|
+
else
|
|
46
|
+
internal_note = params.dig(:order, :internal_note)
|
|
47
|
+
@order.canceled_by(try_spree_current_user, cancellation_reason: internal_note)
|
|
48
|
+
flash[:success] = Spree.t(:order_canceled)
|
|
49
|
+
end
|
|
46
50
|
redirect_back fallback_location: spree.edit_admin_order_url(@order)
|
|
47
51
|
end
|
|
48
52
|
|
|
@@ -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
|
|
@@ -48,7 +48,7 @@ module SpreeCmCommissioner
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def line_item_content(line_item)
|
|
51
|
-
return
|
|
51
|
+
return transit_line_item_content(line_item) if line_item.transit?
|
|
52
52
|
|
|
53
53
|
text = []
|
|
54
54
|
|
|
@@ -64,8 +64,8 @@ module SpreeCmCommissioner
|
|
|
64
64
|
def pretty_date_for(line_item)
|
|
65
65
|
return nil unless line_item.date_present?
|
|
66
66
|
|
|
67
|
-
from_date =
|
|
68
|
-
to_date =
|
|
67
|
+
from_date = pretty_datetime(line_item.from_date)
|
|
68
|
+
to_date = pretty_datetime(line_item.to_date)
|
|
69
69
|
|
|
70
70
|
if from_date == to_date
|
|
71
71
|
"๐๏ธ #{from_date}"
|
|
@@ -84,7 +84,7 @@ module SpreeCmCommissioner
|
|
|
84
84
|
text << "Email: #{inline_code(order.email)}" if order.email.present?
|
|
85
85
|
text << "Delivery Address: #{formatted_shipping_address.presence || 'N/A'}" if order.delivery_required?
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
append_transit_footer(text) if transit_order?
|
|
88
88
|
|
|
89
89
|
if show_details_link && order.guests.any?
|
|
90
90
|
text << ''
|
|
@@ -132,12 +132,12 @@ module SpreeCmCommissioner
|
|
|
132
132
|
|
|
133
133
|
private
|
|
134
134
|
|
|
135
|
-
def
|
|
136
|
-
|
|
135
|
+
def transit_order?
|
|
136
|
+
selected_line_items.any?(&:transit?)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def intercity_taxi_order?
|
|
140
|
-
selected_line_items.any? { |li|
|
|
140
|
+
selected_line_items.any? { |li| trip_for(li)&.intercity_taxi? }
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def trip_for(line_item)
|
|
@@ -147,10 +147,10 @@ module SpreeCmCommissioner
|
|
|
147
147
|
@trip_cache[line_item.trip_id] ||= SpreeCmCommissioner::Trip.find_by(id: line_item.trip_id)
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
def
|
|
150
|
+
def transit_line_item_content(line_item)
|
|
151
151
|
text = []
|
|
152
|
-
route_text =
|
|
153
|
-
departure_text =
|
|
152
|
+
route_text = transit_route_text(line_item)
|
|
153
|
+
departure_text = transit_departure_text(line_item)
|
|
154
154
|
text << bold('๐ Trip Details')
|
|
155
155
|
text << "Route: #{route_text}" if route_text.present?
|
|
156
156
|
text << "Passengers: #{line_item.passenger_count || line_item.quantity}"
|
|
@@ -159,7 +159,7 @@ module SpreeCmCommissioner
|
|
|
159
159
|
text.compact.join("\n")
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
def
|
|
162
|
+
def transit_route_text(line_item)
|
|
163
163
|
trip = trip_for(line_item)
|
|
164
164
|
return line_item.product.name if trip.blank?
|
|
165
165
|
|
|
@@ -171,21 +171,35 @@ module SpreeCmCommissioner
|
|
|
171
171
|
vehicle.present? ? "#{parts} (#{vehicle})" : parts
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
def
|
|
174
|
+
def transit_departure_text(line_item)
|
|
175
175
|
return nil unless line_item.date_present?
|
|
176
176
|
|
|
177
177
|
line_item.from_date.strftime('%b %d, %Y ยท %H:%M')
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
def nationality_text
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
grouped = order.saved_guests.group_by { |sg| sg.nationality_group&.humanize }
|
|
182
|
+
grouped.delete(nil)
|
|
183
|
+
return nil if grouped.empty?
|
|
183
184
|
|
|
184
|
-
|
|
185
|
+
grouped.map { |nationality_group, guests| customer_type_summary(nationality_group, guests) }.join(', ')
|
|
185
186
|
end
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
# e.g. "Local (Adult x1, Child x1)". age_group is NOT NULL, so it is always present.
|
|
189
|
+
def customer_type_summary(nationality_group, guests)
|
|
190
|
+
age_breakdown = guests
|
|
191
|
+
.group_by { |sg| sg.age_group.humanize }
|
|
192
|
+
.map { |age_group, age_guests| "#{age_group} x#{age_guests.count}" }
|
|
193
|
+
.join(', ')
|
|
194
|
+
|
|
195
|
+
"#{nationality_group} (#{age_breakdown})"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def append_transit_footer(text)
|
|
199
|
+
nationality = nationality_text
|
|
200
|
+
text << "Nationality: #{nationality}" if nationality.present?
|
|
201
|
+
|
|
202
|
+
return unless intercity_taxi_order?
|
|
189
203
|
|
|
190
204
|
pickup = selected_line_items.filter_map(&:pickup_map_place).first
|
|
191
205
|
dropoff = selected_line_items.filter_map(&:dropoff_map_place).first
|
|
@@ -61,6 +61,16 @@ module SpreeCmCommissioner
|
|
|
61
61
|
'badge-info'
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
|
+
|
|
65
|
+
def guest_state_badge(guest)
|
|
66
|
+
badge_class = case guest.state
|
|
67
|
+
when 'active' then 'badge-success'
|
|
68
|
+
when 'locked' then 'badge-warning'
|
|
69
|
+
when 'transferred' then 'badge-secondary'
|
|
70
|
+
else 'badge-info'
|
|
71
|
+
end
|
|
72
|
+
content_tag(:span, guest.state.humanize, class: "badge #{badge_class}")
|
|
73
|
+
end
|
|
64
74
|
end
|
|
65
75
|
end
|
|
66
76
|
end
|