spree_cm_commissioner 2.7.1.pre.pre4 → 2.7.1.pre.pre6
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/.gitignore +0 -4
- data/Gemfile.lock +1 -1
- data/app/controllers/spree/api/v2/storefront/pricing_previews_controller.rb +39 -0
- data/app/controllers/spree/api/v2/tenant/base_controller.rb +0 -4
- data/app/controllers/spree/api/v2/tenant/pricing_previews_controller.rb +39 -0
- data/app/factory/spree_cm_commissioner/order_telegram_message_factory.rb +88 -0
- data/app/finders/spree_cm_commissioner/accommodations/find.rb +6 -5
- data/app/helpers/spree_cm_commissioner/admin/homepage_segment_helper.rb +0 -2
- data/app/models/concerns/spree_cm_commissioner/homepage_section_bitwise.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -10
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
- data/app/models/spree_cm_commissioner/pricing_action.rb +2 -2
- data/app/models/spree_cm_commissioner/pricing_actions/create_guest_adjustments.rb +34 -42
- data/app/models/spree_cm_commissioner/pricing_actions/create_line_item_adjustments.rb +17 -10
- data/app/models/spree_cm_commissioner/pricing_actions/create_route_adjustments.rb +38 -39
- data/app/models/spree_cm_commissioner/pricing_model.rb +13 -15
- data/app/models/spree_cm_commissioner/pricing_rule.rb +1 -1
- data/app/models/spree_cm_commissioner/pricing_rules/age_group.rb +9 -12
- data/app/models/spree_cm_commissioner/pricing_rules/extra_drop_off_distance.rb +2 -2
- data/app/models/spree_cm_commissioner/pricing_rules/extra_pick_up_distance.rb +2 -2
- data/app/models/spree_cm_commissioner/pricing_rules/nationality.rb +18 -19
- data/app/models/spree_cm_commissioner/pricing_rules/nationality_group.rb +7 -16
- data/app/models/spree_cm_commissioner/product_decorator.rb +0 -2
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -2
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +1 -10
- data/app/models/spree_cm_commissioner/tenant.rb +0 -9
- data/app/models/spree_cm_commissioner/user_decorator.rb +0 -3
- data/app/models/spree_cm_commissioner/variant_options.rb +0 -4
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +0 -4
- data/app/serializers/spree/v2/tenant/pricing_preview_serializer.rb +15 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/pricing_preview_serializer.rb +15 -0
- data/app/services/spree_cm_commissioner/checkout/update_decorator.rb +1 -1
- data/app/services/spree_cm_commissioner/pricing_models/activate.rb +41 -0
- data/app/services/spree_cm_commissioner/pricing_models/preview.rb +93 -0
- data/config/initializers/spree_permitted_attributes.rb +0 -3
- data/config/locales/en.yml +0 -8
- data/config/locales/km.yml +0 -2
- data/config/routes.rb +4 -17
- data/db/migrate/20260506090000_remove_default_from_cm_guests_nationality_group.rb +6 -0
- data/docs/tenant/test.com.md +88 -0
- data/lib/spree_cm_commissioner/pricing_models/guest_context.rb +81 -0
- data/lib/spree_cm_commissioner/pricing_models/line_item_context.rb +63 -0
- data/lib/spree_cm_commissioner/pricing_models/order_context.rb +61 -0
- data/lib/spree_cm_commissioner/pricing_models/preview_adjustment.rb +30 -0
- data/lib/spree_cm_commissioner/pricing_models/pricing_preview.rb +15 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_action_factory.rb +4 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +6 -7
- metadata +15 -81
- data/app/controllers/spree/api/v2/tenant/free_vote_claims_controller.rb +0 -37
- data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +0 -50
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +0 -49
- data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +0 -36
- data/app/controllers/spree/api/v2/tenant/shows_controller.rb +0 -34
- data/app/controllers/spree/api/v2/tenant/votes_controller.rb +0 -94
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +0 -40
- data/app/controllers/spree/api/v2/tenant/voting_credit_transactions_controller.rb +0 -41
- data/app/controllers/spree/api/v2/tenant/voting_credits_controller.rb +0 -31
- data/app/jobs/spree_cm_commissioner/vote_fraud_event_job.rb +0 -9
- data/app/jobs/spree_cm_commissioner/voting_credit_allocation_job.rb +0 -10
- data/app/jobs/spree_cm_commissioner/voting_credit_de_allocation_job.rb +0 -10
- data/app/models/spree_cm_commissioner/maintenance_tasks/voting_session.rb +0 -19
- data/app/models/spree_cm_commissioner/pricing_model_handler/order.rb +0 -78
- data/app/models/spree_cm_commissioner/show.rb +0 -152
- data/app/models/spree_cm_commissioner/show_contestant.rb +0 -29
- data/app/models/spree_cm_commissioner/show_contestant_image.rb +0 -11
- data/app/models/spree_cm_commissioner/show_episode.rb +0 -98
- data/app/models/spree_cm_commissioner/show_person.rb +0 -15
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +0 -20
- data/app/models/spree_cm_commissioner/show_person_image.rb +0 -11
- data/app/models/spree_cm_commissioner/vote.rb +0 -16
- data/app/models/spree_cm_commissioner/vote_fraud_event.rb +0 -19
- data/app/models/spree_cm_commissioner/voting_contestant.rb +0 -33
- data/app/models/spree_cm_commissioner/voting_credit.rb +0 -72
- data/app/models/spree_cm_commissioner/voting_credit_transaction.rb +0 -55
- data/app/models/spree_cm_commissioner/voting_session.rb +0 -153
- data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +0 -19
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +0 -17
- data/app/serializers/spree/v2/tenant/show_person_assignment_serializer.rb +0 -15
- data/app/serializers/spree/v2/tenant/show_person_serializer.rb +0 -13
- data/app/serializers/spree/v2/tenant/show_serializer.rb +0 -26
- data/app/serializers/spree/v2/tenant/vote_serializer.rb +0 -14
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +0 -17
- data/app/serializers/spree/v2/tenant/voting_credit_serializer.rb +0 -10
- data/app/serializers/spree/v2/tenant/voting_credit_transaction_serializer.rb +0 -14
- data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +0 -14
- data/app/services/spree_cm_commissioner/fraud_check.rb +0 -275
- data/app/services/spree_cm_commissioner/vote_counters/audit_counters.rb +0 -35
- data/app/services/spree_cm_commissioner/vote_counters/base.rb +0 -31
- data/app/services/spree_cm_commissioner/vote_counters/increment.rb +0 -34
- data/app/services/spree_cm_commissioner/vote_counters/per_contestant_counter.rb +0 -25
- data/app/services/spree_cm_commissioner/vote_counters/rebuild_from_db.rb +0 -41
- data/app/services/spree_cm_commissioner/vote_credit_deductor.rb +0 -68
- data/app/services/spree_cm_commissioner/vote_package/create.rb +0 -155
- data/app/services/spree_cm_commissioner/vote_processor.rb +0 -133
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +0 -334
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +0 -32
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +0 -96
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +0 -77
- data/app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb +0 -119
- data/app/services/spree_cm_commissioner/voting_credits/credit_calculator.rb +0 -35
- data/app/services/spree_cm_commissioner/voting_credits/de_allocate.rb +0 -87
- data/db/migrate/20260309230148_create_cm_show_people.rb +0 -14
- data/db/migrate/20260309230149_create_cm_show_people_assignments.rb +0 -16
- data/db/migrate/20260310082711_create_cm_show_contestants.rb +0 -28
- data/db/migrate/20260310082720_create_cm_voting_sessions.rb +0 -21
- data/db/migrate/20260310082721_create_cm_voting_contestants.rb +0 -23
- data/db/migrate/20260310082734_add_voting_fields_to_spree_taxons.rb +0 -9
- data/db/migrate/20260310082735_add_type_to_spree_products.rb +0 -6
- data/db/migrate/20260310082749_create_cm_voting_credits.rb +0 -27
- data/db/migrate/20260326080200_create_cm_voting_credit_transactions.rb +0 -27
- data/db/migrate/20260330160000_create_cm_votes.rb +0 -25
- data/db/migrate/20260401072500_add_advanced_from_to_cm_voting_contestants.rb +0 -7
- data/db/migrate/20260402000001_add_voting_credit_scope_to_spree_taxons.rb +0 -6
- data/db/migrate/20260402000002_rename_scopeable_to_votable_in_cm_voting_credits.rb +0 -12
- data/db/migrate/20260403070000_add_name_to_cm_voting_sessions.rb +0 -5
- data/db/migrate/20260406000001_add_vendor_id_to_voting_tables.rb +0 -6
- data/db/migrate/20260406000001_rename_votes_remaining_to_amount_in_cm_voting_credits.rb +0 -11
- data/db/migrate/20260408085255_add_show_id_and_vendor_id_to_cm_voting_sessions.rb +0 -9
- data/db/migrate/20260420000001_rename_type_to_credit_type_in_cm_voting_credits.rb +0 -25
- data/db/migrate/20260422000001_create_cm_vote_fraud_events.rb +0 -23
- data/docs/sql/jsonb_query_guide.md +0 -57
- data/lib/spree_cm_commissioner/test_helper/factories/show_episode_factory.rb +0 -12
- data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +0 -93
- data/lib/spree_cm_commissioner/test_helper/factories/vote_credit_factory.rb +0 -37
- data/lib/spree_cm_commissioner/test_helper/factories/vote_factory.rb +0 -28
- data/lib/spree_cm_commissioner/test_helper/factories/voting_credit_transaction_factory.rb +0 -11
- data/lib/spree_cm_commissioner/test_helper/factories/voting_session_factory.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f88085ac9f274a24587f64dca172c3219d84b76e02385419388bc84196bdbc2e
|
|
4
|
+
data.tar.gz: 3865b929388b20b69d3a641bbdf2695ae79055e5636c5fed7033bc297b511ff5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec9862ee95fb74dc2031f22534084dbbfe01c7fd5351a248014f5a8011a97fd990d0145b1536d697877face277480bdc837fa126e64b73a41039a55268072182
|
|
7
|
+
data.tar.gz: 4b84c53d6a14a05702b5eaa78a76b1eb6f80471f15b4cc95bee9fef3772f00abe49f40c9c9d0cd78ec7761d5aa012c1d4546931a121e7e8ae2e264e7788e5bb2
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
class PricingPreviewsController < ::Spree::Api::V2::BaseController
|
|
6
|
+
# GET /api/v2/tenant/pricing_previews
|
|
7
|
+
def index
|
|
8
|
+
permitted_preview_params = params.permit(SpreeCmCommissioner::PricingModels::OrderContext::PREVIEW_PERMITTED_PARAMS)
|
|
9
|
+
order_context = SpreeCmCommissioner::PricingModels::OrderContext.load!(permitted_preview_params[:order_context])
|
|
10
|
+
pricing_models_updated_at = SpreeCmCommissioner::PricingModel.joins(:vendor)
|
|
11
|
+
.where(spree_vendors: { tenant_id: nil })
|
|
12
|
+
.maximum(:updated_at)
|
|
13
|
+
cache_key = 'pricing:preview:v2:' \
|
|
14
|
+
"#{Digest::SHA256.hexdigest(permitted_preview_params.to_json)}:" \
|
|
15
|
+
"#{pricing_models_updated_at.to_i}"
|
|
16
|
+
|
|
17
|
+
result = Rails.cache.fetch(cache_key, expires_in: 60.seconds) do
|
|
18
|
+
SpreeCmCommissioner::PricingModels::Preview.call(order_context: order_context)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if result.success?
|
|
22
|
+
render_serialized_payload { serialize_resource(result.value[:pricing_preview]) }
|
|
23
|
+
else
|
|
24
|
+
render_error_payload(result.error, 422)
|
|
25
|
+
end
|
|
26
|
+
rescue ArgumentError => e
|
|
27
|
+
render_error_payload(e.message, 422)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def resource_serializer
|
|
33
|
+
SpreeCmCommissioner::V2::Storefront::PricingPreviewSerializer
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
class PricingPreviewsController < BaseController
|
|
6
|
+
# GET /api/v2/tenant/pricing_previews
|
|
7
|
+
def index
|
|
8
|
+
permitted_preview_params = params.permit(SpreeCmCommissioner::PricingModels::OrderContext::PREVIEW_PERMITTED_PARAMS)
|
|
9
|
+
order_context = SpreeCmCommissioner::PricingModels::OrderContext.load!(permitted_preview_params[:order_context])
|
|
10
|
+
pricing_models_updated_at = SpreeCmCommissioner::PricingModel.joins(:vendor)
|
|
11
|
+
.where(spree_vendors: { tenant_id: current_tenant.id })
|
|
12
|
+
.maximum(:updated_at)
|
|
13
|
+
cache_key = 'pricing:preview:v2:' \
|
|
14
|
+
"#{Digest::SHA256.hexdigest(permitted_preview_params.to_json)}:" \
|
|
15
|
+
"#{pricing_models_updated_at.to_i}"
|
|
16
|
+
|
|
17
|
+
result = Rails.cache.fetch(cache_key, expires_in: 60.seconds) do
|
|
18
|
+
SpreeCmCommissioner::PricingModels::Preview.call(order_context: order_context)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if result.success?
|
|
22
|
+
render_serialized_payload { serialize_resource(result.value[:pricing_preview]) }
|
|
23
|
+
else
|
|
24
|
+
render_error_payload(result.error, 422)
|
|
25
|
+
end
|
|
26
|
+
rescue ArgumentError => e
|
|
27
|
+
render_error_payload(e.message, 422)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def resource_serializer
|
|
33
|
+
Spree::V2::Tenant::PricingPreviewSerializer
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -48,6 +48,8 @@ module SpreeCmCommissioner
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def line_item_content(line_item)
|
|
51
|
+
return intercity_taxi_line_item_content(line_item) if intercity_taxi?(line_item)
|
|
52
|
+
|
|
51
53
|
text = []
|
|
52
54
|
|
|
53
55
|
text << bold(line_item.product.name.to_s)
|
|
@@ -82,6 +84,8 @@ module SpreeCmCommissioner
|
|
|
82
84
|
text << "Email: #{inline_code(order.email)}" if order.email.present?
|
|
83
85
|
text << "Delivery Address: #{formatted_shipping_address.presence || 'N/A'}" if order.delivery_required?
|
|
84
86
|
|
|
87
|
+
append_intercity_taxi_footer(text) if intercity_taxi_order?
|
|
88
|
+
|
|
85
89
|
if show_details_link && order.guests.any?
|
|
86
90
|
text << ''
|
|
87
91
|
text << 'View Tickets:'
|
|
@@ -125,5 +129,89 @@ module SpreeCmCommissioner
|
|
|
125
129
|
|
|
126
130
|
formatted_rows
|
|
127
131
|
end
|
|
132
|
+
|
|
133
|
+
private
|
|
134
|
+
|
|
135
|
+
def intercity_taxi?(line_item)
|
|
136
|
+
trip_for(line_item)&.intercity_taxi?
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def intercity_taxi_order?
|
|
140
|
+
selected_line_items.any? { |li| intercity_taxi?(li) }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def trip_for(line_item)
|
|
144
|
+
return nil unless line_item.respond_to?(:trip_id) && line_item.trip_id.present?
|
|
145
|
+
|
|
146
|
+
@trip_cache ||= {}
|
|
147
|
+
@trip_cache[line_item.trip_id] ||= SpreeCmCommissioner::Trip.find_by(id: line_item.trip_id)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def intercity_taxi_line_item_content(line_item)
|
|
151
|
+
text = []
|
|
152
|
+
route_text = taxi_route_text(line_item)
|
|
153
|
+
departure_text = taxi_departure_text(line_item)
|
|
154
|
+
text << bold('🚗 Trip Details')
|
|
155
|
+
text << "Route: #{route_text}" if route_text.present?
|
|
156
|
+
text << "Passengers: #{line_item.passenger_count || line_item.quantity}"
|
|
157
|
+
text << "Departure: #{departure_text}" if departure_text.present?
|
|
158
|
+
|
|
159
|
+
text.compact.join("\n")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def taxi_route_text(line_item)
|
|
163
|
+
trip = trip_for(line_item)
|
|
164
|
+
return line_item.product.name if trip.blank?
|
|
165
|
+
|
|
166
|
+
origin = trip.origin_place&.name
|
|
167
|
+
destination = trip.destination_place&.name
|
|
168
|
+
vehicle = trip.vehicle_type&.name
|
|
169
|
+
|
|
170
|
+
parts = [origin, destination].compact_blank.join(' → ')
|
|
171
|
+
vehicle.present? ? "#{parts} (#{vehicle})" : parts
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def taxi_departure_text(line_item)
|
|
175
|
+
return nil unless line_item.date_present?
|
|
176
|
+
|
|
177
|
+
line_item.from_date.strftime('%b %d, %Y · %H:%M')
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def nationality_text
|
|
181
|
+
values = order.saved_guests.map { |sg| sg.nationality&.name.presence || sg.nationality_group&.humanize }.compact.uniq
|
|
182
|
+
return nil if values.empty?
|
|
183
|
+
|
|
184
|
+
values.join(', ')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def append_intercity_taxi_footer(text)
|
|
188
|
+
text << "Nationality: #{nationality_text}" if nationality_text.present?
|
|
189
|
+
|
|
190
|
+
pickup = selected_line_items.filter_map(&:pickup_map_place).first
|
|
191
|
+
dropoff = selected_line_items.filter_map(&:dropoff_map_place).first
|
|
192
|
+
|
|
193
|
+
append_map_place(text, '📍 Pick-up Location', pickup) if pickup
|
|
194
|
+
append_map_place(text, '📍 Drop-off Location', dropoff) if dropoff
|
|
195
|
+
|
|
196
|
+
remark = selected_line_items.filter_map { |li| li.remark.presence }.first
|
|
197
|
+
return if remark.blank?
|
|
198
|
+
|
|
199
|
+
text << ''
|
|
200
|
+
text << bold('🗒️ Notes to Driver')
|
|
201
|
+
text << ERB::Util.html_escape(remark)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def append_map_place(text, title, map_place)
|
|
205
|
+
text << ''
|
|
206
|
+
text << bold(title)
|
|
207
|
+
text << "Address: #{ERB::Util.html_escape(map_place.place_name)}" if map_place.place_name.present?
|
|
208
|
+
text << "Google Maps: #{ERB::Util.html_escape(google_maps_link(map_place))}" if google_maps_link(map_place).present?
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def google_maps_link(map_place)
|
|
212
|
+
return nil if map_place.lat.blank? || map_place.lng.blank?
|
|
213
|
+
|
|
214
|
+
"https://www.google.com/maps/search/?api=1&query=#{map_place.lat},#{map_place.lng}"
|
|
215
|
+
end
|
|
128
216
|
end
|
|
129
217
|
end
|
|
@@ -13,11 +13,11 @@ module SpreeCmCommissioner
|
|
|
13
13
|
def execute
|
|
14
14
|
scope
|
|
15
15
|
.where(default_state_id: state_id)
|
|
16
|
-
.where(
|
|
17
|
-
.where('
|
|
18
|
-
|
|
16
|
+
.where('spree_variants.track_inventory = FALSE OR cm_inventory_items.inventory_date BETWEEN ? AND ?', from_date, to_date)
|
|
17
|
+
.where('spree_variants.track_inventory = FALSE OR cm_inventory_items.quantity_available > 0')
|
|
18
|
+
.where('COALESCE(CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER), 0) +
|
|
19
|
+
COALESCE(CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER), 0) >= ?', number_of_guests
|
|
19
20
|
)
|
|
20
|
-
.where('inventory_items.quantity_available > 0')
|
|
21
21
|
.distinct
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -25,7 +25,8 @@ module SpreeCmCommissioner
|
|
|
25
25
|
|
|
26
26
|
def scope
|
|
27
27
|
Spree::Vendor
|
|
28
|
-
.joins(
|
|
28
|
+
.joins(products: :variants)
|
|
29
|
+
.joins('LEFT OUTER JOIN cm_inventory_items ON cm_inventory_items.variant_id = spree_variants.id')
|
|
29
30
|
.where(primary_product_type: :accommodation, state: :active)
|
|
30
31
|
end
|
|
31
32
|
|
|
@@ -26,10 +26,8 @@ module SpreeCmCommissioner
|
|
|
26
26
|
|
|
27
27
|
state_machine.after_transition to: :canceled, do: :precalculate_conversion
|
|
28
28
|
state_machine.after_transition to: :canceled, do: :restock_inventory!
|
|
29
|
-
state_machine.after_transition to: :canceled, do: :de_allocate_resources
|
|
30
29
|
|
|
31
30
|
state_machine.after_transition to: :complete, do: :increment_route_fulfilled_order_count
|
|
32
|
-
state_machine.after_transition to: :complete, do: :allocate_resources
|
|
33
31
|
|
|
34
32
|
scope :accepted, -> { where(request_state: 'accepted') }
|
|
35
33
|
|
|
@@ -330,13 +328,5 @@ module SpreeCmCommissioner
|
|
|
330
328
|
factory = OrderTelegramMessageFactory.new(title: title, order: self)
|
|
331
329
|
TelegramNotificationSenderJob.perform_later(chat_id: chat_id, message: factory.message, parse_mode: factory.parse_mode)
|
|
332
330
|
end
|
|
333
|
-
|
|
334
|
-
def allocate_resources
|
|
335
|
-
SpreeCmCommissioner::VotingCreditAllocationJob.perform_later(order_id: id)
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
def de_allocate_resources
|
|
339
|
-
SpreeCmCommissioner::VotingCreditDeAllocationJob.perform_later(order_id: id)
|
|
340
|
-
end
|
|
341
331
|
end
|
|
342
332
|
end
|
|
@@ -5,7 +5,7 @@ module SpreeCmCommissioner
|
|
|
5
5
|
module ProductType
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
|
-
PRODUCT_TYPES = %i[accommodation service ecommerce transit
|
|
8
|
+
PRODUCT_TYPES = %i[accommodation service ecommerce transit].freeze
|
|
9
9
|
PERMANENT_STOCK_PRODUCT_TYPES = %w[accommodation service transit].freeze
|
|
10
10
|
PRE_INVENTORY_DAYS = { 'transit' => 90, 'accommodation' => 365, 'service' => 30 }.freeze
|
|
11
11
|
|
|
@@ -9,8 +9,8 @@ module SpreeCmCommissioner
|
|
|
9
9
|
|
|
10
10
|
delegate :pricing_rules, to: :pricing_rule_group
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
raise NotImplementedError, "#{self.class}#
|
|
12
|
+
def preview(_options = {})
|
|
13
|
+
raise NotImplementedError, "#{self.class}#preview must be implemented"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def compute_amount(adjustable)
|
|
@@ -1,68 +1,60 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module PricingActions
|
|
3
3
|
class CreateGuestAdjustments < SpreeCmCommissioner::PricingAction
|
|
4
|
-
def
|
|
5
|
-
|
|
4
|
+
def preview(options = {})
|
|
5
|
+
line_item_contexts = Array(options[:line_item_contexts])
|
|
6
6
|
|
|
7
|
-
return if pricing_rule_group.pricing_rules.blank?
|
|
8
|
-
return if
|
|
7
|
+
return [] if pricing_rule_group.pricing_rules.blank?
|
|
8
|
+
return [] if line_item_contexts.blank?
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
line_item_contexts.filter_map do |line_item_context|
|
|
11
|
+
preview_for_line_item_context(line_item_context)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
private
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
return
|
|
17
|
+
def preview_for_line_item_context(line_item_context)
|
|
18
|
+
return nil if line_item_context.guest_contexts.blank?
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
eligible_guest_contexts = find_eligible_guest_contexts(line_item_context)
|
|
21
|
+
return nil if eligible_guest_contexts.empty?
|
|
22
|
+
|
|
23
|
+
total = eligible_guest_contexts.sum do |guest_context|
|
|
24
|
+
compute_guest_amount(line_item_context, guest_context)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
return nil if total.zero?
|
|
28
|
+
|
|
29
|
+
PricingModels::PreviewAdjustment.new(
|
|
30
|
+
label: label,
|
|
31
|
+
amount: total,
|
|
32
|
+
action_type: 'create_guest_adjustments',
|
|
33
|
+
pricing_action: self,
|
|
34
|
+
adjustable_type: 'Spree::LineItem',
|
|
35
|
+
adjustable_id: line_item_context.id,
|
|
36
|
+
line_item_id: line_item_context.id,
|
|
37
|
+
guest_ids: eligible_guest_contexts.map(&:id).compact
|
|
38
|
+
)
|
|
21
39
|
end
|
|
22
40
|
|
|
23
|
-
def
|
|
24
|
-
|
|
25
|
-
|
|
41
|
+
def find_eligible_guest_contexts(line_item_context)
|
|
42
|
+
line_item_context.guest_contexts.select do |guest_context|
|
|
43
|
+
guest_context_eligible_for_all_rules?(guest_context, line_item_context)
|
|
26
44
|
end
|
|
27
45
|
end
|
|
28
46
|
|
|
29
|
-
def
|
|
47
|
+
def guest_context_eligible_for_all_rules?(guest_context, line_item_context)
|
|
30
48
|
pricing_rule_group.pricing_rules.all? do |rule|
|
|
31
|
-
rule.respond_to?(:guest_eligible?) && rule.guest_eligible?(
|
|
49
|
+
rule.respond_to?(:guest_eligible?) && rule.guest_eligible?(guest_context, line_item_context)
|
|
32
50
|
end
|
|
33
51
|
end
|
|
34
52
|
|
|
35
|
-
def compute_guest_amount(
|
|
53
|
+
def compute_guest_amount(line_item_context, _guest_context)
|
|
36
54
|
per_guest_item = Struct.new(:amount, :currency, :quantity)
|
|
37
|
-
.new(
|
|
55
|
+
.new(line_item_context.price, line_item_context.currency, 1)
|
|
38
56
|
calculator&.compute(per_guest_item) || 0
|
|
39
57
|
end
|
|
40
|
-
|
|
41
|
-
def create_adjustment(line_item, amount)
|
|
42
|
-
line_item.adjustments.create!(
|
|
43
|
-
amount: amount,
|
|
44
|
-
source: self,
|
|
45
|
-
adjustable: line_item,
|
|
46
|
-
order: line_item.order,
|
|
47
|
-
label: pricing_rule_group.pricing_model.name,
|
|
48
|
-
mandatory: true
|
|
49
|
-
)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def perform_for_line_item(line_item)
|
|
53
|
-
return if line_item.guests.blank?
|
|
54
|
-
|
|
55
|
-
eligible_guests = find_eligible_guests(line_item)
|
|
56
|
-
return if eligible_guests.empty?
|
|
57
|
-
|
|
58
|
-
total_amount = eligible_guests.sum do |guest|
|
|
59
|
-
compute_guest_amount(line_item, guest)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
return if total_amount.zero?
|
|
63
|
-
|
|
64
|
-
create_adjustment(line_item, total_amount)
|
|
65
|
-
end
|
|
66
58
|
end
|
|
67
59
|
end
|
|
68
60
|
end
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module PricingActions
|
|
3
3
|
class CreateLineItemAdjustments < SpreeCmCommissioner::PricingAction
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
line_items = options[:line_items] || []
|
|
4
|
+
def preview(options = {})
|
|
5
|
+
line_item_contexts = Array(options[:line_item_contexts])
|
|
7
6
|
|
|
8
|
-
return if
|
|
7
|
+
return [] if line_item_contexts.blank?
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
end
|
|
9
|
+
line_item_contexts.filter_map do |line_item_context|
|
|
10
|
+
amount = compute_amount(line_item_context)
|
|
11
|
+
next nil if amount.zero?
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
PricingModels::PreviewAdjustment.new(
|
|
14
|
+
label: label,
|
|
15
|
+
amount: amount,
|
|
16
|
+
action_type: 'create_line_item_adjustments',
|
|
17
|
+
pricing_action: self,
|
|
18
|
+
adjustable_type: 'Spree::LineItem',
|
|
19
|
+
adjustable_id: line_item_context.id,
|
|
20
|
+
line_item_id: line_item_context.id,
|
|
21
|
+
guest_ids: []
|
|
22
|
+
)
|
|
23
|
+
end
|
|
17
24
|
end
|
|
18
25
|
end
|
|
19
26
|
end
|
|
@@ -1,69 +1,68 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module PricingActions
|
|
3
3
|
class CreateRouteAdjustments < SpreeCmCommissioner::PricingAction
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
def preview(options = {})
|
|
5
|
+
order_context = options[:order_context]
|
|
6
|
+
line_item_contexts = Array(options[:line_item_contexts])
|
|
7
7
|
|
|
8
|
-
return if pricing_rules.blank?
|
|
9
|
-
return if
|
|
8
|
+
return [] if pricing_rules.blank?
|
|
9
|
+
return [] if line_item_contexts.blank?
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
return if
|
|
11
|
+
eligible_guest_contexts = collect_unique_eligible_guest_contexts(line_item_contexts)
|
|
12
|
+
return [] if eligible_guest_contexts.empty?
|
|
13
13
|
|
|
14
|
-
total_amount = compute_total_amount(
|
|
15
|
-
return if total_amount.zero?
|
|
14
|
+
total_amount = compute_total_amount(line_item_contexts, eligible_guest_contexts)
|
|
15
|
+
return [] if total_amount.zero?
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
[
|
|
18
|
+
PricingModels::PreviewAdjustment.new(
|
|
19
|
+
label: label,
|
|
20
|
+
amount: total_amount,
|
|
21
|
+
action_type: 'create_route_adjustments',
|
|
22
|
+
pricing_action: self,
|
|
23
|
+
adjustable_type: 'Spree::Order',
|
|
24
|
+
adjustable_id: order_context.id,
|
|
25
|
+
line_item_id: nil,
|
|
26
|
+
guest_ids: eligible_guest_contexts.map(&:id).compact
|
|
27
|
+
)
|
|
28
|
+
]
|
|
18
29
|
end
|
|
19
30
|
|
|
20
31
|
private
|
|
21
32
|
|
|
22
|
-
def
|
|
33
|
+
def collect_unique_eligible_guest_contexts(line_item_contexts)
|
|
23
34
|
seen = {}
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
key =
|
|
36
|
+
line_item_contexts.each_with_object([]) do |line_item_context, result|
|
|
37
|
+
line_item_context.guest_contexts.select { |gc| guest_context_eligible?(gc, line_item_context) }.each_with_index do |guest_context, index|
|
|
38
|
+
key = guest_context.saved_guest_id.present? ? [guest_context.saved_guest_id, index] : guest_context.id
|
|
28
39
|
next if seen[key]
|
|
29
40
|
|
|
30
41
|
seen[key] = true
|
|
31
|
-
result <<
|
|
42
|
+
result << guest_context
|
|
32
43
|
end
|
|
33
44
|
end
|
|
34
45
|
end
|
|
35
46
|
|
|
36
|
-
def
|
|
47
|
+
def guest_context_eligible?(guest_context, line_item_context)
|
|
37
48
|
pricing_rules.all? do |rule|
|
|
38
|
-
!rule.respond_to?(:guest_eligible?) || rule.guest_eligible?(
|
|
49
|
+
!rule.respond_to?(:guest_eligible?) || rule.guest_eligible?(guest_context, line_item_context)
|
|
39
50
|
end
|
|
40
51
|
end
|
|
41
52
|
|
|
42
|
-
def compute_total_amount(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
item = build_per_guest_item(order, guest)
|
|
48
|
-
compute_amount(item)
|
|
53
|
+
def compute_total_amount(line_item_contexts, eligible_guest_contexts)
|
|
54
|
+
eligible_guest_contexts.sum do |guest_context|
|
|
55
|
+
line_item_context = line_item_contexts.find { |l| l.id == guest_context.line_item_id }
|
|
56
|
+
compute_per_guest_amount(line_item_context, guest_context)
|
|
57
|
+
end
|
|
49
58
|
end
|
|
50
59
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
guest.line_item.amount_per_guest,
|
|
54
|
-
order_currency(order),
|
|
55
|
-
1
|
|
56
|
-
)
|
|
57
|
-
end
|
|
60
|
+
def compute_per_guest_amount(line_item_context, _guest_context)
|
|
61
|
+
return 0 if line_item_context.nil?
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
amount: amount,
|
|
63
|
-
order: order,
|
|
64
|
-
label: label,
|
|
65
|
-
mandatory: true
|
|
66
|
-
)
|
|
63
|
+
item = Struct.new(:amount, :currency, :quantity)
|
|
64
|
+
.new(line_item_context.price, line_item_context.currency, 1)
|
|
65
|
+
compute_amount(item)
|
|
67
66
|
end
|
|
68
67
|
end
|
|
69
68
|
end
|
|
@@ -17,30 +17,28 @@ module SpreeCmCommissioner
|
|
|
17
17
|
|
|
18
18
|
enum status: { draft: 0, active: 1, archived: 2 }
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
def preview(order_context:, line_item_contexts:)
|
|
21
|
+
eligible_groups(line_item_contexts).flat_map do |group|
|
|
22
|
+
group.pricing_action&.preview(
|
|
23
|
+
order_context: order_context,
|
|
24
|
+
line_item_contexts: line_item_contexts
|
|
25
|
+
) || []
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
private
|
|
28
30
|
|
|
29
|
-
def
|
|
30
|
-
|
|
31
|
+
def eligible_groups(line_item_contexts)
|
|
32
|
+
pricing_rule_groups.select(&:active?).select do |group|
|
|
33
|
+
eligible_rules = group.pricing_rules.select { |r| any_line_item_context_eligible?(r, line_item_contexts) }
|
|
34
|
+
next false if eligible_rules.empty?
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if group_eligible?(group, eligible_rules)
|
|
35
|
-
|
|
36
|
-
group.pricing_action&.perform(order: order, line_items: line_items)
|
|
37
|
-
else
|
|
38
|
-
Rails.logger.info("PricingRuleGroup #{group.id} not eligible for order #{order.id}")
|
|
36
|
+
group_eligible?(group, eligible_rules)
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
42
|
-
def
|
|
43
|
-
|
|
40
|
+
def any_line_item_context_eligible?(rule, line_item_contexts)
|
|
41
|
+
line_item_contexts.any? { |line_item_context| rule.eligible?(line_item_context) }
|
|
44
42
|
end
|
|
45
43
|
|
|
46
44
|
def group_eligible?(group, eligible_rules)
|
|
@@ -8,7 +8,7 @@ module SpreeCmCommissioner
|
|
|
8
8
|
raise 'eligible? should be implemented in a sub-class of SpreeCmCommissioner::PricingRule'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def guest_eligible?(
|
|
11
|
+
def guest_eligible?(_guest_context, _line_item_context)
|
|
12
12
|
raise 'guest_eligible? should be implemented in a sub-class of SpreeCmCommissioner::PricingRule'
|
|
13
13
|
end
|
|
14
14
|
|