spree_cm_commissioner 2.0.3.pre.pre5 → 2.0.3.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/Gemfile.lock +1 -1
- data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +2 -8
- data/app/controllers/spree/api/v2/storefront/trip_places_controller.rb +29 -0
- data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +2 -0
- data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +14 -0
- data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +17 -4
- data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
- data/app/models/spree_cm_commissioner/address_decorator.rb +17 -3
- data/app/models/spree_cm_commissioner/order/address_book_decorator.rb +30 -12
- data/app/models/spree_cm_commissioner/order_decorator.rb +8 -1
- data/app/models/spree_cm_commissioner/place.rb +2 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +29 -0
- data/app/models/spree_cm_commissioner/saved_guest.rb +2 -0
- data/app/models/spree_cm_commissioner/trip.rb +4 -2
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +3 -0
- data/app/overrides/spree/admin/products/_form/industry_taxons.html.erb.deface +26 -0
- data/app/overrides/spree/admin/products/_form/taxons.html.erb.deface +26 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +18 -18
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -0
- data/app/serializers/spree/v2/storefront/trip_place_serializer.rb +10 -0
- data/app/serializers/spree/v2/storefront/trip_result_serializer.rb +2 -1
- data/app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb +1 -1
- data/db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb +8 -0
- data/db/migrate/20250814073854_add_call_to_action_to_spree_products.rb +5 -0
- data/lib/spree_cm_commissioner/transit/leg.rb +14 -0
- data/lib/spree_cm_commissioner/transit/seat_selection.rb +9 -1
- data/lib/spree_cm_commissioner/trip_query_result.rb +34 -0
- data/lib/spree_cm_commissioner/trip_result.rb +8 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3386c245e402dd11660e1215a50dac52acfd59950f95afb03117bff6c56053a5
|
4
|
+
data.tar.gz: 551927bdc54caee21d0ca26601c2d42b5ee0cd14b5c4264da1a5ae3968270d4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8c9f527ea17e43fabfcf7ecba55e70887a51a31a85849e918cf508cc8bc8d6a3b6f6165f534139fad9704902a7aea8875b58798514caf63882b2914534cc693
|
7
|
+
data.tar.gz: ca8d78212f84afd5091ac23617a88d49b096cc526e84a3aedc2c9b432fe02aaf55546a5a54bfe8c0704be30a72050d01c7be88a505b37abea3f4d634a1829ea5
|
data/Gemfile.lock
CHANGED
@@ -11,17 +11,11 @@ module Spree
|
|
11
11
|
types = ADDITIONAL_FIELDS + kyc_fields
|
12
12
|
|
13
13
|
resources = types.map do |type|
|
14
|
-
event_chart = SpreeCmCommissioner::EventChartQueries.new(
|
15
|
-
taxon_id: params[:taxon_id],
|
16
|
-
chart_type: type,
|
17
|
-
refreshed: params[:refreshed] || false
|
18
|
-
).call
|
19
|
-
|
20
14
|
# Create unique ID by using chart_type as the identifier
|
21
15
|
SpreeCmCommissioner::EventChart.new(
|
22
16
|
id: type.to_s,
|
23
|
-
chart_type:
|
24
|
-
product_charts:
|
17
|
+
chart_type: type,
|
18
|
+
product_charts: nil
|
25
19
|
)
|
26
20
|
end
|
27
21
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Storefront
|
5
|
+
class TripPlacesController < ::Spree::Api::V2::ResourceController
|
6
|
+
# override
|
7
|
+
def collection
|
8
|
+
base_scope = model_class.joins(:location_vendor_places).distinct
|
9
|
+
|
10
|
+
if params[:q].present?
|
11
|
+
@search = base_scope.ransack(params[:q])
|
12
|
+
@search.result
|
13
|
+
else
|
14
|
+
base_scope
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def model_class
|
19
|
+
SpreeCmCommissioner::Place
|
20
|
+
end
|
21
|
+
|
22
|
+
def collection_serializer
|
23
|
+
Spree::V2::Storefront::TripPlaceSerializer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,6 +5,7 @@ module SpreeCmCommissioner
|
|
5
5
|
# spree update user sign_in_count
|
6
6
|
base.around_action :set_writing_role, only: %i[index]
|
7
7
|
base.after_action :set_tenant_after_update, only: %i[update]
|
8
|
+
base.before_action :merge_industry_taxons_into_taxons, only: [:update]
|
8
9
|
end
|
9
10
|
|
10
11
|
# Override
|
@@ -50,6 +51,19 @@ module SpreeCmCommissioner
|
|
50
51
|
|
51
52
|
protected
|
52
53
|
|
54
|
+
def merge_industry_taxons_into_taxons
|
55
|
+
return if params[:product].blank?
|
56
|
+
|
57
|
+
industry_ids = Array(params[:product][:industry_taxon_ids]).compact_blank
|
58
|
+
taxon_ids = Array(params[:product][:taxon_ids]).compact_blank
|
59
|
+
|
60
|
+
merged_ids = (taxon_ids + industry_ids).uniq
|
61
|
+
|
62
|
+
params[:product][:taxon_ids] = merged_ids
|
63
|
+
|
64
|
+
params[:product].delete(:industry_taxon_ids)
|
65
|
+
end
|
66
|
+
|
53
67
|
def find_resource
|
54
68
|
product_scope.with_deleted.includes(vendor: :tenant).friendly.find(params[:id])
|
55
69
|
end
|
@@ -53,6 +53,8 @@ module SpreeCmCommissioner
|
|
53
53
|
|
54
54
|
legs.each do |leg|
|
55
55
|
leg_line_items = build_line_items_for!(leg, order, current_leg_date)
|
56
|
+
leg_line_items = insert_saved_guests_per_line_items_leg(leg_line_items)
|
57
|
+
|
56
58
|
all_line_items.concat(leg_line_items)
|
57
59
|
current_leg_date = leg_line_items.last.to_date.to_date if leg_line_items.any?
|
58
60
|
end
|
@@ -85,13 +87,11 @@ module SpreeCmCommissioner
|
|
85
87
|
}
|
86
88
|
)
|
87
89
|
|
88
|
-
|
89
|
-
|
90
|
-
line_item
|
90
|
+
build_guests_for!(line_item, seat_selections)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def
|
94
|
+
def build_guests_for!(line_item, seat_selections)
|
95
95
|
block_ids = seat_selections.flat_map(&:block_ids)
|
96
96
|
|
97
97
|
if block_ids.any? && block_ids.size != line_item.quantity
|
@@ -101,6 +101,19 @@ module SpreeCmCommissioner
|
|
101
101
|
Array.new(line_item.quantity) do |index|
|
102
102
|
line_item.guests.new(block_id: block_ids[index])
|
103
103
|
end
|
104
|
+
|
105
|
+
line_item
|
106
|
+
end
|
107
|
+
|
108
|
+
def insert_saved_guests_per_line_items_leg(line_items)
|
109
|
+
line_items.flat_map(&:guests).each_with_index do |guest, index|
|
110
|
+
context.saved_guests ||= []
|
111
|
+
context.saved_guests << SpreeCmCommissioner::SavedGuest.new if context.saved_guests[index].blank?
|
112
|
+
|
113
|
+
guest.saved_guest = context.saved_guests[index]
|
114
|
+
end
|
115
|
+
|
116
|
+
line_items
|
104
117
|
end
|
105
118
|
|
106
119
|
def calculate_line_item_duration!(date:, departure_time:, arrival_time:)
|
@@ -3,7 +3,7 @@ module SpreeCmCommissioner
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
enum kind: { category: 0, cms: 1, event: 2, occupation: 3, nationality: 4, organization: 5 }
|
6
|
+
enum kind: { category: 0, cms: 1, event: 2, occupation: 3, nationality: 4, organization: 5, transit: 6, industry: 7 }
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -8,6 +8,12 @@ module SpreeCmCommissioner
|
|
8
8
|
base.validates :country, presence: true, if: :require_country?
|
9
9
|
end
|
10
10
|
|
11
|
+
# override to return false instead of true
|
12
|
+
# in case no country
|
13
|
+
def require_zipcode?
|
14
|
+
country ? country.zipcode_required? : false
|
15
|
+
end
|
16
|
+
|
11
17
|
def require_address1?
|
12
18
|
false
|
13
19
|
end
|
@@ -22,9 +28,17 @@ module SpreeCmCommissioner
|
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
31
|
+
if Spree::Address.included_modules.exclude?(SpreeCmCommissioner::AddressDecorator)
|
32
|
+
keys = %i[address1 city country]
|
33
|
+
|
34
|
+
Spree::Address._validators.reject! { |key, _| keys.include?(key) }
|
35
|
+
Spree::Address._validate_callbacks.each do |c|
|
36
|
+
next unless c.filter.respond_to?(:attributes)
|
37
|
+
|
38
|
+
c.filter.attributes.delete(:address1)
|
39
|
+
c.filter.attributes.delete(:city)
|
40
|
+
c.filter.attributes.delete(:country)
|
41
|
+
end
|
28
42
|
|
29
43
|
Spree::Address.prepend(SpreeCmCommissioner::AddressDecorator)
|
30
44
|
end
|
@@ -5,30 +5,48 @@
|
|
5
5
|
module SpreeCmCommissioner
|
6
6
|
module Order
|
7
7
|
module AddressBookDecorator
|
8
|
-
def guest_order? = user.blank?
|
9
|
-
|
10
8
|
# override
|
11
9
|
def bill_address_attributes=(attributes)
|
12
|
-
attributes[:id] =
|
13
|
-
|
10
|
+
attributes[:id] = bill_address_id if attributes[:id].blank?
|
11
|
+
attributes[:phone] = intel_phone_number if intel_phone_number.present?
|
14
12
|
|
15
|
-
|
13
|
+
self.bill_address = assign_address_attributes(attributes)
|
14
|
+
user.bill_address = bill_address if user && user.bill_address.nil?
|
16
15
|
end
|
17
16
|
|
18
17
|
# override
|
19
18
|
def ship_address_attributes=(attributes)
|
20
|
-
attributes[:id] =
|
21
|
-
|
19
|
+
attributes[:id] = ship_address_id if attributes[:id].blank?
|
20
|
+
attributes[:phone] = intel_phone_number if intel_phone_number.present?
|
22
21
|
|
23
|
-
|
22
|
+
self.ship_address = assign_address_attributes(attributes)
|
23
|
+
user.ship_address = ship_address if user && user.ship_address.nil?
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
def assign_address_attributes(attributes = {})
|
27
|
+
return if attributes.blank?
|
28
|
+
|
29
|
+
attributes.transform_values! { |v| v == '' ? nil : v }
|
30
|
+
attributes = attributes.to_h.symbolize_keys
|
27
31
|
|
28
|
-
|
29
|
-
|
32
|
+
existing_address = attributes[:id].present? ? find_existing_address(attributes[:id]) : nil
|
33
|
+
|
34
|
+
if existing_address&.editable?
|
35
|
+
existing_address.assign_attributes(attributes)
|
36
|
+
existing_address
|
37
|
+
else
|
38
|
+
::Spree::Address.new(attributes.except(:id, :updated_at, :created_at))
|
39
|
+
end
|
40
|
+
end
|
30
41
|
|
31
|
-
|
42
|
+
def find_existing_address(id)
|
43
|
+
if user.present?
|
44
|
+
::Spree::Address.where('(user_id = ? OR user_id IS NULL) AND deleted_at IS NULL', user.id)
|
45
|
+
.find_by(id: id)
|
46
|
+
else
|
47
|
+
::Spree::Address.where(user_id: nil, deleted_at: nil)
|
48
|
+
.find_by(id: id)
|
49
|
+
end
|
32
50
|
end
|
33
51
|
end
|
34
52
|
end
|
@@ -43,7 +43,12 @@ module SpreeCmCommissioner
|
|
43
43
|
base.has_many :vendors, through: :products, class_name: 'Spree::Vendor'
|
44
44
|
base.has_many :taxons, through: :products, class_name: 'Spree::Taxon'
|
45
45
|
base.has_many :guests, through: :line_items, class_name: 'SpreeCmCommissioner::Guest'
|
46
|
-
|
46
|
+
|
47
|
+
base.has_many :saved_guests, -> { distinct.reorder('cm_saved_guests.created_at DESC') },
|
48
|
+
through: :guests,
|
49
|
+
source: :saved_guest,
|
50
|
+
class_name: 'SpreeCmCommissioner::SavedGuest'
|
51
|
+
|
47
52
|
base.has_many :blocks, through: :guests, class_name: 'SpreeCmCommissioner::Block', source: :block
|
48
53
|
base.has_many :reserved_blocks, through: :guests, class_name: 'SpreeCmCommissioner::ReservedBlock'
|
49
54
|
base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass', through: :variants
|
@@ -53,6 +58,8 @@ module SpreeCmCommissioner
|
|
53
58
|
base.whitelisted_ransackable_associations |= %w[customer taxon payments guests invoice]
|
54
59
|
base.whitelisted_ransackable_attributes |= %w[intel_phone_number phone_number email number state]
|
55
60
|
|
61
|
+
base.accepts_nested_attributes_for :saved_guests, allow_destroy: true
|
62
|
+
|
56
63
|
def base.search_by_qr_data!(data)
|
57
64
|
token = data.match(/^R\d{9,}-([A-Za-z0-9_\-]+)$/)&.captures
|
58
65
|
|
@@ -14,6 +14,8 @@ module SpreeCmCommissioner
|
|
14
14
|
has_many :product_places, class_name: 'SpreeCmCommissioner::ProductPlace', dependent: :destroy
|
15
15
|
has_many :products, through: :product_places
|
16
16
|
|
17
|
+
has_many :location_vendor_places, -> { where(place_type: :location) }, class_name: 'SpreeCmCommissioner::VendorPlace'
|
18
|
+
|
17
19
|
has_many :children, -> { order(:lft) }, class_name: 'SpreeCmCommissioner::Place', foreign_key: :parent_id, dependent: :destroy
|
18
20
|
|
19
21
|
has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
|
@@ -48,6 +48,9 @@ module SpreeCmCommissioner
|
|
48
48
|
|
49
49
|
base.belongs_to :event, class_name: 'Spree::Taxon', optional: true
|
50
50
|
|
51
|
+
base.has_many :industry_classifications, -> { joins(:taxon).where(spree_taxons: { kind: :industry }) }, class_name: 'Spree::Classification'
|
52
|
+
base.has_many :industry_taxons, through: :industry_classifications, source: :taxon
|
53
|
+
|
51
54
|
base.scope :min_price, lambda { |vendor|
|
52
55
|
joins(:prices_including_master)
|
53
56
|
.where(vendor_id: vendor.id, product_type: vendor.primary_product_type)
|
@@ -74,6 +77,16 @@ module SpreeCmCommissioner
|
|
74
77
|
base.after_update :sync_event_id_to_children, if: :saved_change_to_event_id?
|
75
78
|
|
76
79
|
base.enum purchasable_on: { both: 0, web: 1, app: 2 }
|
80
|
+
base.enum call_to_action: { buy_now: 0,
|
81
|
+
book_now: 1,
|
82
|
+
reserve: 2,
|
83
|
+
register: 3,
|
84
|
+
apply: 4,
|
85
|
+
get_ticket: 5,
|
86
|
+
secure_your_seat: 6,
|
87
|
+
join_the_event: 7,
|
88
|
+
request_to_book: 8
|
89
|
+
}
|
77
90
|
|
78
91
|
base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
|
79
92
|
base.before_save :set_tenant
|
@@ -83,6 +96,22 @@ module SpreeCmCommissioner
|
|
83
96
|
"#{Spree::Store.default.formatted_url}/tickets/#{slug}"
|
84
97
|
end
|
85
98
|
|
99
|
+
def action_button
|
100
|
+
return :request_to_book if need_confirmation?
|
101
|
+
return :reserve if free?
|
102
|
+
return call_to_action.to_sym if call_to_action.present?
|
103
|
+
|
104
|
+
:buy_now
|
105
|
+
end
|
106
|
+
|
107
|
+
def free?
|
108
|
+
return false if prices_including_master.empty?
|
109
|
+
|
110
|
+
prices_including_master.all? do |master_price|
|
111
|
+
master_price.price.zero? && (master_price.compare_at_price.nil? || master_price.compare_at_price.zero?)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
86
115
|
def dynamic_fields_by_collection_phase
|
87
116
|
{
|
88
117
|
pre_registration: dynamic_fields.pre_registration.order(:position),
|
@@ -8,6 +8,7 @@ module SpreeCmCommissioner
|
|
8
8
|
|
9
9
|
belongs_to :vendor, class_name: 'Spree::Vendor', inverse_of: :trips, optional: false
|
10
10
|
belongs_to :product, class_name: 'Spree::Product', inverse_of: :trip, optional: false
|
11
|
+
|
11
12
|
belongs_to :vehicle, class_name: 'SpreeCmCommissioner::Vehicle', optional: false
|
12
13
|
|
13
14
|
belongs_to :origin_place, class_name: 'SpreeCmCommissioner::Place', optional: false
|
@@ -17,8 +18,8 @@ module SpreeCmCommissioner
|
|
17
18
|
has_many :blazer_queries, through: :trip_blazer_queries, source: :blazer_query, class_name: 'Blazer::Query'
|
18
19
|
|
19
20
|
has_many :trip_stops, class_name: 'SpreeCmCommissioner::TripStop', dependent: :destroy
|
20
|
-
has_many :boarding_trip_stops, -> { boarding }, class_name: 'SpreeCmCommissioner::TripStop'
|
21
|
-
has_many :drop_off_trip_stops, -> { drop_off }, class_name: 'SpreeCmCommissioner::TripStop'
|
21
|
+
has_many :boarding_trip_stops, -> { boarding.order('departure_time ASC NULLS LAST, id ASC') }, class_name: 'SpreeCmCommissioner::TripStop'
|
22
|
+
has_many :drop_off_trip_stops, -> { drop_off.order('arrival_time ASC NULLS LAST') }, class_name: 'SpreeCmCommissioner::TripStop'
|
22
23
|
|
23
24
|
has_many :variants, through: :product
|
24
25
|
has_many :inventory_items, through: :variants
|
@@ -32,6 +33,7 @@ module SpreeCmCommissioner
|
|
32
33
|
accepts_nested_attributes_for :trip_stops, :product, allow_destroy: true
|
33
34
|
|
34
35
|
self.whitelisted_ransackable_associations = %w[product vehicle]
|
36
|
+
self.whitelisted_ransackable_attributes = %w[origin_place_id destination_place_id]
|
35
37
|
|
36
38
|
def convert_duration_to_seconds
|
37
39
|
return if hours.blank? && minutes.blank? && seconds.blank?
|
@@ -84,6 +84,9 @@ module SpreeCmCommissioner
|
|
84
84
|
|
85
85
|
base.has_many :vehicles, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
|
86
86
|
base.has_many :trips, class_name: 'SpreeCmCommissioner::Trip', dependent: :destroy
|
87
|
+
base.has_many :trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop'
|
88
|
+
base.has_many :boarding_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :boarding_trip_stops
|
89
|
+
base.has_many :drop_off_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :drop_off_trip_stops
|
87
90
|
|
88
91
|
base.validates :account_name, :account_number, presence: true, if: lambda {
|
89
92
|
payment_qrcode.present? && Spree::Store.default.code.include?('billing')
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!-- insert_after "[data-hook='admin_product_form_taxons']" -->
|
2
|
+
|
3
|
+
<div data-hook="admin_product_form_industry_taxons">
|
4
|
+
<%= f.field_container :industry_taxons do %>
|
5
|
+
<%= f.label :industry_taxon_ids, Spree.t(:Industries) %>
|
6
|
+
|
7
|
+
<% if can? :modify, Spree::Classification %>
|
8
|
+
<%= f.select :industry_taxon_ids, options_from_collection_for_select(@product.industry_taxons, :id, :pretty_name, @product.industry_taxon_ids),
|
9
|
+
{ include_hidden: true },
|
10
|
+
multiple: true,
|
11
|
+
data: { autocomplete_url_value: 'taxons_api_v2',
|
12
|
+
autocomplete_return_attr_value: 'pretty_name',
|
13
|
+
autocomplete_multiple_value: true,
|
14
|
+
autocomplete_additional_url_params_value: "q[kind_eq]=7" } %>
|
15
|
+
<% elsif @product.industry_taxons.any? %>
|
16
|
+
<ul class="text_list">
|
17
|
+
<% @product.industry_taxons.each do |taxon| %>
|
18
|
+
<li><%= taxon.name %></li>
|
19
|
+
<% end %>
|
20
|
+
</ul>
|
21
|
+
<% else %>
|
22
|
+
<div class="alert alert-info"><%= Spree.t(:no_resource_found, resource: :taxons) %></div>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% end %>
|
26
|
+
</div>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<!-- replace "[data-hook='admin_product_form_taxons']" -->
|
2
|
+
|
3
|
+
<div data-hook="admin_product_form_taxons">
|
4
|
+
<%= f.field_container :taxons do %>
|
5
|
+
<%= f.label :taxon_ids, Spree.t(:taxons) %>
|
6
|
+
|
7
|
+
<% if can? :modify, Spree::Classification %>
|
8
|
+
<%= f.select :taxon_ids, options_from_collection_for_select(@product.taxons, :id, :pretty_name, @product.taxon_ids.reject { |id| @product.industry_taxon_ids.include?(id) }),
|
9
|
+
{ include_hidden: true },
|
10
|
+
multiple: true,
|
11
|
+
data: { autocomplete_url_value: 'taxons_api_v2',
|
12
|
+
autocomplete_return_attr_value: 'pretty_name',
|
13
|
+
autocomplete_multiple_value: true,
|
14
|
+
autocomplete_additional_url_params_value: "q[kind_not_eq]=7" } %>
|
15
|
+
<% elsif @product.taxons.any? %>
|
16
|
+
<ul class="text_list">
|
17
|
+
<% @product.taxons.each do |taxon| %>
|
18
|
+
<li><%= taxon.name %></li>
|
19
|
+
<% end %>
|
20
|
+
</ul>
|
21
|
+
<% else %>
|
22
|
+
<div class="alert alert-info"><%= Spree.t(:no_resource_found, resource: :taxons) %></div>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% end %>
|
26
|
+
</div>
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class TripQuery
|
3
|
-
attr_reader :origin_id, :destination_id, :date
|
3
|
+
attr_reader :origin_id, :destination_id, :date, :vendor_id, :number_of_guests, :params
|
4
4
|
|
5
|
-
def initialize(origin_id:, destination_id:, date:, params: {})
|
5
|
+
def initialize(origin_id:, destination_id:, date:, vendor_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
|
+
@vendor_id = vendor_id
|
10
|
+
@number_of_guests = number_of_guests || 1
|
9
11
|
@params = params
|
10
12
|
@page = (params[:page] || 1).to_i
|
11
|
-
@per_page =
|
13
|
+
@per_page = params[:per_page]
|
12
14
|
end
|
13
15
|
|
14
16
|
def call
|
@@ -17,15 +19,16 @@ module SpreeCmCommissioner
|
|
17
19
|
paginated_relation = direct_trips
|
18
20
|
return Kaminari.paginate_array([]) if paginated_relation.empty?
|
19
21
|
|
20
|
-
|
22
|
+
unique_trips = paginated_relation.uniq(&:id)
|
23
|
+
results_array = unique_trips.map do |trip|
|
21
24
|
result = build_trip_result(trip)
|
22
25
|
SpreeCmCommissioner::TripQueryResult.new([result])
|
23
26
|
end
|
24
27
|
|
25
28
|
Kaminari.paginate_array(
|
26
29
|
results_array,
|
27
|
-
total_count:
|
28
|
-
limit:
|
30
|
+
total_count: unique_trips.size,
|
31
|
+
limit: unique_trips.size,
|
29
32
|
offset: paginated_relation.offset_value
|
30
33
|
)
|
31
34
|
end
|
@@ -51,17 +54,17 @@ module SpreeCmCommissioner
|
|
51
54
|
INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = cm_trips.id AND drop_off.stop_type = 1
|
52
55
|
INNER JOIN cm_places AS origin_places ON origin_places.id = cm_trips.origin_place_id
|
53
56
|
INNER JOIN cm_places AS dest_places ON dest_places.id = cm_trips.destination_place_id
|
54
|
-
INNER JOIN
|
55
|
-
INNER JOIN spree_variants AS master ON master.product_id = spree_products.id AND master.is_master = true
|
57
|
+
INNER JOIN spree_variants AS master ON master.product_id = cm_trips.product_id AND master.is_master = true
|
56
58
|
INNER JOIN spree_prices AS prices ON prices.variant_id = master.id AND prices.deleted_at IS NULL
|
57
59
|
SQL
|
58
|
-
.where('(boarding.location_place_id = ? OR boarding.stop_place_id = ?)
|
59
|
-
AND (drop_off.location_place_id = ? OR drop_off.stop_place_id = ?
|
60
|
+
.where('(boarding.location_place_id = ? OR boarding.stop_place_id = ? OR cm_trips.origin_place_id = ?)
|
61
|
+
AND (drop_off.location_place_id = ? OR drop_off.stop_place_id = ? OR cm_trips.destination_place_id = ?)',
|
62
|
+
origin_id, origin_id, origin_id, destination_id, destination_id, destination_id
|
60
63
|
)
|
61
|
-
.joins("
|
64
|
+
.joins("INNER JOIN (#{@inventory_sql.to_sql}) iv ON cm_trips.product_id = iv.product_id")
|
62
65
|
|
63
|
-
result = result.where(vendor_id:
|
64
|
-
result.page(@page).per(@per_page)
|
66
|
+
result = result.where(vendor_id: vendor_id) if vendor_id.present?
|
67
|
+
@per_page.to_i.positive? ? result.page(@page).per(@per_page) : result.page(@page)
|
65
68
|
end
|
66
69
|
|
67
70
|
def product_inventory_totals
|
@@ -72,16 +75,12 @@ module SpreeCmCommissioner
|
|
72
75
|
SUM(cm_inventory_items.quantity_available) AS quantity_available'
|
73
76
|
)
|
74
77
|
.joins(variants: :inventory_items)
|
75
|
-
.where(cm_inventory_items
|
78
|
+
.where('cm_inventory_items.inventory_date = ? AND cm_inventory_items.quantity_available >= ?', @date.to_date, @number_of_guests)
|
76
79
|
.group('spree_products.id')
|
77
80
|
end
|
78
81
|
|
79
82
|
private
|
80
83
|
|
81
|
-
def cached_inventory_sql
|
82
|
-
@inventory_sql ||= product_inventory_totals
|
83
|
-
end
|
84
|
-
|
85
84
|
def build_trip_result(trip)
|
86
85
|
vehicle = trip&.vehicle
|
87
86
|
vendor = trip&.vendor
|
@@ -90,6 +89,7 @@ module SpreeCmCommissioner
|
|
90
89
|
departure_time: trip&.departure_time,
|
91
90
|
duration: trip&.duration,
|
92
91
|
allow_seat_selection: trip&.allow_seat_selection,
|
92
|
+
route_type: trip&.route_type,
|
93
93
|
origin_place: {
|
94
94
|
id: trip&.origin_place_id,
|
95
95
|
name: trip&.origin_place_name
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Spree
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class TripPlaceSerializer < BaseSerializer
|
5
|
+
attributes :reference, :name, :vicinity, :lat, :lon, :icon, :url, :rating,
|
6
|
+
:formatted_phone_number, :formatted_address, :address_components, :types
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -5,8 +5,9 @@ module Spree
|
|
5
5
|
set_type :trip_result
|
6
6
|
|
7
7
|
attributes :origin_place, :destination_place, :boarding, :drop_off, :price, :compare_at_amount, :currency, :quantity_available, :max_capacity,
|
8
|
-
:allow_seat_selection, :departure_time
|
8
|
+
:allow_seat_selection, :departure_time, :route_type
|
9
9
|
attribute :duration_in_hms, &:duration_in_hms
|
10
|
+
attribute :arrival_time, &:arrival_time
|
10
11
|
belongs_to :vendor, serializer: Spree::V2::Storefront::TripVendorSerializer
|
11
12
|
belongs_to :vehicle, serializer: Spree::V2::Storefront::TripVehicleSerializer
|
12
13
|
has_many :amenities, serializer: Spree::V2::Storefront::AmenitySerializer
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class RemoveUniqueIndexesFromCmUserIdentityProviders < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
if index_exists?(:cm_user_identity_providers, [:identity_type, :sub], name: "index_cm_user_identity_providers_on_identity_type_and_sub")
|
4
|
+
remove_index :cm_user_identity_providers,
|
5
|
+
name: "index_cm_user_identity_providers_on_identity_type_and_sub"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
@@ -19,5 +19,19 @@ module SpreeCmCommissioner::Transit
|
|
19
19
|
seat_selections: (hash[:seat_selections] || []).map { |seat_selection| SeatSelection.from_hash(seat_selection) }
|
20
20
|
)
|
21
21
|
end
|
22
|
+
|
23
|
+
def quantity
|
24
|
+
@seat_selections.sum(&:quantity).to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_h
|
28
|
+
{
|
29
|
+
direction: @direction,
|
30
|
+
trip_id: @trip_id,
|
31
|
+
boarding_trip_stop_id: @boarding_trip_stop_id,
|
32
|
+
drop_off_trip_stop_id: @drop_off_trip_stop_id,
|
33
|
+
seat_selections: @seat_selections.map(&:to_h)
|
34
|
+
}
|
35
|
+
end
|
22
36
|
end
|
23
37
|
end
|
@@ -4,7 +4,7 @@ module SpreeCmCommissioner::Transit
|
|
4
4
|
|
5
5
|
def initialize(options = {})
|
6
6
|
@variant_id = options[:variant_id]
|
7
|
-
@quantity = options[:quantity]
|
7
|
+
@quantity = options[:quantity]&.to_i
|
8
8
|
@block_ids = options[:block_ids] || []
|
9
9
|
end
|
10
10
|
|
@@ -15,5 +15,13 @@ module SpreeCmCommissioner::Transit
|
|
15
15
|
block_ids: hash[:block_ids] || [] # empty when no seat selection.
|
16
16
|
)
|
17
17
|
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{
|
21
|
+
variant_id: @variant_id,
|
22
|
+
quantity: @quantity,
|
23
|
+
block_ids: @block_ids
|
24
|
+
}
|
25
|
+
end
|
18
26
|
end
|
19
27
|
end
|
@@ -26,5 +26,39 @@ module SpreeCmCommissioner
|
|
26
26
|
def max_capacity
|
27
27
|
@trips.map(&:max_capacity).compact.min
|
28
28
|
end
|
29
|
+
|
30
|
+
def total_price
|
31
|
+
@trips.map(&:price).compact.sum
|
32
|
+
end
|
33
|
+
|
34
|
+
def total_duration
|
35
|
+
@trips.map(&:duration).compact.sum
|
36
|
+
end
|
37
|
+
|
38
|
+
def total_duration_in_hms
|
39
|
+
total_seconds = total_duration || 0
|
40
|
+
return { hours: 0, minutes: 0, seconds: 0 } if total_seconds.nil? || total_seconds <= 0
|
41
|
+
|
42
|
+
hours = total_seconds / 3600
|
43
|
+
minutes = (total_seconds % 3600) / 60
|
44
|
+
seconds = total_seconds % 60
|
45
|
+
{ hours: hours, minutes: minutes, seconds: seconds }
|
46
|
+
end
|
47
|
+
|
48
|
+
def departure_time
|
49
|
+
@trips.first.departure_time
|
50
|
+
end
|
51
|
+
|
52
|
+
def arrival_time
|
53
|
+
@trips.last.arrival_time
|
54
|
+
end
|
55
|
+
|
56
|
+
def vendors
|
57
|
+
@trips.map(&:vendor).uniq
|
58
|
+
end
|
59
|
+
|
60
|
+
def vehicle_types
|
61
|
+
@trips.map(&:vehicle).map(&:vehicle_type).uniq
|
62
|
+
end
|
29
63
|
end
|
30
64
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module SpreeCmCommissioner
|
2
2
|
class TripResult
|
3
|
-
attr_accessor :id, :origin_place, :destination_place, :allow_seat_selection,
|
3
|
+
attr_accessor :id, :origin_place, :destination_place, :allow_seat_selection,
|
4
|
+
:departure_time, :duration, :route_type,
|
4
5
|
:vehicle_id, :vehicle, :vendor_id, :vendor,
|
5
6
|
:quantity_available, :max_capacity, :boarding, :drop_off,
|
6
7
|
:product_id, :amenities, :price, :compare_at_amount, :currency
|
@@ -29,5 +30,11 @@ module SpreeCmCommissioner
|
|
29
30
|
seconds = duration % 60
|
30
31
|
{ hours: hours, minutes: minutes, seconds: seconds }
|
31
32
|
end
|
33
|
+
|
34
|
+
def arrival_time
|
35
|
+
return nil if departure_time.nil? || duration.nil?
|
36
|
+
|
37
|
+
departure_time + duration.seconds
|
38
|
+
end
|
32
39
|
end
|
33
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_cm_commissioner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.3.pre.
|
4
|
+
version: 2.0.3.pre.pre6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- You
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-08-
|
11
|
+
date: 2025-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree
|
@@ -941,6 +941,7 @@ files:
|
|
941
941
|
- app/controllers/spree/api/v2/storefront/reset_passwords_controller.rb
|
942
942
|
- app/controllers/spree/api/v2/storefront/s3_signed_urls_controller.rb
|
943
943
|
- app/controllers/spree/api/v2/storefront/self_check_in_controller.rb
|
944
|
+
- app/controllers/spree/api/v2/storefront/trip_places_controller.rb
|
944
945
|
- app/controllers/spree/api/v2/storefront/trip_search_controller.rb
|
945
946
|
- app/controllers/spree/api/v2/storefront/user_account_linkages_controller.rb
|
946
947
|
- app/controllers/spree/api/v2/storefront/user_contacts_controller.rb
|
@@ -1541,6 +1542,7 @@ files:
|
|
1541
1542
|
- app/overrides/spree/admin/products/_form/allow_self_check_in.html.erb.deface
|
1542
1543
|
- app/overrides/spree/admin/products/_form/available_on.html.erb.deface
|
1543
1544
|
- app/overrides/spree/admin/products/_form/discontinue_on.html.erb.deface
|
1545
|
+
- app/overrides/spree/admin/products/_form/industry_taxons.html.erb.deface
|
1544
1546
|
- app/overrides/spree/admin/products/_form/need_confirmation_checkbox.html.erb.deface
|
1545
1547
|
- app/overrides/spree/admin/products/_form/option_types.html.erb.deface
|
1546
1548
|
- app/overrides/spree/admin/products/_form/product_types.html.erb.deface
|
@@ -1549,6 +1551,7 @@ files:
|
|
1549
1551
|
- app/overrides/spree/admin/products/_form/required_self_check_in_location.html.erb.deface
|
1550
1552
|
- app/overrides/spree/admin/products/_form/reveal_description_to_user.html.erb.deface
|
1551
1553
|
- app/overrides/spree/admin/products/_form/subscribable_checkbox.html.erb.deface
|
1554
|
+
- app/overrides/spree/admin/products/_form/taxons.html.erb.deface
|
1552
1555
|
- app/overrides/spree/admin/products/_form/use_video_as_default.html.erb.deface
|
1553
1556
|
- app/overrides/spree/admin/products/edit/clear_cache_button.html.erb.deface
|
1554
1557
|
- app/overrides/spree/admin/products/index/product_vendor_link.html.erb.deface
|
@@ -1705,6 +1708,7 @@ files:
|
|
1705
1708
|
- app/serializers/spree/v2/storefront/stock_location_serializer_decorator.rb
|
1706
1709
|
- app/serializers/spree/v2/storefront/store_promotion_serializer.rb
|
1707
1710
|
- app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb
|
1711
|
+
- app/serializers/spree/v2/storefront/trip_place_serializer.rb
|
1708
1712
|
- app/serializers/spree/v2/storefront/trip_query_result_serializer.rb
|
1709
1713
|
- app/serializers/spree/v2/storefront/trip_result_serializer.rb
|
1710
1714
|
- app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb
|
@@ -2686,6 +2690,8 @@ files:
|
|
2686
2690
|
- db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb
|
2687
2691
|
- db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb
|
2688
2692
|
- db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb
|
2693
|
+
- db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb
|
2694
|
+
- db/migrate/20250814073854_add_call_to_action_to_spree_products.rb
|
2689
2695
|
- docker-compose.yml
|
2690
2696
|
- docs/option_types/attr_types.md
|
2691
2697
|
- docs/private_key.pem
|