spree_cm_commissioner 2.0.3.pre.pre5 → 2.0.3.pre.pre8
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/locations_controller.rb +62 -0
- data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +2 -8
- data/app/controllers/spree/api/v2/platform/places_controller.rb +4 -1
- data/app/controllers/spree/api/v2/storefront/dynamic_fields_controller.rb +42 -0
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +2 -0
- data/app/controllers/spree/api/v2/storefront/trip_places_controller.rb +29 -0
- data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +3 -1
- data/app/controllers/spree/api/v2/storefront/trips_controller.rb +24 -0
- data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +14 -0
- data/app/interactors/spree_cm_commissioner/billing_address_creator.rb +33 -0
- data/app/interactors/spree_cm_commissioner/create_vendor.rb +11 -1
- data/app/interactors/spree_cm_commissioner/google_places_fetcher.rb +1 -0
- data/app/interactors/spree_cm_commissioner/intercity_taxi_order_creator.rb +106 -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/concerns/spree_cm_commissioner/variant_options_concern.rb +1 -0
- data/app/models/spree_cm_commissioner/address_decorator.rb +17 -3
- data/app/models/spree_cm_commissioner/guest.rb +105 -56
- data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +37 -27
- 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/taxon_decorator.rb +7 -0
- data/app/models/spree_cm_commissioner/trip.rb +4 -2
- data/app/models/spree_cm_commissioner/user_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/variant_options.rb +4 -0
- data/app/models/spree_cm_commissioner/vehicle.rb +2 -0
- 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/overrides/spree/admin/shared/sub_menu/_configuration/locations_tab.html.erb.deface +5 -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 → spree_cm_commissioner}/v2/storefront/amenity_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/block_serializer.rb +9 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +1 -3
- data/app/serializers/spree_cm_commissioner/v2/storefront/seat_layout_serializer.rb +12 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/seat_section_serializer.rb +11 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_place_serializer.rb +10 -0
- data/app/serializers/{spree → spree_cm_commissioner}/v2/storefront/trip_query_result_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +17 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_serializer.rb +17 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_stop_serializer.rb +9 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_variant_serializer.rb +12 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vehicle_serializer.rb +16 -0
- data/app/serializers/{spree → spree_cm_commissioner}/v2/storefront/trip_vendor_serializer.rb +4 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/variant_block_serializer.rb +9 -0
- data/app/views/shared/_map.html.erb +5 -4
- data/app/views/spree/admin/locations/_form.html.erb +133 -0
- data/app/views/spree/admin/locations/edit.html.erb +11 -0
- data/app/views/spree/admin/locations/index.html.erb +67 -0
- data/app/views/spree/admin/locations/new.html.erb +11 -0
- data/config/locales/en.yml +2 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb +8 -0
- data/db/migrate/20250812121745_add_data_fill_stage_phase_to_cm_guests.rb +5 -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 +31 -7
- data/app/serializers/spree/v2/storefront/trip_result_serializer.rb +0 -16
- data/app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb +0 -11
@@ -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
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module
|
1
|
+
module SpreeCmCommissioner
|
2
2
|
module V2
|
3
3
|
module Storefront
|
4
4
|
class AmenitySerializer < BaseSerializer
|
5
5
|
set_type :amenity
|
6
6
|
attributes :name, :presentation
|
7
7
|
attribute :display_icon do |option_value|
|
8
|
-
ActionController::Base.helpers.image_url(option_value.display_icon)
|
8
|
+
::ActionController::Base.helpers.image_url(option_value.display_icon)
|
9
9
|
rescue StandardError
|
10
10
|
nil
|
11
11
|
end
|
@@ -7,7 +7,7 @@ module SpreeCmCommissioner
|
|
7
7
|
attributes :first_name, :last_name, :dob, :gender, :kyc_fields, :other_occupation, :created_at, :updated_at,
|
8
8
|
:qr_data, :social_contact_platform, :social_contact, :available_social_contact_platforms,
|
9
9
|
:age, :emergency_contact, :other_organization, :expectation, :upload_later, :address, :formatted_bib_number, :phone_number,
|
10
|
-
:token, :country_code, :contact
|
10
|
+
:token, :country_code, :contact, :data_fill_stage_phase
|
11
11
|
|
12
12
|
# temporary, once app release after cm-app v1.9.1, we no longer need this.
|
13
13
|
attribute :seat_number do |object|
|
@@ -22,8 +22,6 @@ module SpreeCmCommissioner
|
|
22
22
|
belongs_to :nationality, serializer: Spree::V2::Storefront::TaxonSerializer
|
23
23
|
belongs_to :line_item, serializer: Spree::V2::Storefront::LineItemSerializer
|
24
24
|
|
25
|
-
has_many :guest_dynamic_fields, serializer: SpreeCmCommissioner::V2::Storefront::GuestDynamicFieldSerializer
|
26
|
-
|
27
25
|
has_one :id_card, serializer: Spree::V2::Storefront::IdCardSerializer
|
28
26
|
has_one :check_in
|
29
27
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class SeatLayoutSerializer < BaseSerializer
|
5
|
+
attributes :name, :status, :width, :height
|
6
|
+
|
7
|
+
has_many :seat_sections, serializer: SpreeCmCommissioner::V2::Storefront::SeatSectionSerializer
|
8
|
+
has_many :top_level_blocks, serializer: SpreeCmCommissioner::V2::Storefront::BlockSerializer
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class SeatSectionSerializer < BaseSerializer
|
5
|
+
attributes :name, :width, :height, :x, :y, :rotation, :shape_path
|
6
|
+
|
7
|
+
has_many :blocks, serializer: SpreeCmCommissioner::V2::Storefront::BlockSerializer
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module SpreeCmCommissioner
|
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
|
data/app/serializers/{spree → spree_cm_commissioner}/v2/storefront/trip_query_result_serializer.rb
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SpreeCmCommissioner
|
2
2
|
module V2
|
3
3
|
module Storefront
|
4
4
|
class TripQueryResultSerializer < BaseSerializer
|
@@ -7,7 +7,7 @@ module Spree
|
|
7
7
|
attributes :quantity_available, :max_capacity
|
8
8
|
|
9
9
|
attribute :direct, &:direct?
|
10
|
-
has_many :trips, serializer:
|
10
|
+
has_many :trips, serializer: ::SpreeCmCommissioner::V2::Storefront::TripResultSerializer
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class TripResultSerializer < BaseSerializer
|
5
|
+
set_type :trip_result
|
6
|
+
|
7
|
+
attributes :origin_place, :destination_place, :boarding, :drop_off, :price, :compare_at_amount, :currency, :quantity_available, :max_capacity,
|
8
|
+
:allow_seat_selection, :departure_time, :route_type
|
9
|
+
attribute :duration_in_hms, &:duration_in_hms
|
10
|
+
attribute :arrival_time, &:arrival_time
|
11
|
+
belongs_to :vendor, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVendorSerializer
|
12
|
+
belongs_to :vehicle, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVehicleSerializer
|
13
|
+
has_many :amenities, serializer: ::SpreeCmCommissioner::V2::Storefront::AmenitySerializer
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class TripSerializer < BaseSerializer
|
5
|
+
attributes :departure_time, :arrival_time, :duration_in_hms, :origin_place, :destination_place, :route_type
|
6
|
+
|
7
|
+
has_one :vehicle, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVehicleSerializer
|
8
|
+
|
9
|
+
has_many :boarding_trip_stops, serializer: ::SpreeCmCommissioner::V2::Storefront::TripStopSerializer
|
10
|
+
has_many :drop_off_trip_stops, serializer: ::SpreeCmCommissioner::V2::Storefront::TripStopSerializer
|
11
|
+
has_many :variants, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVariantSerializer
|
12
|
+
|
13
|
+
belongs_to :vendor, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVendorSerializer
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class TripVariantSerializer < BaseSerializer
|
5
|
+
attributes :price, :display_price, :compare_at_price, :display_compare_at_price,
|
6
|
+
:number_of_guests, :seat_type
|
7
|
+
|
8
|
+
has_many :variant_blocks, serializer: ::SpreeCmCommissioner::V2::Storefront::VariantBlockSerializer
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module V2
|
3
|
+
module Storefront
|
4
|
+
class TripVehicleSerializer < BaseSerializer
|
5
|
+
set_type :vehicle
|
6
|
+
|
7
|
+
attributes :id, :code, :vehicle_type
|
8
|
+
|
9
|
+
has_many :vehicle_photos, serializer: ::SpreeCmCommissioner::V2::Storefront::AssetSerializer
|
10
|
+
has_many :amenities, serializer: ::SpreeCmCommissioner::V2::Storefront::AmenitySerializer
|
11
|
+
|
12
|
+
has_one :seat_layout, serializer: SpreeCmCommissioner::V2::Storefront::SeatLayoutSerializer
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/app/serializers/{spree → spree_cm_commissioner}/v2/storefront/trip_vendor_serializer.rb
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SpreeCmCommissioner
|
2
2
|
module V2
|
3
3
|
module Storefront
|
4
4
|
class TripVendorSerializer < BaseSerializer
|
@@ -7,6 +7,9 @@ module Spree
|
|
7
7
|
attributes :name, :star_rating
|
8
8
|
|
9
9
|
has_one :logo, serializer: ::SpreeCmCommissioner::V2::Storefront::AssetSerializer
|
10
|
+
|
11
|
+
has_many :vendor_kind_option_types, serializer: ::Spree::V2::Storefront::OptionTypeSerializer
|
12
|
+
has_many :vendor_kind_option_values, serializer: ::Spree::V2::Storefront::OptionValueSerializer
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
@@ -1,14 +1,15 @@
|
|
1
|
-
|
1
|
+
<% map_height ||= 200 %>
|
2
2
|
|
3
|
+
<div class="border rounded mb-4">
|
4
|
+
<div id="map" class="rounded" style="height: <%= map_height %>px;"></div>
|
5
|
+
</div>
|
3
6
|
<% @default_latlon = ENV.fetch("DEFAULT_LATLON") %>
|
4
7
|
<% @default_lat = @default_latlon.split(",")[0] %>
|
5
8
|
<% @default_lon = @default_latlon.split(",")[1] %>
|
6
|
-
|
7
9
|
<%= content_tag :div, class: 'map-selector', data: {
|
8
|
-
lat: lat || @default_lat,
|
10
|
+
lat: lat || @default_lat,
|
9
11
|
lon: lon || @default_lon
|
10
12
|
} do %><% end %>
|
11
|
-
|
12
13
|
<%# MAP scripts %>
|
13
14
|
<% @map_key = ENV.fetch("GOOGLE_MAP_KEY") %>
|
14
15
|
<% @map_src = "https://maps.googleapis.com/maps/api/js?key=#{@map_key}&callback=initMap&v=weekly" %>
|
@@ -0,0 +1,133 @@
|
|
1
|
+
<div class="row g-4" data-controller="place">
|
2
|
+
<div class="col-md-6">
|
3
|
+
<div class="form-group">
|
4
|
+
<%= f.field_container :base_64_content do %>
|
5
|
+
<%= f.label :base_64_content, Spree.t(:place) %>
|
6
|
+
<% if can? :modify, SpreeCmCommissioner::Place %>
|
7
|
+
<% selected_name = f.object.name.presence || f.object.formatted_address || "Search Place" %>
|
8
|
+
<%= f.select :base_64_content, [], { include_hidden: true },
|
9
|
+
class: 'select2autocomplete',
|
10
|
+
data: {
|
11
|
+
autocomplete_url_value: 'places_api_v2',
|
12
|
+
autocomplete_return_attr_value: :name,
|
13
|
+
autocomplete_custom_return_id_value: :base_64_content
|
14
|
+
} do %>
|
15
|
+
<option selected><%= selected_name %></option>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<%= render 'shared/map', lat: f.object.lat, lon: f.object.lon, map_height: 270 %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="col-md-6">
|
25
|
+
<div class="card shadow-sm border-0">
|
26
|
+
<div class="card-header bg-light fw-semibold">
|
27
|
+
<i class="bi bi-geo-alt-fill me-2"></i><%= Spree.t(:location_details) %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="card-body">
|
31
|
+
<div class="mb-3">
|
32
|
+
<%= f.label :name, raw(Spree.t(:name) + required_span_tag) %>
|
33
|
+
<%= f.text_field :name,
|
34
|
+
class: "form-control",
|
35
|
+
placeholder: "Enter your name",
|
36
|
+
required: :required,
|
37
|
+
data: { target: "place.name" } %>
|
38
|
+
<%= error_message_on(f.object, :name) %>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div class="row">
|
42
|
+
<div class="col-md-6 mb-3">
|
43
|
+
<%= f.label :lat, Spree.t(:lat), class: "form-label" %>
|
44
|
+
<%= f.text_field :lat,
|
45
|
+
class: "form-control",
|
46
|
+
placeholder: "e.g., 11.5621",
|
47
|
+
data: { target: "place.lat" } %>
|
48
|
+
<%= error_message_on(f.object, :lat) %>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div class="col-md-6 mb-3">
|
52
|
+
<%= f.label :lon, Spree.t(:lon), class: "form-label" %>
|
53
|
+
<%= f.text_field :lon,
|
54
|
+
class: "form-control",
|
55
|
+
placeholder: "e.g., 104.9143",
|
56
|
+
data: { target: "place.lon" } %>
|
57
|
+
<%= error_message_on(f.object, :lon) %>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<div class="mb-3">
|
62
|
+
<%= f.label :formatted_address, Spree.t(:address), class: "form-label" %>
|
63
|
+
<%= f.text_field :formatted_address,
|
64
|
+
class: "form-control",
|
65
|
+
placeholder: "Enter your address",
|
66
|
+
data: { target: "place.address" } %>
|
67
|
+
<%= error_message_on(f.object, :formatted_address) %>
|
68
|
+
</div>
|
69
|
+
|
70
|
+
<%= f.hidden_field :reference, value: f.object.reference, data: { target: "place.reference" } %>
|
71
|
+
<%= f.hidden_field :types, value: f.object.types, data: { target: "place.types" } %>
|
72
|
+
<%= f.hidden_field :vicinity, value: f.object.vicinity, data: { target: "place.vicinity" } %>
|
73
|
+
<%= f.hidden_field :icon, value: f.object.icon, data: { target: "place.icon" } %>
|
74
|
+
<%= f.hidden_field :rating, value: f.object.rating, data: { target: "place.rating" } %>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
|
80
|
+
<script>
|
81
|
+
let map, marker;
|
82
|
+
|
83
|
+
function initMap() {
|
84
|
+
const mapElement = document.getElementById("map");
|
85
|
+
if (!mapElement) return;
|
86
|
+
|
87
|
+
const container = document.querySelector(".map-selector");
|
88
|
+
const defaultLat = parseFloat(container?.dataset.lat) || 11.5621;
|
89
|
+
const defaultLon = parseFloat(container?.dataset.lon) || 104.8885;
|
90
|
+
|
91
|
+
const center = { lat: defaultLat, lng: defaultLon };
|
92
|
+
|
93
|
+
map = new google.maps.Map(mapElement, { center, zoom: 18 });
|
94
|
+
marker = new google.maps.Marker({ position: center, map });
|
95
|
+
}
|
96
|
+
|
97
|
+
document.addEventListener("spree:load", () => {
|
98
|
+
const select = document.querySelector(".select2autocomplete");
|
99
|
+
if (!select) return;
|
100
|
+
|
101
|
+
$(select).on("select2:select", (e) => {
|
102
|
+
const base64Content = e.params.data.id;
|
103
|
+
if (!base64Content) return;
|
104
|
+
|
105
|
+
try {
|
106
|
+
const placeData = JSON.parse(atob(base64Content));
|
107
|
+
|
108
|
+
const setValue = (selector, value) => {
|
109
|
+
const el = document.querySelector(selector);
|
110
|
+
if (el) el.value = value ?? "";
|
111
|
+
};
|
112
|
+
|
113
|
+
setValue('[data-target="place.name"]', placeData.name);
|
114
|
+
setValue('[data-target="place.lat"]', placeData.lat);
|
115
|
+
setValue('[data-target="place.lon"]', placeData.lon);
|
116
|
+
setValue('[data-target="place.address"]', placeData.formatted_address);
|
117
|
+
setValue('[data-target="place.reference"]', placeData.reference);
|
118
|
+
setValue('[data-target="place.types"]', placeData.types?.[0] || "");
|
119
|
+
setValue('[data-target="place.vicinity"]', placeData.vicinity);
|
120
|
+
setValue('[data-target="place.icon"]', placeData.icon);
|
121
|
+
setValue('[data-target="place.rating"]', placeData.rating);
|
122
|
+
|
123
|
+
if (placeData.lat && placeData.lon && map && marker) {
|
124
|
+
const newLatLng = new google.maps.LatLng(+placeData.lat, +placeData.lon);
|
125
|
+
map.setCenter(newLatLng);
|
126
|
+
marker.setPosition(newLatLng);
|
127
|
+
}
|
128
|
+
} catch (err) {
|
129
|
+
console.error("Error decoding or parsing place data:", err);
|
130
|
+
}
|
131
|
+
});
|
132
|
+
});
|
133
|
+
</script>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= page_header_back_button spree.admin_locations_path %>
|
3
|
+
<%= @object.name %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= form_with model: @object, url: { action: 'update' }, html: { multipart: true } do |f| %>
|
7
|
+
<fieldset>
|
8
|
+
<%= render partial: 'form', locals: { f: f } %>
|
9
|
+
<%= render partial: 'spree/admin/shared/edit_resource_links' %>
|
10
|
+
</fieldset>
|
11
|
+
<% end %>
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= Spree.t(:locations) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<% if can?(:create, SpreeCmCommissioner::Place) %>
|
7
|
+
<%= button_link_to Spree.t(:new_location),
|
8
|
+
new_object_url,
|
9
|
+
class: "btn-success",
|
10
|
+
icon: "add.svg",
|
11
|
+
id: "admin_new_location" %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% content_for :table_filter do %>
|
16
|
+
<div data-hook="admin_locations_index_search">
|
17
|
+
<%= search_form_for [:admin, @search], url: spree.admin_locations_path do |f| %>
|
18
|
+
<div class="row">
|
19
|
+
<div class="col-md-6">
|
20
|
+
<div class="form-group">
|
21
|
+
<%= label_tag :q_name_cont, Spree.t(:name) %>
|
22
|
+
<%= f.text_field :name_cont, tabindex: 1, class: "form-control js-quick-search-target" %>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<div data-hook="admin_locations_index_search_buttons" class="form-actions">
|
27
|
+
<%= button Spree.t(:filter_results), 'search' %>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<div class="table-responsive border rounded bg-white mb-3" >
|
34
|
+
<table class="table" id="listing_locations" data-hook>
|
35
|
+
<thead class="text-muted">
|
36
|
+
<tr data-hook="location_header">
|
37
|
+
<th><%= sort_link @search, :name, Spree.t(:name), {}, { title: 'name' } %></th>
|
38
|
+
<th><%= Spree.t(:address) %></th>
|
39
|
+
<th><%= Spree.t(:latitude) %></th>
|
40
|
+
<th><%= Spree.t(:longitude) %></th>
|
41
|
+
<th><%= sort_link @search, :created_at, Spree.t(:created_at), {}, { title: 'created_at' } %></th>
|
42
|
+
<th><%= sort_link @search, :updated_at, Spree.t(:updated_at), {}, { title: 'updated_at' } %></th>
|
43
|
+
<th scope="col" data-hook="admin_locations_actions" class="actions"></th>
|
44
|
+
</tr>
|
45
|
+
</thead>
|
46
|
+
<tbody>
|
47
|
+
<% @locations.each do |location| %>
|
48
|
+
<tr id="<%= spree_dom_id(location) %>" data-hook="location_row">
|
49
|
+
<td><%= link_to location.name, spree.edit_admin_location_path(location) %></td>
|
50
|
+
<td><%= location.formatted_address.presence || location.vicinity %></td>
|
51
|
+
<td><%= location.lat %></td>
|
52
|
+
<td><%= location.lon %></td>
|
53
|
+
<td><%= location.created_at %></td>
|
54
|
+
<td><%= location.updated_at %></td>
|
55
|
+
<td data-hook="admin_locations_index_row_actions">
|
56
|
+
<span class="d-flex justify-content-end ">
|
57
|
+
<%= link_to_edit(location, url: edit_admin_location_url(location), no_text: true, class: 'edit') if can?(:edit, location) %>
|
58
|
+
<%= link_to_delete(location, url: admin_location_url(location), no_text: true) if can?(:delete, location) %>
|
59
|
+
</span>
|
60
|
+
</td>
|
61
|
+
</tr>
|
62
|
+
<% end %>
|
63
|
+
</tbody>
|
64
|
+
</table>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<%= paginate @locations, theme: 'admin-twitter-bootstrap-4' %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= page_header_back_button spree.admin_locations_path %>
|
3
|
+
<%= Spree.t(:new_location) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= form_with model: @object, url: { action: 'create' }, html: { multipart: true } do |f| %>
|
7
|
+
<fieldset>
|
8
|
+
<%= render partial: 'form', locals: { f: f } %>
|
9
|
+
<%= render partial: 'spree/admin/shared/new_resource_links' %>
|
10
|
+
</fieldset>
|
11
|
+
<% end %>
|
data/config/locales/en.yml
CHANGED
data/config/routes.rb
CHANGED
@@ -284,6 +284,8 @@ Spree::Core::Engine.add_routes do
|
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|
287
|
+
resources :locations
|
288
|
+
|
287
289
|
resources :tenants do
|
288
290
|
resources :vendors, controller: :tenant_vendors
|
289
291
|
end
|
@@ -555,6 +557,7 @@ Spree::Core::Engine.add_routes do
|
|
555
557
|
|
556
558
|
resources :trip_places
|
557
559
|
resources :trip_search, only: [:index]
|
560
|
+
resources :trips, only: %i[show]
|
558
561
|
|
559
562
|
namespace :queue_cart do
|
560
563
|
resources :line_items, only: [:create]
|
@@ -644,6 +647,7 @@ Spree::Core::Engine.add_routes do
|
|
644
647
|
resources :id_cards
|
645
648
|
end
|
646
649
|
resources :dynamic_field_options
|
650
|
+
resources :dynamic_fields
|
647
651
|
resources :user_guests do
|
648
652
|
resources :id_cards
|
649
653
|
end
|
@@ -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
|