spree_cm_commissioner 2.3.1 → 2.3.2.pre.pre4
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/product_completion_steps_controller.rb +17 -1
- data/app/controllers/spree/admin/tenants_controller.rb +1 -1
- data/app/controllers/spree/api/v2/storefront/intercity_taxi/draft_orders_controller.rb +52 -11
- data/app/controllers/spree/api/v2/storefront/popular_route_places_controller.rb +63 -0
- data/app/controllers/spree/api/v2/storefront/route_places_controller.rb +68 -0
- data/app/controllers/spree/api/v2/tenant/intercity_taxi/draft_orders_controller.rb +81 -0
- data/app/controllers/spree/api/v2/tenant/trip_places_controller.rb +42 -0
- data/app/controllers/spree/api/v2/tenant/trip_search_controller.rb +103 -0
- data/app/controllers/spree/api/v2/tenant/trips_controller.rb +32 -0
- data/app/factory/spree_cm_commissioner/order_telegram_message_factory.rb +12 -0
- data/app/finders/spree_cm_commissioner/places/find_with_route.rb +43 -0
- data/app/finders/spree_cm_commissioner/routes/find_popular.rb +25 -0
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +2 -0
- data/app/interactors/spree_cm_commissioner/host_matcher.rb +1 -1
- data/app/interactors/spree_cm_commissioner/vendor_creation_telegram_alert_sender.rb +1 -1
- data/app/mailers/spree/order_mailer_decorator.rb +12 -11
- data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +34 -89
- data/app/models/concerns/spree_cm_commissioner/service_recommendations.rb +2 -2
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +1 -0
- data/app/models/spree_cm_commissioner/adjustment_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/calculators/extra_drop_off_distance.rb +15 -0
- data/app/models/spree_cm_commissioner/calculators/extra_pick_up_distance.rb +15 -0
- data/app/models/spree_cm_commissioner/place.rb +7 -0
- data/app/models/spree_cm_commissioner/pricing_action.rb +27 -0
- data/app/models/spree_cm_commissioner/pricing_model.rb +18 -0
- data/app/models/spree_cm_commissioner/pricing_model_variant.rb +6 -0
- data/app/models/spree_cm_commissioner/pricing_rule.rb +15 -0
- data/app/models/spree_cm_commissioner/pricing_rule_group.rb +20 -0
- data/app/models/spree_cm_commissioner/pricing_rules/extra_drop_off_distance.rb +10 -0
- data/app/models/spree_cm_commissioner/pricing_rules/extra_pick_up_distance.rb +12 -0
- data/app/models/spree_cm_commissioner/pricing_rules/nationality.rb +35 -0
- data/app/models/spree_cm_commissioner/product_completion_step.rb +4 -1
- data/app/models/spree_cm_commissioner/product_completion_step_banner.rb +12 -0
- data/app/models/spree_cm_commissioner/product_completion_steps/social_entry_url.rb +86 -19
- data/app/models/spree_cm_commissioner/tenant.rb +14 -1
- data/app/models/spree_cm_commissioner/variant_decorator.rb +3 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/vendor_place.rb +10 -1
- data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +9 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +23 -17
- data/app/request_schemas/spree_cm_commissioner/intercity_taxi_draft_order_schema.rb +10 -0
- data/app/request_schemas/spree_cm_commissioner/intercity_taxi_draft_order_update_schema.rb +29 -0
- data/app/request_schemas/spree_cm_commissioner/route_places_request_schema.rb +12 -0
- data/app/serializers/spree/v2/storefront/place_serializer.rb +3 -2
- data/app/serializers/spree/v2/tenant/cart_serializer.rb +1 -0
- data/app/serializers/spree/v2/tenant/intercity_taxi_cart_serializer.rb +12 -0
- data/app/serializers/spree/v2/tenant/line_item_serializer.rb +1 -0
- data/app/serializers/spree/v2/tenant/trip_place_serializer.rb +8 -0
- data/app/serializers/spree/v2/tenant/trip_query_result_serializer.rb +8 -0
- data/app/serializers/spree/v2/tenant/trip_serializer.rb +8 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/intercity_taxi_line_item_serializer.rb +17 -18
- data/app/serializers/spree_cm_commissioner/v2/storefront/route_serializer.rb +12 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vehicle_serializer.rb +1 -1
- data/app/services/spree_cm_commissioner/intercity_taxi_order/create.rb +20 -23
- data/app/services/spree_cm_commissioner/intercity_taxi_order/update.rb +36 -72
- data/app/services/spree_cm_commissioner/pricing_models/apply.rb +51 -0
- data/app/services/spree_cm_commissioner/pricing_rules/build_params.rb +53 -0
- data/app/services/spree_cm_commissioner/pricing_rules/build_template.rb +27 -0
- data/app/services/spree_cm_commissioner/pricing_rules/create.rb +10 -0
- data/app/services/spree_cm_commissioner/pricing_rules/update.rb +11 -0
- data/app/services/spree_cm_commissioner/vendor_places/base.rb +24 -0
- data/app/services/spree_cm_commissioner/vendor_places/bulk_create.rb +70 -0
- data/app/services/spree_cm_commissioner/vendor_places/create_with_google_map_data.rb +85 -0
- data/app/services/spree_cm_commissioner/vendor_places/update.rb +56 -0
- data/app/views/shared/_asset_field.html.erb +13 -0
- data/app/views/spree/admin/product_completion_steps/_form.html.erb +28 -2
- data/app/views/spree/admin/product_completion_steps/_supported_fields.html.erb +33 -0
- data/app/views/spree/admin/tenants/_form.html.erb +1 -1
- data/app/views/spree/order_mailer/confirm_email.html.erb +1 -1
- data/app/views/spree_cm_commissioner/order_mailer/_mailer_stylesheets.html.erb +14 -13
- data/app/views/spree_cm_commissioner/order_mailer/tenant/_greeting.html.erb +6 -4
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/km.yml +65 -61
- data/config/routes.rb +15 -1
- data/db/migrate/20250915075830_create_spree_cm_commissioner_pricing_models.rb +17 -0
- data/db/migrate/20250915080733_create_spree_cm_commissioner_pricing_model_variants.rb +14 -0
- data/db/migrate/20251003082144_create_spree_cm_commissioner_pricing_rule_groups.rb +16 -0
- data/db/migrate/20251003093408_create_spree_cm_commissioner_pricing_rule.rb +19 -0
- data/db/migrate/20251003093643_create_spree_cm_commissioner_pricing_action.rb +14 -0
- data/db/migrate/20251119093000_add_tenant_id_to_cm_vendor_places.rb +8 -0
- data/lib/spree_cm_commissioner/intercity_taxi/distance.rb +38 -0
- data/lib/spree_cm_commissioner/intercity_taxi/map_place.rb +31 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_action_factory.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_model_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_rule_factory.rb +17 -0
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_rule_group_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/product_completion_step_banner_factory.rb +7 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +2 -0
- metadata +54 -4
|
@@ -12,7 +12,10 @@ module SpreeCmCommissioner
|
|
|
12
12
|
through: :vendors,
|
|
13
13
|
source: :payment_methods
|
|
14
14
|
|
|
15
|
-
validates :host,
|
|
15
|
+
validates :host, presence: true, uniqueness: true,
|
|
16
|
+
format: { without: %r{\Ahttps?://},
|
|
17
|
+
message: :format
|
|
18
|
+
}
|
|
16
19
|
|
|
17
20
|
enum state: { enabled: 0, disabled: 1 }
|
|
18
21
|
|
|
@@ -22,6 +25,16 @@ module SpreeCmCommissioner
|
|
|
22
25
|
vendors.where(state: :active).first
|
|
23
26
|
end
|
|
24
27
|
|
|
28
|
+
def url
|
|
29
|
+
host
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def formatted_url
|
|
33
|
+
return if host.blank?
|
|
34
|
+
|
|
35
|
+
Rails.env.development? || Rails.env.test? ? "http://#{host}" : "https://#{host}"
|
|
36
|
+
end
|
|
37
|
+
|
|
25
38
|
private
|
|
26
39
|
|
|
27
40
|
def generate_slug
|
|
@@ -30,6 +30,9 @@ module SpreeCmCommissioner
|
|
|
30
30
|
|
|
31
31
|
base.has_many :inventory_items, class_name: 'SpreeCmCommissioner::InventoryItem'
|
|
32
32
|
|
|
33
|
+
base.has_many :pricing_model_variants, class_name: 'SpreeCmCommissioner::PricingModelVariant', dependent: :destroy
|
|
34
|
+
base.has_many :pricing_models, through: :pricing_model_variants, class_name: 'SpreeCmCommissioner::PricingModel'
|
|
35
|
+
|
|
33
36
|
base.scope :subscribable, -> { active.joins(:product).where(product: { subscribable: true, status: :active }) }
|
|
34
37
|
base.scope :with_permanent_stock, -> { where(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
|
|
35
38
|
base.scope :with_non_permanent_stock, -> { where.not(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
|
|
@@ -91,6 +91,7 @@ module SpreeCmCommissioner
|
|
|
91
91
|
base.has_many :trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop'
|
|
92
92
|
base.has_many :boarding_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :boarding_trip_stops
|
|
93
93
|
base.has_many :drop_off_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :drop_off_trip_stops
|
|
94
|
+
base.has_many :pricing_models, class_name: 'SpreeCmCommissioner::PricingModel', foreign_key: :vendor_id, dependent: :destroy
|
|
94
95
|
|
|
95
96
|
base.validates :account_name, :account_number, presence: true, if: lambda {
|
|
96
97
|
payment_qrcode.present? && Spree::Store.default.code.include?('billing')
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class VendorPlace < Base
|
|
3
|
-
enum place_type: {
|
|
3
|
+
enum place_type: { venue: 0, branch: 1, stop: 2, location: 3 }
|
|
4
4
|
acts_as_list scope: :vendor
|
|
5
5
|
|
|
6
|
+
belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant', optional: true
|
|
6
7
|
belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
|
|
7
8
|
belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: false
|
|
8
9
|
belongs_to :location, class_name: 'SpreeCmCommissioner::VendorPlace', optional: true
|
|
@@ -16,6 +17,8 @@ module SpreeCmCommissioner
|
|
|
16
17
|
|
|
17
18
|
accepts_nested_attributes_for :place, allow_destroy: true
|
|
18
19
|
|
|
20
|
+
before_save :set_tenant_id
|
|
21
|
+
|
|
19
22
|
# include place when using these delegate to avoid N+1
|
|
20
23
|
def display_name
|
|
21
24
|
place&.name
|
|
@@ -28,5 +31,11 @@ module SpreeCmCommissioner
|
|
|
28
31
|
def selected
|
|
29
32
|
vendor.selected_place_references.include?(place&.reference)
|
|
30
33
|
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def set_tenant_id
|
|
38
|
+
self.tenant_id = vendor&.tenant_id
|
|
39
|
+
end
|
|
31
40
|
end
|
|
32
41
|
end
|
|
@@ -37,6 +37,15 @@
|
|
|
37
37
|
<% end %>
|
|
38
38
|
</div>
|
|
39
39
|
|
|
40
|
+
<!-- Telegram New Vendor Alert Chat ID -->
|
|
41
|
+
<div class="col-6">
|
|
42
|
+
<%= f.field_container :preferred_telegram_new_vendor_alert_chat_id do %>
|
|
43
|
+
<%= f.label :preferred_telegram_new_vendor_alert_chat_id, Spree.t(:telegram_new_vendor_alert_chat_id) %>
|
|
44
|
+
<%= f.text_field :preferred_telegram_new_vendor_alert_chat_id, class: 'form-control' %>
|
|
45
|
+
<%= f.error_message_on :preferred_telegram_new_vendor_alert_chat_id %>
|
|
46
|
+
<% end %>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
40
49
|
<!-- Assetlinks -->
|
|
41
50
|
<div class="col-12">
|
|
42
51
|
<%= f.field_container :preferred_assetlinks do %>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
class TripQuery
|
|
3
|
-
attr_reader :origin_id, :destination_id, :date, :vendor_id, :number_of_guests, :route_type, :params
|
|
3
|
+
attr_reader :origin_id, :destination_id, :date, :vendor_id, :tenant_id, :number_of_guests, :route_type, :params
|
|
4
4
|
|
|
5
|
-
def initialize(origin_id:, destination_id:, date:, route_type: nil, vendor_id: nil, number_of_guests: nil, params: {}) # rubocop:disable Metrics/ParameterLists
|
|
5
|
+
def initialize(origin_id:, destination_id:, date:, route_type: nil, vendor_id: nil, tenant_id: nil, number_of_guests: nil, params: {}) # rubocop:disable Metrics/ParameterLists
|
|
6
6
|
@origin_id = origin_id
|
|
7
7
|
@destination_id = destination_id
|
|
8
8
|
@date = date.to_date == Time.zone.now.to_date ? Time.zone.now : Time.zone.parse(date.to_s)
|
|
9
9
|
@vendor_id = vendor_id
|
|
10
|
+
@tenant_id = tenant_id
|
|
10
11
|
@number_of_guests = number_of_guests || 1
|
|
11
12
|
@route_type = route_type
|
|
12
13
|
@params = params
|
|
@@ -36,8 +37,9 @@ module SpreeCmCommissioner
|
|
|
36
37
|
|
|
37
38
|
def direct_trips
|
|
38
39
|
result = trip_scope
|
|
39
|
-
result = result.where({ vendor_id: vendor_id }.compact)
|
|
40
|
+
result = result.where({ vendor_id: vendor_id }.compact) if vendor_id.present?
|
|
40
41
|
result = result.where(route_type: route_type) if route_type.present?
|
|
42
|
+
result = result.where(spree_vendors: { tenant_id: tenant_id }) if tenant_id.present?
|
|
41
43
|
paginate(result)
|
|
42
44
|
end
|
|
43
45
|
|
|
@@ -56,20 +58,24 @@ module SpreeCmCommissioner
|
|
|
56
58
|
private
|
|
57
59
|
|
|
58
60
|
def trip_scope
|
|
59
|
-
SpreeCmCommissioner::Trip
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
scope = SpreeCmCommissioner::Trip
|
|
62
|
+
.select(<<~SQL.squish)
|
|
63
|
+
cm_trips.*,
|
|
64
|
+
boarding.departure_time AS boarding_departure_time,
|
|
65
|
+
boarding.stop_place_id AS boarding_stop_id, boarding.stop_name AS boarding_stop_name,
|
|
66
|
+
drop_off.stop_name AS drop_off_stop_name, drop_off.stop_place_id AS drop_off_stop_id,
|
|
67
|
+
drop_off.arrival_time AS drop_off_arrival_time,
|
|
68
|
+
COALESCE(iv.quantity_available, 0) AS quantity_available,
|
|
69
|
+
COALESCE(iv.max_capacity, 0) AS max_capacity,
|
|
70
|
+
origin_places.name AS origin_place_name, dest_places.name AS destination_place_name,
|
|
71
|
+
prices.amount AS amount, prices.compare_at_amount AS compare_at_amount,
|
|
72
|
+
prices.currency AS currency
|
|
73
|
+
SQL
|
|
74
|
+
.includes(vendor: :logo, vehicle: :option_values)
|
|
75
|
+
|
|
76
|
+
scope = scope.joins(:vendor) if tenant_id.present?
|
|
77
|
+
|
|
78
|
+
scope
|
|
73
79
|
.joins(<<~SQL.squish)
|
|
74
80
|
INNER JOIN cm_trip_stops AS boarding ON boarding.trip_id = cm_trips.id AND boarding.stop_type = 0
|
|
75
81
|
INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = cm_trips.id AND drop_off.stop_type = 1
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class IntercityTaxiDraftOrderSchema < ApplicationRequestSchema
|
|
3
|
+
params do
|
|
4
|
+
required(:trip_id).value(:integer)
|
|
5
|
+
required(:from_date).value(:date)
|
|
6
|
+
required(:to_date).value(:date)
|
|
7
|
+
required(:quantity).value(:integer)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class IntercityTaxiDraftOrderUpdateSchema < ApplicationRequestSchema
|
|
3
|
+
params do
|
|
4
|
+
optional(:remark).filled(:string)
|
|
5
|
+
optional(:pickup_map_place_attributes).hash do
|
|
6
|
+
optional(:place_name).filled(:string)
|
|
7
|
+
optional(:lat).filled(:string)
|
|
8
|
+
optional(:lng).filled(:string)
|
|
9
|
+
optional(:oob_confirmed).filled(:bool)
|
|
10
|
+
end
|
|
11
|
+
optional(:dropoff_map_place_attributes).hash do
|
|
12
|
+
optional(:place_name).filled(:string)
|
|
13
|
+
optional(:lat).filled(:string)
|
|
14
|
+
optional(:lng).filled(:string)
|
|
15
|
+
optional(:oob_confirmed).filled(:bool)
|
|
16
|
+
end
|
|
17
|
+
optional(:distance_attributes).hash do
|
|
18
|
+
optional(:distance_km).filled(:float)
|
|
19
|
+
optional(:ordered_points).filled(:array)
|
|
20
|
+
optional(:estimated_time_minutes).filled(:integer)
|
|
21
|
+
optional(:base_km).filled(:float)
|
|
22
|
+
optional(:detour_pickup_km).filled(:float)
|
|
23
|
+
optional(:detour_dropoff_km).filled(:float)
|
|
24
|
+
optional(:extra_pickup_km).filled(:float)
|
|
25
|
+
optional(:extra_dropoff_km).filled(:float)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class RoutePlacesRequestSchema < ApplicationRequestSchema
|
|
3
|
+
params do
|
|
4
|
+
required(:place_type).filled(:string)
|
|
5
|
+
required(:query).filled(:string)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
rule(:place_type) do
|
|
9
|
+
key.failure('Invalid place_type. Use origin or destination') unless %w[origin destination].include?(value)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -4,8 +4,9 @@ module Spree
|
|
|
4
4
|
class PlaceSerializer < BaseSerializer
|
|
5
5
|
set_type :place
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
has_many :
|
|
7
|
+
# Included by default, pass false to exclude
|
|
8
|
+
has_many :vendors, if: proc { |_, params| params.nil? || params[:include_vendors] != false }
|
|
9
|
+
has_many :nearby_places, serializer: :nearby_place, if: proc { |_, params| params.nil? || params[:include_nearby_places] != false }
|
|
9
10
|
|
|
10
11
|
attributes :reference, :name, :vicinity, :lat, :lon, :icon, :url, :rating,
|
|
11
12
|
:formatted_phone_number, :formatted_address, :address_components, :types
|
|
@@ -20,6 +20,7 @@ module Spree
|
|
|
20
20
|
has_many :promotions, object_method_name: :valid_promotions, id_method_name: :valid_promotion_ids,
|
|
21
21
|
serializer: Spree::V2::Storefront::PromotionSerializer
|
|
22
22
|
|
|
23
|
+
has_many :saved_guests, serializer: SpreeCmCommissioner::V2::Storefront::SavedGuestSerializer
|
|
23
24
|
has_many :variants, serializer: Spree::V2::Tenant::VariantSerializer
|
|
24
25
|
has_many :products, serializer: Spree::V2::Tenant::ProductSerializer
|
|
25
26
|
has_many :line_items, serializer: Spree::V2::Tenant::LineItemSerializer
|
|
@@ -20,6 +20,7 @@ module Spree
|
|
|
20
20
|
|
|
21
21
|
has_one :vendor, serializer: Spree::V2::Tenant::VendorSerializer
|
|
22
22
|
has_one :product, serializer: Spree::V2::Storefront::ProductSerializer
|
|
23
|
+
has_many :saved_guests, serializer: SpreeCmCommissioner::V2::Storefront::SavedGuestSerializer
|
|
23
24
|
|
|
24
25
|
belongs_to :variant, serializer: Spree::V2::Tenant::VariantSerializer
|
|
25
26
|
belongs_to :order, serializer: Spree::V2::Tenant::OrderSerializer
|
data/app/serializers/spree_cm_commissioner/v2/storefront/intercity_taxi_line_item_serializer.rb
CHANGED
|
@@ -2,29 +2,28 @@ module SpreeCmCommissioner
|
|
|
2
2
|
module V2
|
|
3
3
|
module Storefront
|
|
4
4
|
class IntercityTaxiLineItemSerializer < BaseSerializer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
:
|
|
8
|
-
:
|
|
9
|
-
:drop_off_lat,
|
|
10
|
-
:drop_off_lng,
|
|
11
|
-
:passenger_count,
|
|
12
|
-
:distance_km,
|
|
13
|
-
:ordered_points,
|
|
14
|
-
:base_km,
|
|
15
|
-
:detour_pickup_km,
|
|
16
|
-
:detour_dropoff_km,
|
|
17
|
-
:extra_pickup_km,
|
|
18
|
-
:extra_dropoff_km,
|
|
19
|
-
:extra_pickup_charge_usd,
|
|
20
|
-
:extra_dropoff_charge_usd,
|
|
21
|
-
:estimated_time_minutes,
|
|
5
|
+
# Nested-only API shape
|
|
6
|
+
attributes :pickup_map_place,
|
|
7
|
+
:dropoff_map_place,
|
|
8
|
+
:distance,
|
|
22
9
|
:from_date,
|
|
23
10
|
:to_date,
|
|
24
|
-
:
|
|
11
|
+
:remark,
|
|
25
12
|
:trip_id
|
|
26
13
|
|
|
27
14
|
cache_options store: nil
|
|
15
|
+
|
|
16
|
+
def pickup_map_place
|
|
17
|
+
object.pickup_map_place&.to_h
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def dropoff_map_place
|
|
21
|
+
object.dropoff_map_place&.to_h
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def distance
|
|
25
|
+
object.distance&.to_h
|
|
26
|
+
end
|
|
28
27
|
end
|
|
29
28
|
end
|
|
30
29
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module V2
|
|
3
|
+
module Storefront
|
|
4
|
+
class RouteSerializer < BaseSerializer
|
|
5
|
+
attributes :route_name
|
|
6
|
+
|
|
7
|
+
has_one :origin_place, serializer: ::Spree::V2::Storefront::PlaceSerializer
|
|
8
|
+
has_one :destination_place, serializer: ::Spree::V2::Storefront::PlaceSerializer
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -4,7 +4,7 @@ module SpreeCmCommissioner
|
|
|
4
4
|
class TripVehicleSerializer < BaseSerializer
|
|
5
5
|
set_type :vehicle
|
|
6
6
|
|
|
7
|
-
attributes :id, :code, :vehicle_type
|
|
7
|
+
attributes :id, :code, :vehicle_type, :number_of_seats
|
|
8
8
|
|
|
9
9
|
has_many :vehicle_photos, serializer: ::SpreeCmCommissioner::V2::Storefront::AssetSerializer
|
|
10
10
|
has_many :amenities, serializer: ::SpreeCmCommissioner::V2::Storefront::AmenitySerializer
|
|
@@ -1,35 +1,19 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module IntercityTaxiOrder
|
|
3
3
|
class Create
|
|
4
|
-
|
|
4
|
+
prepend ::Spree::ServiceModule::Base
|
|
5
5
|
|
|
6
|
-
def
|
|
7
|
-
|
|
8
|
-
trip_id: trip_id,
|
|
9
|
-
from_date: from_date,
|
|
10
|
-
to_date: to_date,
|
|
11
|
-
user_id: user_id,
|
|
12
|
-
quantity: quantity
|
|
13
|
-
).call
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def initialize(trip_id:, from_date:, to_date:, user_id:, quantity:)
|
|
17
|
-
@trip_id = trip_id
|
|
18
|
-
@from_date = from_date
|
|
19
|
-
@to_date = to_date
|
|
20
|
-
@user_id = user_id
|
|
21
|
-
@quantity = quantity.to_i <= 0 ? 1 : quantity.to_i
|
|
22
|
-
end
|
|
6
|
+
def call(trip_id:, from_date:, to_date:, user: nil, quantity: 1)
|
|
7
|
+
validate!(trip_id: trip_id, from_date: from_date, to_date: to_date, quantity: quantity)
|
|
23
8
|
|
|
24
|
-
|
|
25
|
-
validate!
|
|
9
|
+
quantity = quantity.to_i
|
|
26
10
|
|
|
27
|
-
ActiveRecord::Base.transaction do
|
|
11
|
+
order = ActiveRecord::Base.transaction do
|
|
28
12
|
trip = SpreeCmCommissioner::Trip.find(trip_id)
|
|
29
13
|
variant = trip.product.variants.first
|
|
30
14
|
raise ArgumentError, 'No variant found for trip' if variant.blank?
|
|
31
15
|
|
|
32
|
-
order = Spree::Order.new(state: 'cart', use_billing: true,
|
|
16
|
+
order = Spree::Order.new(state: 'cart', use_billing: true, user: user)
|
|
33
17
|
|
|
34
18
|
line_item = order.line_items.new(
|
|
35
19
|
variant_id: variant.id,
|
|
@@ -42,26 +26,39 @@ module SpreeCmCommissioner
|
|
|
42
26
|
)
|
|
43
27
|
|
|
44
28
|
build_guests_for!(line_item, quantity)
|
|
29
|
+
assign_saved_guests_to_line_item(line_item)
|
|
45
30
|
|
|
46
31
|
order.save!
|
|
47
32
|
order.update_with_updater!
|
|
48
33
|
|
|
49
34
|
order
|
|
50
35
|
end
|
|
36
|
+
|
|
37
|
+
success(order)
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
failure(nil, e.message)
|
|
51
40
|
end
|
|
52
41
|
|
|
53
42
|
private
|
|
54
43
|
|
|
55
|
-
def validate!
|
|
44
|
+
def validate!(trip_id:, from_date:, to_date:, quantity:)
|
|
56
45
|
raise ArgumentError, 'trip_id is required' if trip_id.blank?
|
|
57
46
|
raise ArgumentError, 'from_date is required' if from_date.blank?
|
|
58
47
|
raise ArgumentError, 'to_date is required' if to_date.blank?
|
|
59
48
|
raise ArgumentError, 'to_date must be after from_date' if from_date.present? && to_date.present? && to_date < from_date
|
|
49
|
+
raise ArgumentError, 'quantity must be 1' if quantity.to_i != 1
|
|
60
50
|
end
|
|
61
51
|
|
|
62
52
|
def build_guests_for!(line_item, qty)
|
|
63
53
|
Array.new(qty) { line_item.guests.new }
|
|
64
54
|
end
|
|
55
|
+
|
|
56
|
+
def assign_saved_guests_to_line_item(line_item)
|
|
57
|
+
line_item.guests.each do |guest|
|
|
58
|
+
saved_guest = SpreeCmCommissioner::SavedGuest.new
|
|
59
|
+
guest.saved_guest = saved_guest
|
|
60
|
+
end
|
|
61
|
+
end
|
|
65
62
|
end
|
|
66
63
|
end
|
|
67
64
|
end
|
|
@@ -1,78 +1,42 @@
|
|
|
1
1
|
module SpreeCmCommissioner
|
|
2
2
|
module IntercityTaxiOrder
|
|
3
3
|
class Update
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
:intel_phone_number,
|
|
41
|
-
:email,
|
|
42
|
-
line_items_attributes: [
|
|
43
|
-
:id,
|
|
44
|
-
:pickup_place_name,
|
|
45
|
-
:drop_off_place_name,
|
|
46
|
-
:from_date,
|
|
47
|
-
:pickup_lat,
|
|
48
|
-
:pickup_lng,
|
|
49
|
-
:pickup_oob_confirmed,
|
|
50
|
-
:drop_off_lat,
|
|
51
|
-
:drop_off_lng,
|
|
52
|
-
:drop_off_oob_confirmed,
|
|
53
|
-
:distance_km,
|
|
54
|
-
:ordered_points,
|
|
55
|
-
:base_km,
|
|
56
|
-
:detour_pickup_km,
|
|
57
|
-
:detour_dropoff_km,
|
|
58
|
-
:extra_pickup_km,
|
|
59
|
-
:extra_dropoff_km,
|
|
60
|
-
:extra_pickup_charge_usd,
|
|
61
|
-
:extra_dropoff_charge_usd,
|
|
62
|
-
:estimated_time_minutes,
|
|
63
|
-
:remark,
|
|
64
|
-
:passenger_count,
|
|
65
|
-
{ guests_attributes: %i[
|
|
66
|
-
id
|
|
67
|
-
first_name
|
|
68
|
-
last_name
|
|
69
|
-
gender
|
|
70
|
-
nationality_id
|
|
71
|
-
age
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
)
|
|
4
|
+
prepend ::Spree::ServiceModule::Base
|
|
5
|
+
|
|
6
|
+
def call(
|
|
7
|
+
order:,
|
|
8
|
+
remark: nil,
|
|
9
|
+
pickup_map_place_attributes: nil,
|
|
10
|
+
dropoff_map_place_attributes: nil,
|
|
11
|
+
distance_attributes: nil
|
|
12
|
+
)
|
|
13
|
+
line_item = order.line_items.first
|
|
14
|
+
|
|
15
|
+
raise ArgumentError, 'Order has no line items' if line_item.blank?
|
|
16
|
+
|
|
17
|
+
if pickup_map_place_attributes.present?
|
|
18
|
+
line_item.pickup_map_place = SpreeCmCommissioner::IntercityTaxi::MapPlace.new(
|
|
19
|
+
pickup_map_place_attributes
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if dropoff_map_place_attributes.present?
|
|
24
|
+
line_item.dropoff_map_place = SpreeCmCommissioner::IntercityTaxi::MapPlace.new(
|
|
25
|
+
dropoff_map_place_attributes
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if distance_attributes.present?
|
|
30
|
+
line_item.distance = SpreeCmCommissioner::IntercityTaxi::Distance.new(
|
|
31
|
+
distance_attributes
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
line_item.update!(remark: remark)
|
|
36
|
+
|
|
37
|
+
success(order.reload)
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
failure(nil, e.message)
|
|
76
40
|
end
|
|
77
41
|
end
|
|
78
42
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module PricingModels
|
|
3
|
+
class Apply
|
|
4
|
+
def initialize(line_item_id:, pricing_model_id:)
|
|
5
|
+
@line_item_id = line_item_id
|
|
6
|
+
@pricing_model_id = pricing_model_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call
|
|
10
|
+
pricing_model.pricing_rule_groups.each do |group|
|
|
11
|
+
apply_group(group, line_item)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
attr_reader :line_item_id, :pricing_model_id
|
|
18
|
+
|
|
19
|
+
def line_item
|
|
20
|
+
@line_item ||= Spree::LineItem.find(line_item_id)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def pricing_model
|
|
24
|
+
@pricing_model ||= SpreeCmCommissioner::PricingModel.find(pricing_model_id)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def apply_group(group, line_item)
|
|
28
|
+
eligible_rules = group.pricing_rules.select { |r| r.eligible?(line_item) }
|
|
29
|
+
|
|
30
|
+
return if eligible_rules.empty?
|
|
31
|
+
|
|
32
|
+
if group_eligible?(group, eligible_rules)
|
|
33
|
+
group.pricing_action&.perform(line_item)
|
|
34
|
+
else
|
|
35
|
+
Rails.logger.info("Group #{group.id} not eligible for line_item #{line_item.id}")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def group_eligible?(group, eligible_rules)
|
|
40
|
+
case group.match_type
|
|
41
|
+
when 'all'
|
|
42
|
+
eligible_rules.size == group.pricing_rules.size
|
|
43
|
+
when 'any'
|
|
44
|
+
eligible_rules.any?
|
|
45
|
+
else
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module PricingRules
|
|
3
|
+
module BuildParams
|
|
4
|
+
module_function
|
|
5
|
+
|
|
6
|
+
def permitted_group_params(params)
|
|
7
|
+
group_params = params[:spree_cm_commissioner_pricing_rule_group] || params
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
name: group_params[:name],
|
|
11
|
+
status: group_params[:status],
|
|
12
|
+
template_key: group_params[:template_key],
|
|
13
|
+
match_type: group_params[:match_type],
|
|
14
|
+
pricing_rules_attributes: build_rules_attributes(params[:pricing_rules]),
|
|
15
|
+
pricing_action_attributes: build_action_attributes(params[:pricing_action])
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build_rules_attributes(rules_array)
|
|
20
|
+
return [] unless rules_array
|
|
21
|
+
|
|
22
|
+
rules_array.map do |r|
|
|
23
|
+
{
|
|
24
|
+
id: r[:id],
|
|
25
|
+
type: r[:type],
|
|
26
|
+
private_metadata: r[:private_metadata],
|
|
27
|
+
_destroy: r[:_destroy]
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build_action_attributes(action_data)
|
|
33
|
+
return nil unless action_data&.dig(:calculator)
|
|
34
|
+
|
|
35
|
+
calc_data = action_data[:calculator]
|
|
36
|
+
calculator = calc_data[:type].safe_constantize&.new
|
|
37
|
+
set_preferences(calculator, calc_data[:preferences]) if calculator
|
|
38
|
+
|
|
39
|
+
{ id: action_data[:id], calculator: calculator }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def set_preferences(calculator, preferences)
|
|
43
|
+
return unless preferences && calculator
|
|
44
|
+
|
|
45
|
+
prefs = preferences.respond_to?(:to_unsafe_h) ? preferences.to_unsafe_h : preferences
|
|
46
|
+
prefs.each do |key, value|
|
|
47
|
+
setter = "preferred_#{key}="
|
|
48
|
+
calculator.public_send(setter, value) if calculator.respond_to?(setter)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|