spree_cm_commissioner 2.9.2 → 2.9.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/Gemfile.lock +1 -1
- data/app/controllers/concerns/spree_cm_commissioner/load_test_account_scope.rb +14 -21
- data/app/controllers/concerns/spree_cm_commissioner/load_test_bypassable.rb +29 -0
- data/app/controllers/spree/api/chatrace/guests_controller.rb +1 -1
- data/app/controllers/spree/api/v2/storefront/account/guest_dynamic_fields_controller.rb +19 -48
- data/app/controllers/spree/api/v2/storefront/account/mark_guest_info_complete_controller.rb +2 -2
- data/app/controllers/spree/api/v2/storefront/account/orders_controller_decorator.rb +5 -15
- data/app/controllers/spree/api/v2/storefront/account/saved_guests_controller.rb +65 -0
- data/app/controllers/spree/api/v2/storefront/draft_orders_controller.rb +3 -0
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +10 -9
- data/app/controllers/spree/api/v2/storefront/order_histories_controller.rb +0 -1
- data/app/controllers/spree/api/v2/tenant/account/saved_guests_controller.rb +70 -0
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +3 -1
- data/app/controllers/spree/api/v2/tenant/guests_controller.rb +11 -21
- data/app/controllers/spree/api/v2/tenant/order_histories_controller.rb +0 -1
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +7 -1
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +3 -14
- data/app/jobs/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage_batch_job.rb +28 -0
- data/app/models/concerns/spree_cm_commissioner/guest_data_fill_stage_concern.rb +82 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +4 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +13 -31
- data/app/models/spree_cm_commissioner/current.rb +6 -3
- data/app/models/spree_cm_commissioner/dynamic_field.rb +12 -0
- data/app/models/spree_cm_commissioner/guest.rb +1 -144
- data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +43 -71
- data/app/models/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage.rb +21 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +26 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +0 -22
- data/app/models/spree_cm_commissioner/product_dynamic_field.rb +17 -0
- data/app/models/spree_cm_commissioner/request_guard.rb +19 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +26 -1
- data/app/models/spree_cm_commissioner/voting_contestant.rb +13 -2
- data/app/queries/spree_cm_commissioner/event_chart_queries.rb +2 -2
- data/app/queries/spree_cm_commissioner/pie_chart_event_aggregator_queries.rb +2 -2
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +2 -2
- data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +3 -1
- data/app/serializers/spree/v2/tenant/saved_guest_serializer.rb +23 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/cart_serializer_decorator.rb +1 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -6
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_serializer.rb +2 -2
- data/app/services/spree_cm_commissioner/{cart/create_guest.rb → guests/create.rb} +12 -10
- data/app/services/spree_cm_commissioner/guests/refresh_data_fill_stage.rb +20 -0
- data/app/services/spree_cm_commissioner/guests/send_dynamic_field_notification.rb +15 -0
- data/app/services/spree_cm_commissioner/guests/update.rb +68 -0
- data/app/services/spree_cm_commissioner/inventory_holds/validate_limits.rb +8 -3
- data/app/services/spree_cm_commissioner/load_test/destroy_accounts.rb +7 -10
- data/app/services/spree_cm_commissioner/load_test/generate_booking_ticket_data.rb +83 -19
- data/app/services/spree_cm_commissioner/order/guests/update.rb +5 -8
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +10 -3
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +20 -2
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +15 -9
- data/app/views/spree/admin/variants/fixture.html.erb +1 -1
- data/config/initializers/spree_permitted_attributes.rb +19 -0
- data/config/load_test_flows/tenant.yml +47 -0
- data/config/locales/en.yml +2 -5
- data/config/locales/km.yml +2 -0
- data/config/routes.rb +3 -1
- data/db/migrate/20260713022227_add_advanced_to_episode_id_to_cm_voting_contestants.rb +8 -0
- data/db/migrate/20260714002626_rename_data_fill_stage_phase_on_cm_guests.rb +5 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/tasks/recompute_guest_data_fill_stage.rake +19 -0
- metadata +17 -12
- data/app/controllers/spree/api/v2/storefront/saved_guests_controller.rb +0 -77
- data/app/interactors/spree_cm_commissioner/guest_dynamic_field_notification_sender.rb +0 -11
- data/app/interactors/spree_cm_commissioner/guest_dynamic_fields_manager.rb +0 -33
- data/app/serializers/spree/v2/storefront/order_serializer_decorator.rb +0 -63
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_minimal_serializer.rb +0 -30
- data/app/serializers/spree_cm_commissioner/v2/storefront/line_item_minimal_serializer.rb +0 -57
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_minimal_serializer.rb +0 -17
- data/app/services/spree_cm_commissioner/update_guest_service.rb +0 -129
- data/app/services/spree_cm_commissioner/users/incomplete_guest_checker_service.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73795eb4d207d3bf219b7c5913512b6b82ff71b71f5f9c5ea41acd18a016ade6
|
|
4
|
+
data.tar.gz: 44ed0c0b84771995b3f858d6d3db3e5c8feb4cb872a5d23981022837c2c8f847
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 56fa3d866b2de53c7f58978403eb1a04c26a0da14a95d4a8447502dfed4123db703e84ef733385aa0b271774940031a362096a10b3606f0b6dda63dbcb3136ba
|
|
7
|
+
data.tar.gz: 8343f2ec6ff570e80a833272763431b699d68b926648f5b0a98a8929fd321aa4df7636461cbd2b94c8685dfaef162131440cdd5a02a3610ab1a87ea090d7a02d
|
data/Gemfile.lock
CHANGED
|
@@ -10,37 +10,30 @@ module SpreeCmCommissioner
|
|
|
10
10
|
raise NotImplementedError, "#{self.class} must implement #load_test_tenant"
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
# covering realistic load-test pool sizes.
|
|
15
|
-
EXPORT_SCAN_LIMIT = 2000
|
|
16
|
-
|
|
17
|
-
DEFAULT_EXPORT_PER_PAGE = 20
|
|
13
|
+
DEFAULT_EXPORT_PER_PAGE = 10
|
|
18
14
|
|
|
19
15
|
# Queried fresh from the DB every time, so it's always in sync with the current pool rather than
|
|
20
16
|
# a stashed file or session state.
|
|
21
17
|
#
|
|
22
|
-
# `load_test_account`
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# correctly regardless of that storage quirk.
|
|
18
|
+
# Filters the `load_test_account` flag in SQL via the model's `load_test_accounts` scope (see
|
|
19
|
+
# UserDecorator), so only the tenant's load-test accounts are considered — never the whole users
|
|
20
|
+
# table. Unlike the old `order(:id).limit(2000).select(&:...)` approach, there's no scan cap:
|
|
21
|
+
# newly created accounts (highest ids, ordered first below) always show up even on tenants with
|
|
22
|
+
# far more than 2,000 users.
|
|
28
23
|
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
# instead of hand-rolled pagination just for this one page.
|
|
24
|
+
# Kaminari pages on the relation itself, so the DB only ever loads the current page's rows
|
|
25
|
+
# (`LIMIT`/`OFFSET`) — never the full pool into memory — via the same `page`/`per_page` params
|
|
26
|
+
# and `paginate` view helper every other index page in this app uses.
|
|
33
27
|
#
|
|
34
28
|
# Shared between LoadTestAccountManagement (lists/mutates the pool) and
|
|
35
29
|
# LoadTestLoginTokenGeneration (mints tokens for exactly the page shown), so both controllers
|
|
36
30
|
# resolve the same page the same way.
|
|
37
31
|
def export_accounts
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Kaminari.paginate_array(matches).page(params[:page]).per(params[:per_page] || DEFAULT_EXPORT_PER_PAGE)
|
|
32
|
+
Spree::User.where(tenant_id: load_test_tenant&.id)
|
|
33
|
+
.load_test_accounts
|
|
34
|
+
.order(id: :desc)
|
|
35
|
+
.page(params[:page])
|
|
36
|
+
.per(params[:per_page] || DEFAULT_EXPORT_PER_PAGE)
|
|
44
37
|
end
|
|
45
38
|
end
|
|
46
39
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
# Sets Current.load_test_bypass when the request carries the correct X-Request-Verify secret, so
|
|
3
|
+
# anti-abuse services (e.g. InventoryHolds::ValidateLimits) can skip their checks for trusted
|
|
4
|
+
# load tests. No-op unless LOAD_TEST_BYPASS_KEY is set. Include in any controller that can
|
|
5
|
+
# trigger such a check.
|
|
6
|
+
module LoadTestBypassable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action :set_load_test_bypass_current
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
# Always assigns the flag (false unless the request carries the correct
|
|
16
|
+
# secret), so its value never leaks from a previous request.
|
|
17
|
+
def set_load_test_bypass_current
|
|
18
|
+
SpreeCmCommissioner::Current.load_test_bypass = load_test_bypass_requested?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def load_test_bypass_requested?
|
|
22
|
+
key = ENV.fetch('LOAD_TEST_BYPASS_KEY', nil)
|
|
23
|
+
return false if key.blank?
|
|
24
|
+
|
|
25
|
+
provided = request.headers.fetch('X-Request-Verify', nil).to_s
|
|
26
|
+
ActiveSupport::SecurityUtils.secure_compare(provided, key)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -53,7 +53,7 @@ module Spree
|
|
|
53
53
|
preferences upload_later social_contact_platform user_id
|
|
54
54
|
bib_number bib_prefix bib_index public_metadata private_metadata
|
|
55
55
|
seat_number intel_phone_number block_id saved_guest_id
|
|
56
|
-
|
|
56
|
+
data_fill_stage
|
|
57
57
|
].freeze
|
|
58
58
|
|
|
59
59
|
def guest_base_columns
|
|
@@ -4,69 +4,40 @@ module Spree
|
|
|
4
4
|
module Storefront
|
|
5
5
|
module Account
|
|
6
6
|
class GuestDynamicFieldsController < ::Spree::Api::V2::ResourceController
|
|
7
|
+
ALLOWED_PHASES = %w[pre_registration post_registration].freeze
|
|
8
|
+
|
|
7
9
|
before_action :require_spree_current_user
|
|
8
10
|
before_action :load_guest
|
|
9
11
|
|
|
10
12
|
def update_dynamic_field
|
|
11
|
-
phase
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
process_dynamic_field(field)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
@guest.save_and_move_to_next_stage
|
|
13
|
+
return render_error_payload('Invalid phase') unless ALLOWED_PHASES.include?(params[:phase])
|
|
14
|
+
return render_error_payload('No dynamic fields provided') if dynamic_fields_params.blank?
|
|
15
|
+
|
|
16
|
+
result = SpreeCmCommissioner::Guests::Update.call(
|
|
17
|
+
guest: @guest,
|
|
18
|
+
guest_params: {
|
|
19
|
+
guest_dynamic_fields_attributes: dynamic_fields_params.map { |f| { dynamic_field_id: f[:id], value: f[:value] } }
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if result.success?
|
|
24
|
+
render_serialized_payload { serialize_guest(result.value[:guest]) }
|
|
25
|
+
else
|
|
26
|
+
render_error_payload(result.error)
|
|
29
27
|
end
|
|
30
|
-
|
|
31
|
-
render_serialized_payload { serialize_guest(@guest) }
|
|
32
|
-
rescue ActiveRecord::RecordInvalid => e
|
|
33
|
-
render_error_payload(e.record.errors, 422)
|
|
34
|
-
rescue ActiveRecord::RecordNotFound => e
|
|
35
|
-
render_error_payload(e.message, 404)
|
|
36
28
|
end
|
|
37
29
|
|
|
38
30
|
private
|
|
39
31
|
|
|
40
32
|
def dynamic_fields_params
|
|
41
|
-
params
|
|
42
|
-
field.permit(:id, :value)
|
|
43
|
-
end
|
|
33
|
+
Array(params[:dynamic_fields]).map { |field| field.permit(:id, :value) }
|
|
44
34
|
end
|
|
45
35
|
|
|
46
36
|
def load_guest
|
|
47
37
|
@guest = SpreeCmCommissioner::Guest.find(params[:guest_id])
|
|
48
38
|
|
|
49
|
-
unless spree_current_user.guests.exists?(id: @guest.id) ||
|
|
50
|
-
|
|
51
|
-
render_error_payload('Unauthorized', 401)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def process_dynamic_field(field)
|
|
56
|
-
dynamic_field = SpreeCmCommissioner::DynamicField.find(field[:id])
|
|
57
|
-
guest_field = @guest.guest_dynamic_fields.build(dynamic_field_id: dynamic_field.id)
|
|
58
|
-
|
|
59
|
-
if dynamic_field.requires_dynamic_field_options?
|
|
60
|
-
option = dynamic_field.dynamic_field_options.find_by(value: field[:value])
|
|
61
|
-
raise ActiveRecord::RecordNotFound, "Invalid value for dynamic field #{dynamic_field.label}" unless option
|
|
62
|
-
|
|
63
|
-
guest_field.dynamic_field_option = option
|
|
64
|
-
guest_field.value = option.value
|
|
65
|
-
else
|
|
66
|
-
guest_field.value = field[:value]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
guest_field.save!
|
|
39
|
+
raise CanCan::AccessDenied unless spree_current_user.guests.exists?(id: @guest.id) ||
|
|
40
|
+
@guest.line_item.order.user == spree_current_user
|
|
70
41
|
end
|
|
71
42
|
|
|
72
43
|
def serialize_guest(guest)
|
|
@@ -7,7 +7,7 @@ module Spree
|
|
|
7
7
|
before_action :require_spree_current_user
|
|
8
8
|
|
|
9
9
|
def update
|
|
10
|
-
|
|
10
|
+
spree_current_user.clear_has_incomplete_guest_info_cache
|
|
11
11
|
render_success
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -18,7 +18,7 @@ module Spree
|
|
|
18
18
|
{
|
|
19
19
|
success: true,
|
|
20
20
|
message: 'Guest information marked as complete',
|
|
21
|
-
has_incomplete_guest_info:
|
|
21
|
+
has_incomplete_guest_info: spree_current_user.has_incomplete_guest_info?
|
|
22
22
|
}
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -24,21 +24,11 @@ module Spree
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def find_orders_with_incomplete_guest_info
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
order.line_items.any? do |line_item|
|
|
33
|
-
line_item.guests.any? do |guest|
|
|
34
|
-
guest.pre_registration_completed? &&
|
|
35
|
-
guest.post_registration_fields? &&
|
|
36
|
-
!guest.post_registration_completed?
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end.map(&:id)
|
|
40
|
-
|
|
41
|
-
spree_current_user.orders.where(id: incomplete_order_ids)
|
|
27
|
+
spree_current_user.orders
|
|
28
|
+
.complete
|
|
29
|
+
.joins(:guests)
|
|
30
|
+
.merge(SpreeCmCommissioner::Guest.post_registration)
|
|
31
|
+
.distinct
|
|
42
32
|
end
|
|
43
33
|
|
|
44
34
|
def collection_finder
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
module Account
|
|
6
|
+
class SavedGuestsController < ::Spree::Api::V2::ResourceController
|
|
7
|
+
before_action :require_spree_current_user
|
|
8
|
+
before_action :load_saved_guest, only: %i[show update destroy]
|
|
9
|
+
|
|
10
|
+
def collection
|
|
11
|
+
spree_current_user.saved_guests.order(created_at: :desc)
|
|
12
|
+
.page(params[:page])
|
|
13
|
+
.per(params[:per_page])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create
|
|
17
|
+
saved_guest = spree_current_user.saved_guests.new(saved_guest_params)
|
|
18
|
+
|
|
19
|
+
if saved_guest.save
|
|
20
|
+
render_serialized_payload(201) { serialize_resource(saved_guest) }
|
|
21
|
+
else
|
|
22
|
+
render_error_payload(saved_guest.errors.full_messages.to_sentence, 422)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def update
|
|
27
|
+
if @saved_guest.update(saved_guest_params)
|
|
28
|
+
render_serialized_payload { serialize_resource(@saved_guest) }
|
|
29
|
+
else
|
|
30
|
+
render_error_payload(@saved_guest.errors.full_messages.to_sentence, 422)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def destroy
|
|
35
|
+
@saved_guest.destroy
|
|
36
|
+
head :no_content
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def model_class
|
|
42
|
+
SpreeCmCommissioner::SavedGuest
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def collection_serializer
|
|
46
|
+
resource_serializer
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def resource_serializer
|
|
50
|
+
SpreeCmCommissioner::V2::Storefront::SavedGuestSerializer
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def load_saved_guest
|
|
54
|
+
@saved_guest = spree_current_user.saved_guests.find(params[:id])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def saved_guest_params
|
|
58
|
+
params.require(:saved_guest).permit(*::Spree::PermittedAttributes.saved_guest_attributes)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -3,6 +3,9 @@ module Spree
|
|
|
3
3
|
module V2
|
|
4
4
|
module Storefront
|
|
5
5
|
class DraftOrdersController < ::Spree::Api::V2::ResourceController
|
|
6
|
+
# Creating the order acquires the inventory hold, so honor the load-test bypass here too.
|
|
7
|
+
include SpreeCmCommissioner::LoadTestBypassable
|
|
8
|
+
|
|
6
9
|
# Creates a generic draft order from a locally-assembled cart in a single request.
|
|
7
10
|
# Endpoint: POST /api/v2/storefront/draft_orders
|
|
8
11
|
# Params:
|
|
@@ -31,26 +31,27 @@ module Spree
|
|
|
31
31
|
def create
|
|
32
32
|
spree_authorize! :update, spree_current_order, order_token
|
|
33
33
|
|
|
34
|
-
result = SpreeCmCommissioner::
|
|
34
|
+
result = SpreeCmCommissioner::Guests::Create.call(
|
|
35
35
|
line_item: parent,
|
|
36
|
-
|
|
36
|
+
guest_params: guest_params
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
if result.success?
|
|
40
|
-
render_serialized_payload(201) { serialize_resource(result.value) }
|
|
40
|
+
render_serialized_payload(201) { serialize_resource(result.value[:guest]) }
|
|
41
41
|
else
|
|
42
|
-
render_error_payload(result.value.errors, 422)
|
|
42
|
+
render_error_payload(result.error || result.value.errors, 422)
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def update
|
|
47
47
|
spree_authorize! :update, spree_current_order, order_token unless guest_for_update.pre_registration?
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
result = SpreeCmCommissioner::Guests::Update.call(guest: guest_for_update, guest_params: guest_params)
|
|
50
|
+
|
|
51
|
+
if result.success?
|
|
52
|
+
render_serialized_payload { serialize_resource(result.value[:guest]) }
|
|
53
|
+
else
|
|
54
|
+
render_error_payload(result.error || result.value&.errors, 422)
|
|
54
55
|
end
|
|
55
56
|
end
|
|
56
57
|
|
|
@@ -18,7 +18,6 @@ module Spree
|
|
|
18
18
|
order = Spree::Order.not_archived.find_by!(token: order_token)
|
|
19
19
|
|
|
20
20
|
spree_authorize! :update, order, order_token
|
|
21
|
-
raise CanCan::AccessDenied unless order.payment?
|
|
22
21
|
|
|
23
22
|
if order.mark_as_archive
|
|
24
23
|
render_serialized_payload { serialize_resource(order) }
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
module Account
|
|
6
|
+
class SavedGuestsController < BaseController
|
|
7
|
+
around_action :wrap_with_multitenant_without
|
|
8
|
+
before_action :require_spree_current_user
|
|
9
|
+
before_action :load_saved_guest, only: %i[show update destroy]
|
|
10
|
+
|
|
11
|
+
def collection
|
|
12
|
+
spree_current_user.saved_guests.order(created_at: :desc)
|
|
13
|
+
.page(params[:page])
|
|
14
|
+
.per(params[:per_page])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create
|
|
18
|
+
saved_guest = spree_current_user.saved_guests.new(saved_guest_params)
|
|
19
|
+
|
|
20
|
+
if saved_guest.save
|
|
21
|
+
render_serialized_payload(201) { serialize_resource(saved_guest) }
|
|
22
|
+
else
|
|
23
|
+
render_error_payload(saved_guest.errors.full_messages.to_sentence, 422)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update
|
|
28
|
+
if @saved_guest.update(saved_guest_params)
|
|
29
|
+
render_serialized_payload { serialize_resource(@saved_guest) }
|
|
30
|
+
else
|
|
31
|
+
render_error_payload(@saved_guest.errors.full_messages.to_sentence, 422)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def destroy
|
|
36
|
+
@saved_guest.destroy
|
|
37
|
+
head :no_content
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def wrap_with_multitenant_without(&block)
|
|
43
|
+
MultiTenant.without(&block)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def model_class
|
|
47
|
+
SpreeCmCommissioner::SavedGuest
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def collection_serializer
|
|
51
|
+
resource_serializer
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def resource_serializer
|
|
55
|
+
Spree::V2::Tenant::SavedGuestSerializer
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def load_saved_guest
|
|
59
|
+
@saved_guest = spree_current_user.saved_guests.find(params[:id])
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def saved_guest_params
|
|
63
|
+
params.require(:saved_guest).permit(*::Spree::PermittedAttributes.saved_guest_attributes)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -14,7 +14,9 @@ module Spree
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def scope
|
|
17
|
-
current_season.episodes
|
|
17
|
+
current_season.episodes
|
|
18
|
+
.where(product_type: :show_episode, status: :active)
|
|
19
|
+
.includes(:voting_sessions, :vote_packages)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def current_season
|
|
@@ -30,28 +30,25 @@ module Spree
|
|
|
30
30
|
def create
|
|
31
31
|
spree_authorize! :update, spree_current_order, order_token
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
result = SpreeCmCommissioner::Guests::Create.call(line_item: parent, guest_params: guest_params)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
if result.success?
|
|
36
|
+
render_serialized_payload(201) { serialize_resource(result.value[:guest]) }
|
|
37
|
+
else
|
|
38
|
+
render_error_payload(result.error || result.value&.errors, 422)
|
|
39
39
|
end
|
|
40
|
-
|
|
41
|
-
render_serialized_payload(201) { serialize_resource(resource) }
|
|
42
40
|
end
|
|
43
41
|
|
|
44
42
|
def update
|
|
45
43
|
spree_authorize! :update, spree_current_order, order_token
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
run_dynamic_fields(resource) if guest_params[:guest_dynamic_fields_attributes]
|
|
49
|
-
resource.assign_attributes(guest_params.except(:guest_dynamic_fields_attributes))
|
|
50
|
-
resource.save!
|
|
51
|
-
resource.save_and_move_to_next_stage
|
|
52
|
-
end
|
|
45
|
+
result = SpreeCmCommissioner::Guests::Update.call(guest: resource, guest_params: guest_params)
|
|
53
46
|
|
|
54
|
-
|
|
47
|
+
if result.success?
|
|
48
|
+
render_serialized_payload { serialize_resource(result.value[:guest]) }
|
|
49
|
+
else
|
|
50
|
+
render_error_payload(result.error || result.value&.errors, 422)
|
|
51
|
+
end
|
|
55
52
|
end
|
|
56
53
|
|
|
57
54
|
private
|
|
@@ -99,13 +96,6 @@ module Spree
|
|
|
99
96
|
)
|
|
100
97
|
end
|
|
101
98
|
|
|
102
|
-
def run_dynamic_fields(resource)
|
|
103
|
-
SpreeCmCommissioner::GuestDynamicFieldsManager.call(
|
|
104
|
-
resource: resource,
|
|
105
|
-
dynamic_fields_attributes: guest_params[:guest_dynamic_fields_attributes]
|
|
106
|
-
)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
99
|
def handle_record_invalid(exception)
|
|
110
100
|
render_error_payload(exception.record.errors, 422)
|
|
111
101
|
end
|
|
@@ -21,7 +21,6 @@ module Spree
|
|
|
21
21
|
order = Spree::Order.not_archived.find_by!(token: order_token)
|
|
22
22
|
|
|
23
23
|
spree_authorize! :update, order, order_token
|
|
24
|
-
raise CanCan::AccessDenied unless order.payment?
|
|
25
24
|
|
|
26
25
|
if order.mark_as_archive
|
|
27
26
|
render_serialized_payload { serialize_resource(order) }
|
|
@@ -58,8 +58,14 @@ module SpreeCmCommissioner
|
|
|
58
58
|
|
|
59
59
|
# Builds the load-test fixture for this variant so it can be used by the k6 booking flow.
|
|
60
60
|
# Shown on a page (with a check for whether the variant can be booked) for the tester to
|
|
61
|
-
# copy into the load_testing config.
|
|
61
|
+
# copy into the load_testing config. A product with a tenant_id belongs to a tenant
|
|
62
|
+
# (SaaS-hosted) store rather than the platform — the two k6 workflows keep separate fixture
|
|
63
|
+
# folders (load_testing/config/fixture/platform/booking_ticket_flow/ vs
|
|
64
|
+
# load_testing/config/fixture/tenant/cash_on_booking_ticket_flow/ — the tenant flow is named
|
|
65
|
+
# cash_on_* since it has an ABA sibling; the platform flow doesn't).
|
|
62
66
|
def fixture
|
|
67
|
+
@fixture_workflow = @variant.product.tenant_id.present? ? 'tenant' : 'platform'
|
|
68
|
+
@fixture_flow = @fixture_workflow == 'tenant' ? 'cash_on_booking_ticket_flow' : 'booking_ticket_flow'
|
|
63
69
|
result = SpreeCmCommissioner::LoadTest::GenerateBookingTicketData.call(variant: @variant)
|
|
64
70
|
@fixture = result.value[:data]
|
|
65
71
|
@fixture_issues = result.value[:issues]
|
data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb
CHANGED
|
@@ -5,22 +5,11 @@ module SpreeCmCommissioner
|
|
|
5
5
|
module CheckoutControllerDecorator
|
|
6
6
|
def self.prepended(base)
|
|
7
7
|
base.include SpreeCmCommissioner::OrderConcern
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def set_load_test_bypass_current
|
|
15
|
-
key = ENV.fetch('LOAD_TEST_BYPASS_KEY', nil)
|
|
16
|
-
return if key.blank?
|
|
17
|
-
|
|
18
|
-
provided = request.headers.fetch('X-Request-Verify', nil).to_s
|
|
19
|
-
SpreeCmCommissioner::Current.load_test_bypass = ActiveSupport::SecurityUtils.secure_compare(provided, key)
|
|
8
|
+
# Sets Current.load_test_bypass from the X-Request-Verify secret so
|
|
9
|
+
# InventoryHolds::ValidateLimits can skip anti-abuse checks for trusted load tests.
|
|
10
|
+
base.include SpreeCmCommissioner::LoadTestBypassable
|
|
20
11
|
end
|
|
21
12
|
|
|
22
|
-
public
|
|
23
|
-
|
|
24
13
|
# Override Spree's default behavior:
|
|
25
14
|
# By default, Spree raises an error if `complete` is called on a completed or confirmed order.
|
|
26
15
|
# We want to allow this call to succeed, so the API can be used both to:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module MaintenanceTasks
|
|
3
|
+
class GuestDataFillStageBatchJob < ApplicationJob
|
|
4
|
+
queue_as :maintenance
|
|
5
|
+
|
|
6
|
+
# Refreshes data_fill_stage (+ clears has_incomplete_guest_info caches, and optionally
|
|
7
|
+
# notifies newly-incomplete guests) for a bounded batch of guests. Enqueued in slices by
|
|
8
|
+
# MaintenanceTasks::GuestDataFillStage#maintain and by the recompute_guest_data_fill_stage
|
|
9
|
+
# rake task instead of looping over every guest inline, so neither a product with many
|
|
10
|
+
# completed-order guests nor a full-table backfill blocks a single job for a long time.
|
|
11
|
+
def perform(guest_ids:, notify: true)
|
|
12
|
+
SpreeCmCommissioner::Guest
|
|
13
|
+
.where(id: guest_ids)
|
|
14
|
+
.includes(line_item: :order)
|
|
15
|
+
.find_each do |guest|
|
|
16
|
+
result = SpreeCmCommissioner::Guests::RefreshDataFillStage.call(guest: guest, notify: notify)
|
|
17
|
+
|
|
18
|
+
next if result.success?
|
|
19
|
+
|
|
20
|
+
CmAppLogger.log(
|
|
21
|
+
label: "#{self.class.name} failed",
|
|
22
|
+
data: { guest_id: guest.id, error: result.error.to_s }
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|