spree_cm_commissioner 2.8.3 → 2.8.4.pre.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/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/system/waiting_room_controller.rb +15 -0
- data/app/controllers/spree/admin/taxons_controller_decorator.rb +5 -0
- 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/guests_controller.rb +7 -5
- 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/transit/draft_orders_controller.rb +3 -1
- data/app/controllers/spree/api/v2/tenant/transit/draft_orders_controller.rb +3 -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/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/pin_code_sender.rb +62 -5
- data/app/interactors/spree_cm_commissioner/waiting_guests_caller.rb +86 -10
- data/app/jobs/spree_cm_commissioner/expire_ticket_transfer_job.rb +10 -0
- data/app/jobs/spree_cm_commissioner/telegram_gateway/pin_code_sender_job.rb +18 -0
- 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/jobs/spree_cm_commissioner/waiting_room/publish_lobby_path_job.rb +17 -0
- data/app/jobs/spree_cm_commissioner/waiting_room/stamp_queue_positions_job.rb +84 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +16 -2
- data/app/models/concerns/spree_cm_commissioner/line_item_open_dated_trippable.rb +50 -7
- data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +0 -1
- data/app/models/concerns/spree_cm_commissioner/line_items_filter_scope.rb +5 -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/line_item_decorator.rb +7 -0
- data/app/models/spree_cm_commissioner/notification.rb +10 -1
- data/app/models/spree_cm_commissioner/order_decorator.rb +13 -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/pin_code.rb +62 -9
- data/app/models/spree_cm_commissioner/product_decorator.rb +6 -2
- data/app/models/spree_cm_commissioner/reserved_block.rb +2 -0
- 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/taxon_ad_banner.rb +12 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -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 +33 -12
- data/app/models/spree_cm_commissioner/user_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/vendor_route_metric.rb +25 -0
- 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/taxons/_form/assets_form.html.erb.deface +10 -1
- data/app/queries/spree_cm_commissioner/multi_leg_trips_query.rb +31 -8
- data/app/queries/spree_cm_commissioner/recipient_searcher_query.rb +14 -0
- data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +57 -5
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +4 -2
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +4 -2
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -0
- data/app/serializers/spree/v2/tenant/dynamic_field_serializer.rb +1 -1
- 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/pin_code_serializer.rb +1 -1
- 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 +4 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +2 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_stop_serializer.rb +1 -0
- data/app/services/spree_cm_commissioner/cart/add_guest.rb +6 -1
- data/app/services/spree_cm_commissioner/cart/create_guest.rb +61 -0
- data/app/services/spree_cm_commissioner/cart/remove_guest.rb +6 -1
- 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_items/reset.rb +1 -1
- data/app/services/spree_cm_commissioner/open_dated_trips/redeem.rb +80 -36
- data/app/services/spree_cm_commissioner/reserved_blocks/reserve.rb +2 -1
- data/app/services/spree_cm_commissioner/telegram_gateway/pin_code_sender.rb +99 -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 +48 -14
- data/app/services/spree_cm_commissioner/trips/add_ons/create.rb +124 -0
- data/app/services/spree_cm_commissioner/trips/add_ons/update_price.rb +36 -0
- data/app/services/spree_cm_commissioner/trips/create_multi_leg.rb +1 -2
- data/app/services/spree_cm_commissioner/trips/variants/create.rb +1 -2
- 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/waiting_room/publish_lobby_path.rb +48 -0
- data/app/services/spree_cm_commissioner/waiting_room_lobby_metadata_fetcher.rb +47 -0
- data/app/services/telegram_gateway_adapter/client.rb +124 -0
- data/app/views/spree/admin/guests/_table.html.erb +82 -87
- 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/system/waiting_room/show.html.erb +53 -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/locales/en.yml +68 -6
- data/config/locales/km.yml +74 -4
- data/config/routes.rb +22 -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/db/migrate/20260610000001_add_delivery_channel_to_cm_pin_codes.rb +6 -0
- data/db/migrate/20260610000001_drop_is_open_dated_from_cm_trips.rb +6 -0
- data/db/migrate/20260614000001_change_code_limit_in_cm_pin_codes.rb +5 -0
- data/db/migrate/20260615000002_add_index_to_code_on_cm_pin_codes.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/transit/trip_form.rb +0 -13
- data/lib/spree_cm_commissioner/trip_query_result.rb +46 -6
- data/lib/spree_cm_commissioner/trip_result.rb +9 -7
- 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 +89 -6
- data/app/services/spree_cm_commissioner/trips/create_open_dated_trip.rb +0 -98
- data/app/services/spree_cm_commissioner/trips/update_open_dated_trip.rb +0 -67
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6b4cb4f14de6554d09bdd97872267ca1f23e73d144401b49a8969203e601b910
|
|
4
|
+
data.tar.gz: 454758bb34c6df3a4f1e2272b65bb19f57e7d829c06c045d7f748a72a56cb42f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3dea963b405471ddcf3a1b7819bab6d7ffca7b76f0567b6a0092262b5b8d980db83fc052c4913f06ff42921727bc4168c2c044beeeb38ddc65ef242071918f34
|
|
7
|
+
data.tar.gz: f9a841e7c01222124a041e65adf42b7e6d57b53fdc8e731c08e595dbceb601fb45fbe7ef6850df709d454b75220c4e58da2af1f8c2d0bb37d58ab00bc4c2031c
|
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
|
|
@@ -4,7 +4,10 @@ module Spree
|
|
|
4
4
|
class WaitingRoomController < Spree::Admin::BaseController
|
|
5
5
|
def show
|
|
6
6
|
@fetcher = SpreeCmCommissioner::WaitingRoomSystemMetadataFetcher.new
|
|
7
|
+
@lobby_fetcher = SpreeCmCommissioner::WaitingRoomLobbyMetadataFetcher.new
|
|
8
|
+
|
|
7
9
|
@fetcher.load_document_data
|
|
10
|
+
@lobby_fetcher.load_document_data
|
|
8
11
|
|
|
9
12
|
@active_sesions_count = SpreeCmCommissioner::WaitingRoomSession.active.count
|
|
10
13
|
end
|
|
@@ -29,6 +32,18 @@ module Spree
|
|
|
29
32
|
|
|
30
33
|
redirect_back fallback_location: admin_system_waiting_room_path
|
|
31
34
|
end
|
|
35
|
+
|
|
36
|
+
def publish_lobby_path
|
|
37
|
+
result = SpreeCmCommissioner::WaitingRoom::PublishLobbyPath.call
|
|
38
|
+
|
|
39
|
+
if result.success?
|
|
40
|
+
flash[:success] = "Published waiting guests records path: #{result.value[:records_path]}"
|
|
41
|
+
else
|
|
42
|
+
flash[:error] = result.error.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
redirect_back fallback_location: admin_system_waiting_room_path
|
|
46
|
+
end
|
|
32
47
|
end
|
|
33
48
|
end
|
|
34
49
|
end
|
|
@@ -27,6 +27,10 @@ module Spree
|
|
|
27
27
|
remove_asset(@taxon.home_banner)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def remove_ad_banner
|
|
31
|
+
remove_asset(@taxon.ad_banner)
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
def remove_video_banner
|
|
31
35
|
remove_asset(@taxon.video_banner)
|
|
32
36
|
end
|
|
@@ -48,6 +52,7 @@ module Spree
|
|
|
48
52
|
@taxon.build_app_banner(attachment: permitted_resource_params.delete(:app_banner)) if permitted_resource_params[:app_banner]
|
|
49
53
|
@taxon.build_web_banner(attachment: permitted_resource_params.delete(:web_banner)) if permitted_resource_params[:web_banner]
|
|
50
54
|
@taxon.build_home_banner(attachment: permitted_resource_params.delete(:home_banner)) if permitted_resource_params[:home_banner]
|
|
55
|
+
@taxon.build_ad_banner(attachment: permitted_resource_params.delete(:ad_banner)) if permitted_resource_params[:ad_banner]
|
|
51
56
|
@taxon.build_video_banner(attachment: permitted_resource_params.delete(:video_banner)) if permitted_resource_params[:video_banner]
|
|
52
57
|
end
|
|
53
58
|
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
|
|
@@ -31,13 +31,15 @@ module Spree
|
|
|
31
31
|
def create
|
|
32
32
|
spree_authorize! :update, spree_current_order, order_token
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
result = SpreeCmCommissioner::Cart::CreateGuest.call(
|
|
35
|
+
line_item: parent,
|
|
36
|
+
options: guest_params
|
|
37
|
+
)
|
|
35
38
|
|
|
36
|
-
if
|
|
37
|
-
|
|
38
|
-
render_serialized_payload(201) { serialize_resource(resource) }
|
|
39
|
+
if result.success?
|
|
40
|
+
render_serialized_payload(201) { serialize_resource(result.value) }
|
|
39
41
|
else
|
|
40
|
-
render_error_payload(
|
|
42
|
+
render_error_payload(result.value.errors, 422)
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
|
|
@@ -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
|
|
@@ -11,6 +11,7 @@ module Spree
|
|
|
11
11
|
# - inbound_date: Date of inbound transit (optional)
|
|
12
12
|
# - outbound_legs: Array of outbound leg details (required)
|
|
13
13
|
# - inbound_legs: Array of inbound leg details (optional)
|
|
14
|
+
# - include_return: Whether to add the trip's "return included" add-on as a line item (optional)
|
|
14
15
|
def create
|
|
15
16
|
@outbound_legs = params[:outbound_legs].is_a?(Array) && params[:outbound_legs].any? ? build_legs(:outbound, params[:outbound_legs]) : []
|
|
16
17
|
@inbound_legs = params[:inbound_legs].is_a?(Array) && params[:inbound_legs].any? ? build_legs(:inbound, params[:inbound_legs]) : []
|
|
@@ -20,7 +21,8 @@ module Spree
|
|
|
20
21
|
inbound_date: params[:inbound_date]&.to_date,
|
|
21
22
|
outbound_legs: @outbound_legs,
|
|
22
23
|
inbound_legs: @inbound_legs,
|
|
23
|
-
user: spree_current_user
|
|
24
|
+
user: spree_current_user,
|
|
25
|
+
include_return: ActiveModel::Type::Boolean.new.cast(params[:include_return])
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
if result.success?
|
|
@@ -11,6 +11,7 @@ module Spree
|
|
|
11
11
|
# - inbound_date: Date of inbound transit (optional)
|
|
12
12
|
# - outbound_legs: Array of outbound leg details (required)
|
|
13
13
|
# - inbound_legs: Array of inbound leg details (optional)
|
|
14
|
+
# - include_return: Whether to add the trip's "return included" add-on as a line item (optional)
|
|
14
15
|
def create
|
|
15
16
|
@outbound_legs = params[:outbound_legs].is_a?(Array) && params[:outbound_legs].any? ? build_legs(:outbound, params[:outbound_legs]) : []
|
|
16
17
|
@inbound_legs = params[:inbound_legs].is_a?(Array) && params[:inbound_legs].any? ? build_legs(:inbound, params[:inbound_legs]) : []
|
|
@@ -20,7 +21,8 @@ module Spree
|
|
|
20
21
|
inbound_date: params[:inbound_date]&.to_date,
|
|
21
22
|
outbound_legs: @outbound_legs,
|
|
22
23
|
inbound_legs: @inbound_legs,
|
|
23
|
-
user: spree_current_user
|
|
24
|
+
user: spree_current_user,
|
|
25
|
+
include_return: ActiveModel::Type::Boolean.new.cast(params[:include_return])
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
if result.success?
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Admin
|
|
3
|
+
module TicketTransfersHelper
|
|
4
|
+
def ticket_transfer_state_badge(state)
|
|
5
|
+
badge_class = case state
|
|
6
|
+
when 'pending' then 'badge-warning'
|
|
7
|
+
when 'accepted' then 'badge-info'
|
|
8
|
+
when 'completed' then 'badge-success'
|
|
9
|
+
when 'rejected' then 'badge-danger'
|
|
10
|
+
when 'expired' then 'badge-danger' # rubocop:disable Lint/DuplicateBranch
|
|
11
|
+
when 'cancelled' then 'badge-secondary'
|
|
12
|
+
else 'badge-secondary' # rubocop:disable Lint/DuplicateBranch
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
content_tag(:span, state.humanize, class: "badge #{badge_class}")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ticket_transfer_settlement_status_badge(ticket_transfer)
|
|
19
|
+
badge_class = case ticket_transfer.settlement_status
|
|
20
|
+
when 'pending' then 'badge-warning'
|
|
21
|
+
when 'ready' then 'badge-info'
|
|
22
|
+
when 'disputed' then 'badge-danger'
|
|
23
|
+
when 'resolved' then 'badge-primary'
|
|
24
|
+
when 'completed' then 'badge-success'
|
|
25
|
+
else 'badge-secondary'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
content_tag(:span, ticket_transfer.settlement_status.humanize, class: "badge #{badge_class}")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -6,7 +6,7 @@ module SpreeCmCommissioner
|
|
|
6
6
|
context.fail!(message: I18n.t('pincode_sender.pincode.blank')) if context.pin_code.nil?
|
|
7
7
|
|
|
8
8
|
if context.pin_code.phone_number?
|
|
9
|
-
|
|
9
|
+
send_phone_otp
|
|
10
10
|
else
|
|
11
11
|
send_email
|
|
12
12
|
end
|
|
@@ -16,18 +16,73 @@ module SpreeCmCommissioner
|
|
|
16
16
|
|
|
17
17
|
private
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# Channel selection for phone-number OTPs lives here so the routing is
|
|
20
|
+
# easy to find and reason about. Telegram Gateway is primary; SMS is the fallback.
|
|
21
|
+
def send_phone_otp
|
|
22
|
+
if telegram_gateway_available?
|
|
23
|
+
send_via_telegram_gateway
|
|
24
|
+
else
|
|
25
|
+
send_via_sms
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def telegram_gateway_available?
|
|
30
|
+
return false unless telegram_gateway_enabled?
|
|
31
|
+
return false if telegram_gateway_api_key.blank?
|
|
32
|
+
|
|
33
|
+
ability = telegram_gateway_adapter.check_send_ability(context.pin_code.contact)
|
|
34
|
+
context.telegram_gateway_request_id = ability.request_id if ability.ok?
|
|
35
|
+
ability.ok?
|
|
36
|
+
rescue TelegramGatewayAdapter::Error, Faraday::Error
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def send_via_telegram_gateway
|
|
20
41
|
from_number = sms_from_number
|
|
21
42
|
return if from_number.blank?
|
|
22
43
|
|
|
23
|
-
|
|
44
|
+
# Save the chosen channel + the Telegram request_id synchronously so
|
|
45
|
+
# (a) the API response already reflects the channel for the mobile UI,
|
|
46
|
+
# (b) verification can reach Telegram even if the user submits the OTP
|
|
47
|
+
# before the async send job has run. For Telegram-delivered codes
|
|
48
|
+
# the `code` column stores Telegram's request_id (Telegram generates
|
|
49
|
+
# and holds the actual OTP).
|
|
50
|
+
context.pin_code.update!(
|
|
51
|
+
delivery_channel: :telegram_gateway,
|
|
52
|
+
code: context.telegram_gateway_request_id
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
SpreeCmCommissioner::TelegramGateway::PinCodeSenderJob.perform_later(
|
|
56
|
+
pin_code_id: context.pin_code.id,
|
|
57
|
+
from: from_number,
|
|
58
|
+
request_id: context.telegram_gateway_request_id,
|
|
59
|
+
tenant_id: context.pin_code&.application&.tenant_id
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def send_via_sms
|
|
64
|
+
from_number = sms_from_number
|
|
65
|
+
return if from_number.blank?
|
|
66
|
+
|
|
67
|
+
SpreeCmCommissioner::SmsPinCodeJob.perform_later(
|
|
68
|
+
pin_code_id: context.pin_code.id,
|
|
24
69
|
from: from_number,
|
|
25
70
|
to: context.pin_code.contact,
|
|
26
71
|
body: I18n.t('pincode_sender.sms.body', code: context.pin_code.code, readable_type: context.pin_code.readable_type),
|
|
27
72
|
tenant_id: context.pin_code&.application&.tenant_id
|
|
28
|
-
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def telegram_gateway_enabled?
|
|
77
|
+
ENV['TELEGRAM_GATEWAY_ENABLED'] == 'yes'
|
|
78
|
+
end
|
|
29
79
|
|
|
30
|
-
|
|
80
|
+
def telegram_gateway_api_key
|
|
81
|
+
@telegram_gateway_api_key ||= ENV.fetch('TELEGRAM_GATEWAY_API_KEY', nil)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def telegram_gateway_adapter
|
|
85
|
+
@telegram_gateway_adapter ||= TelegramGatewayAdapter::Client.new
|
|
31
86
|
end
|
|
32
87
|
|
|
33
88
|
def sms_from_number
|
|
@@ -38,6 +93,8 @@ module SpreeCmCommissioner
|
|
|
38
93
|
end
|
|
39
94
|
|
|
40
95
|
def send_email
|
|
96
|
+
context.pin_code.update!(delivery_channel: :email)
|
|
97
|
+
|
|
41
98
|
SpreeCmCommissioner::PinCodeMailer.send_pin_code(
|
|
42
99
|
context.pin_code.id,
|
|
43
100
|
context.pin_code.readable_type,
|