spree_cm_commissioner 2.3.2.pre.pre2 → 2.3.2.pre.pre5
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/storefront/intercity_taxi/draft_orders_controller.rb +36 -36
- 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 +37 -37
- data/app/controllers/spree/api/v2/tenant/trip_places_controller.rb +5 -11
- data/app/controllers/spree/api/v2/tenant/trip_search_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/trips_controller.rb +8 -8
- 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/mailers/spree/order_mailer_decorator.rb +8 -6
- 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/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/order_decorator.rb +1 -1
- 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/tenant.rb +4 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +3 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
- data/app/request_schemas/spree_cm_commissioner/intercity_taxi_draft_order_update_schema.rb +22 -3
- 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/services/spree_cm_commissioner/intercity_taxi_order/create.rb +11 -22
- data/app/services/spree_cm_commissioner/intercity_taxi_order/update.rb +32 -11
- 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/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/routes.rb +4 -10
- 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 +2 -1
- 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/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +2 -0
- metadata +42 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41cc123a59db2cddcf70bc8769d9a99a1d5fe1dbc81121d2002e8683032cb4a2
|
|
4
|
+
data.tar.gz: 49729cab30781d0bfe470c7b4d3d3b5912e888104263122cb62ef37f46cdf813
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d981677facf743342469f9749e35550db74983bbc458c86d623c93fd7e3309e635ca45ee1ac65893e4b7186ee6f933b7785a6475631a8b3f7fde280518340457
|
|
7
|
+
data.tar.gz: ee81f47e4c74fdcb25ee291371bb81740127709910479d551adc9b2cc26c0d73036380bd7c2c5cd8ece6154605a062e4646d747179a26eac3ed00614d4f51bfd
|
data/Gemfile.lock
CHANGED
|
@@ -8,8 +8,9 @@ module Spree
|
|
|
8
8
|
include SpreeCmCommissioner::OrderConcern
|
|
9
9
|
|
|
10
10
|
before_action :ensure_order, only: :update
|
|
11
|
+
|
|
11
12
|
def create
|
|
12
|
-
|
|
13
|
+
result = SpreeCmCommissioner::IntercityTaxiOrder::Create.call(
|
|
13
14
|
trip_id: params[:trip_id],
|
|
14
15
|
from_date: params[:from_date],
|
|
15
16
|
to_date: params[:to_date],
|
|
@@ -17,51 +18,50 @@ module Spree
|
|
|
17
18
|
quantity: params[:quantity]
|
|
18
19
|
)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
if result.success?
|
|
22
|
+
render_serialized_payload { serialize_resource(result.value) }
|
|
23
|
+
else
|
|
24
|
+
render_error_payload(result.error)
|
|
25
|
+
end
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def update
|
|
26
|
-
|
|
29
|
+
result = SpreeCmCommissioner::IntercityTaxiOrder::Update.call(
|
|
27
30
|
order: spree_current_order,
|
|
28
|
-
|
|
31
|
+
remark: params[:remark],
|
|
32
|
+
pickup_map_place_attributes: params.require(:pickup_map_place_attributes).permit(
|
|
33
|
+
:place_name,
|
|
34
|
+
:lat,
|
|
35
|
+
:lng,
|
|
36
|
+
:oob_confirmed
|
|
37
|
+
),
|
|
38
|
+
dropoff_map_place_attributes: params.require(:dropoff_map_place_attributes).permit(
|
|
39
|
+
:place_name,
|
|
40
|
+
:lat,
|
|
41
|
+
:lng,
|
|
42
|
+
:oob_confirmed
|
|
43
|
+
),
|
|
44
|
+
distance_attributes: params.require(:distance_attributes).permit(
|
|
45
|
+
:distance_km,
|
|
46
|
+
:ordered_points,
|
|
47
|
+
:estimated_time_minutes,
|
|
48
|
+
:base_km,
|
|
49
|
+
:detour_pickup_km,
|
|
50
|
+
:detour_dropoff_km,
|
|
51
|
+
:extra_pickup_km,
|
|
52
|
+
:extra_dropoff_km
|
|
53
|
+
)
|
|
29
54
|
)
|
|
30
55
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
56
|
+
if result.success?
|
|
57
|
+
render_serialized_payload { serialize_resource(result.value) }
|
|
58
|
+
else
|
|
59
|
+
render_error_payload(result.error)
|
|
60
|
+
end
|
|
34
61
|
end
|
|
35
62
|
|
|
36
63
|
private
|
|
37
64
|
|
|
38
|
-
def intercity_taxi_update_order_params
|
|
39
|
-
params.require(:order).permit(
|
|
40
|
-
line_items_attributes: %i[
|
|
41
|
-
id
|
|
42
|
-
pickup_place_name
|
|
43
|
-
drop_off_place_name
|
|
44
|
-
from_date
|
|
45
|
-
pickup_lat
|
|
46
|
-
pickup_lng
|
|
47
|
-
pickup_oob_confirmed
|
|
48
|
-
drop_off_lat
|
|
49
|
-
drop_off_lng
|
|
50
|
-
drop_off_oob_confirmed
|
|
51
|
-
distance_km
|
|
52
|
-
ordered_points
|
|
53
|
-
base_km
|
|
54
|
-
detour_pickup_km
|
|
55
|
-
detour_dropoff_km
|
|
56
|
-
extra_pickup_km
|
|
57
|
-
extra_dropoff_km
|
|
58
|
-
estimated_time_minutes
|
|
59
|
-
remark
|
|
60
|
-
passenger_count
|
|
61
|
-
]
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
65
|
def required_schema
|
|
66
66
|
if action_name == 'create'
|
|
67
67
|
SpreeCmCommissioner::IntercityTaxiDraftOrderSchema
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# API endpoint for retrieving popular routes ordered by order metrics.
|
|
2
|
+
#
|
|
3
|
+
# GET /api/v2/storefront/popular_route_places
|
|
4
|
+
#
|
|
5
|
+
# Returns routes sorted by popularity (fulfilled_order_count, then order_count) with their
|
|
6
|
+
# origin and destination places. Supports optional includes for vendors and nearby_places.
|
|
7
|
+
#
|
|
8
|
+
# Response: Collection of routes serialized with RouteSerializer
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# GET /api/v2/storefront/popular_route_places
|
|
12
|
+
module Spree
|
|
13
|
+
module Api
|
|
14
|
+
module V2
|
|
15
|
+
module Storefront
|
|
16
|
+
class PopularRoutePlacesController < ::Spree::Api::V2::ResourceController
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# override
|
|
20
|
+
def collection
|
|
21
|
+
@collection ||= collection_finder.new.execute
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# override
|
|
25
|
+
def default_resource_includes
|
|
26
|
+
%w[origin_place destination_place]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# override
|
|
30
|
+
def collection_finder
|
|
31
|
+
SpreeCmCommissioner::Routes::FindPopular
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# override
|
|
35
|
+
def collection_serializer
|
|
36
|
+
resource_serializer
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# override
|
|
40
|
+
def resource_serializer
|
|
41
|
+
SpreeCmCommissioner::V2::Storefront::RouteSerializer
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# override
|
|
45
|
+
def serializer_params
|
|
46
|
+
super.merge(
|
|
47
|
+
include_vendors: include_vendors?,
|
|
48
|
+
include_nearby_places: include_nearby_places?
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def include_vendors?
|
|
53
|
+
resource_includes.include?(:vendors) || false
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def include_nearby_places?
|
|
57
|
+
resource_includes.include?(:nearby_places) || false
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# API endpoint for searching places that are used in routes by keyword.
|
|
2
|
+
#
|
|
3
|
+
# GET /api/v2/storefront/route_places
|
|
4
|
+
#
|
|
5
|
+
# Searches for places (origins or destinations) that are used in existing routes,
|
|
6
|
+
# filtered by keyword search on place names.
|
|
7
|
+
#
|
|
8
|
+
# Query Parameters:
|
|
9
|
+
# - query: [String] Required. Keyword to search in place names (case-insensitive)
|
|
10
|
+
# - place_type: [String] Required. Type of route place: 'origin' or 'destination'
|
|
11
|
+
# - include: Optional comma-separated list (e.g., 'vendors,nearby_places')
|
|
12
|
+
#
|
|
13
|
+
# Response: Collection of places serialized with PlaceSerializer
|
|
14
|
+
#
|
|
15
|
+
# Behavior:
|
|
16
|
+
# - Returns empty collection if query is blank or place_type is invalid
|
|
17
|
+
# - UI should only call this endpoint when user has input a search term
|
|
18
|
+
# - For initial/empty state, use GET /api/v2/storefront/popular_route_places instead
|
|
19
|
+
#
|
|
20
|
+
# @example
|
|
21
|
+
# GET /api/v2/storefront/route_places?query=Phnom&place_type=origin
|
|
22
|
+
module Spree
|
|
23
|
+
module Api
|
|
24
|
+
module V2
|
|
25
|
+
module Storefront
|
|
26
|
+
class RoutePlacesController < ::Spree::Api::V2::ResourceController
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# override
|
|
30
|
+
def collection
|
|
31
|
+
@collection ||= collection_finder.new(keyword: params[:query], place_type: params[:place_type]).execute
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# override
|
|
35
|
+
def collection_finder
|
|
36
|
+
SpreeCmCommissioner::Places::FindWithRoute
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# override
|
|
40
|
+
def collection_serializer
|
|
41
|
+
Spree::V2::Storefront::PlaceSerializer
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# override
|
|
45
|
+
def required_schema
|
|
46
|
+
SpreeCmCommissioner::RoutePlacesRequestSchema
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# override
|
|
50
|
+
def serializer_params
|
|
51
|
+
super.merge(
|
|
52
|
+
include_vendors: include_vendors?,
|
|
53
|
+
include_nearby_places: include_nearby_places?
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def include_vendors?
|
|
58
|
+
resource_includes.include?(:vendors) || false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def include_nearby_places?
|
|
62
|
+
resource_includes.include?(:nearby_places) || false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -8,8 +8,9 @@ module Spree
|
|
|
8
8
|
include SpreeCmCommissioner::OrderConcern
|
|
9
9
|
|
|
10
10
|
before_action :ensure_order, only: :update
|
|
11
|
+
|
|
11
12
|
def create
|
|
12
|
-
|
|
13
|
+
result = SpreeCmCommissioner::IntercityTaxiOrder::Create.call(
|
|
13
14
|
trip_id: params[:trip_id],
|
|
14
15
|
from_date: params[:from_date],
|
|
15
16
|
to_date: params[:to_date],
|
|
@@ -17,51 +18,50 @@ module Spree
|
|
|
17
18
|
user: spree_current_user
|
|
18
19
|
)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
if result.success?
|
|
22
|
+
render_serialized_payload { serialize_resource(result.value) }
|
|
23
|
+
else
|
|
24
|
+
render_error_payload(result.error)
|
|
25
|
+
end
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def update
|
|
26
|
-
|
|
29
|
+
result = SpreeCmCommissioner::IntercityTaxiOrder::Update.call(
|
|
27
30
|
order: spree_current_order,
|
|
28
|
-
|
|
31
|
+
remark: params[:remark],
|
|
32
|
+
pickup_map_place_attributes: params.require(:pickup_map_place_attributes).permit(
|
|
33
|
+
:place_name,
|
|
34
|
+
:lat,
|
|
35
|
+
:lng,
|
|
36
|
+
:oob_confirmed
|
|
37
|
+
),
|
|
38
|
+
dropoff_map_place_attributes: params.require(:dropoff_map_place_attributes).permit(
|
|
39
|
+
:place_name,
|
|
40
|
+
:lat,
|
|
41
|
+
:lng,
|
|
42
|
+
:oob_confirmed
|
|
43
|
+
),
|
|
44
|
+
distance_attributes: params.require(:distance_attributes).permit(
|
|
45
|
+
:distance_km,
|
|
46
|
+
:ordered_points,
|
|
47
|
+
:estimated_time_minutes,
|
|
48
|
+
:base_km,
|
|
49
|
+
:detour_pickup_km,
|
|
50
|
+
:detour_dropoff_km,
|
|
51
|
+
:extra_pickup_km,
|
|
52
|
+
:extra_dropoff_km
|
|
53
|
+
)
|
|
29
54
|
)
|
|
30
55
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
56
|
+
if result.success?
|
|
57
|
+
render_serialized_payload { serialize_resource(result.value) }
|
|
58
|
+
else
|
|
59
|
+
render_error_payload(result.error)
|
|
60
|
+
end
|
|
34
61
|
end
|
|
35
62
|
|
|
36
63
|
private
|
|
37
64
|
|
|
38
|
-
def intercity_taxi_update_order_params
|
|
39
|
-
params.require(:order).permit(
|
|
40
|
-
line_items_attributes: %i[
|
|
41
|
-
id
|
|
42
|
-
pickup_place_name
|
|
43
|
-
drop_off_place_name
|
|
44
|
-
from_date
|
|
45
|
-
pickup_lat
|
|
46
|
-
pickup_lng
|
|
47
|
-
pickup_oob_confirmed
|
|
48
|
-
drop_off_lat
|
|
49
|
-
drop_off_lng
|
|
50
|
-
drop_off_oob_confirmed
|
|
51
|
-
distance_km
|
|
52
|
-
ordered_points
|
|
53
|
-
base_km
|
|
54
|
-
detour_pickup_km
|
|
55
|
-
detour_dropoff_km
|
|
56
|
-
extra_pickup_km
|
|
57
|
-
extra_dropoff_km
|
|
58
|
-
estimated_time_minutes
|
|
59
|
-
remark
|
|
60
|
-
passenger_count
|
|
61
|
-
]
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
65
|
def required_schema
|
|
66
66
|
if action_name == 'create'
|
|
67
67
|
SpreeCmCommissioner::IntercityTaxiDraftOrderSchema
|
|
@@ -71,7 +71,7 @@ module Spree
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def resource_serializer
|
|
74
|
-
|
|
74
|
+
Spree::V2::Tenant::IntercityTaxiCartSerializer
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
77
|
end
|
|
@@ -3,18 +3,9 @@ module Spree
|
|
|
3
3
|
module V2
|
|
4
4
|
module Tenant
|
|
5
5
|
class TripPlacesController < BaseController
|
|
6
|
-
def index
|
|
7
|
-
render_serialized_payload do
|
|
8
|
-
serialize_collection(paginated_collection)
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
6
|
private
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
collection.page(params[:page]).per(params[:per_page])
|
|
16
|
-
end
|
|
17
|
-
|
|
8
|
+
# override
|
|
18
9
|
def collection
|
|
19
10
|
@collection ||= begin
|
|
20
11
|
base_scope = scope
|
|
@@ -28,18 +19,21 @@ module Spree
|
|
|
28
19
|
end
|
|
29
20
|
end
|
|
30
21
|
|
|
22
|
+
# override
|
|
31
23
|
def scope
|
|
32
24
|
model_class.joins(:location_vendor_places)
|
|
33
25
|
.where(location_vendor_places: { tenant_id: @tenant.id })
|
|
34
26
|
.distinct
|
|
35
27
|
end
|
|
36
28
|
|
|
29
|
+
# override
|
|
37
30
|
def model_class
|
|
38
31
|
SpreeCmCommissioner::Place
|
|
39
32
|
end
|
|
40
33
|
|
|
34
|
+
# override
|
|
41
35
|
def collection_serializer
|
|
42
|
-
|
|
36
|
+
Spree::V2::Tenant::TripPlaceSerializer
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
end
|
|
@@ -70,7 +70,7 @@ module Spree
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def serialize_collection(collection)
|
|
73
|
-
serialized_data =
|
|
73
|
+
serialized_data = Spree::V2::Tenant::TripQueryResultSerializer.new(
|
|
74
74
|
collection,
|
|
75
75
|
include: default_resource_includes,
|
|
76
76
|
params: serializer_params
|
|
@@ -3,27 +3,27 @@ module Spree
|
|
|
3
3
|
module V2
|
|
4
4
|
module Tenant
|
|
5
5
|
class TripsController < BaseController
|
|
6
|
-
|
|
7
|
-
resource = scope.find(params[:id])
|
|
6
|
+
private
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
# override
|
|
9
|
+
def resource
|
|
10
|
+
scope.find(params[:id])
|
|
12
11
|
end
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
# override
|
|
16
14
|
def scope
|
|
17
15
|
model_class.joins(:vendor)
|
|
18
16
|
.where(spree_vendors: { tenant_id: @tenant.id })
|
|
19
17
|
end
|
|
20
18
|
|
|
19
|
+
# override
|
|
21
20
|
def model_class
|
|
22
21
|
SpreeCmCommissioner::Trip
|
|
23
22
|
end
|
|
24
23
|
|
|
24
|
+
# override
|
|
25
25
|
def resource_serializer
|
|
26
|
-
|
|
26
|
+
Spree::V2::Tenant::TripSerializer
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
# Name: Vaneath Awesome
|
|
20
20
|
# Tel: <code>+85570760548</code>
|
|
21
21
|
# Email: <code>admin_dev@cm.com</code>
|
|
22
|
+
# Delivery Address: #123, St. 456, Phnom Penh
|
|
22
23
|
|
|
23
24
|
module SpreeCmCommissioner
|
|
24
25
|
class OrderTelegramMessageFactory < TelegramMessageFactory
|
|
@@ -79,6 +80,7 @@ module SpreeCmCommissioner
|
|
|
79
80
|
text << "Name: #{order.name}"
|
|
80
81
|
text << "Tel: #{inline_code(order.intel_phone_number || order.phone_number)}"
|
|
81
82
|
text << "Email: #{inline_code(order.email)}" if order.email.present?
|
|
83
|
+
text << "Delivery Address: #{formatted_shipping_address.presence || 'N/A'}" if order.delivery_required?
|
|
82
84
|
|
|
83
85
|
if show_details_link && order.guests.any?
|
|
84
86
|
text << ''
|
|
@@ -89,6 +91,16 @@ module SpreeCmCommissioner
|
|
|
89
91
|
text.compact.join("\n")
|
|
90
92
|
end
|
|
91
93
|
|
|
94
|
+
def formatted_shipping_address
|
|
95
|
+
return 'N/A' if order.shipping_address.blank?
|
|
96
|
+
|
|
97
|
+
@formatted_shipping_address ||= [
|
|
98
|
+
order.shipping_address.address1,
|
|
99
|
+
order.shipping_address.address2,
|
|
100
|
+
order.shipping_address.state&.name
|
|
101
|
+
].compact.compact_blank.join(', ')
|
|
102
|
+
end
|
|
103
|
+
|
|
92
104
|
# Result:
|
|
93
105
|
# | No. A24 | No. A24 |
|
|
94
106
|
# | No. A24 | No. A24 |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Finds places that are used in routes (as origin or destination) by keyword search.
|
|
2
|
+
#
|
|
3
|
+
# @param keyword [String] Search term to match against place names (case-insensitive)
|
|
4
|
+
# @param place_type [String] Type of route place: 'origin' or 'destination'
|
|
5
|
+
#
|
|
6
|
+
# @return [ActiveRecord::Relation<SpreeCmCommissioner::Place>] Places matching the keyword
|
|
7
|
+
# that are used as origins or destinations in existing routes. Returns empty relation if
|
|
8
|
+
# keyword is blank or place_type is invalid.
|
|
9
|
+
#
|
|
10
|
+
# @note For default/empty state display, use SpreeCmCommissioner::Routes::FindPopular instead
|
|
11
|
+
# to show popular routes to users before they enter a search term.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# finder = SpreeCmCommissioner::Places::FindWithRoute.new(keyword: 'Phnom', place_type: 'origin')
|
|
15
|
+
# finder.execute # => Returns places with "Phnom" in name that are used as route origins
|
|
16
|
+
module SpreeCmCommissioner
|
|
17
|
+
module Places
|
|
18
|
+
class FindWithRoute
|
|
19
|
+
attr_reader :keyword, :place_type
|
|
20
|
+
|
|
21
|
+
def initialize(keyword:, place_type:)
|
|
22
|
+
@keyword = keyword
|
|
23
|
+
@place_type = place_type
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def execute
|
|
27
|
+
return SpreeCmCommissioner::Place.none if keyword.blank? || place_type.blank?
|
|
28
|
+
|
|
29
|
+
scope.where('cm_places.name ILIKE ?', "%#{keyword}%")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def scope
|
|
35
|
+
if place_type == 'origin'
|
|
36
|
+
SpreeCmCommissioner::Place.with_routes_as_origin
|
|
37
|
+
else
|
|
38
|
+
SpreeCmCommissioner::Place.with_routes_as_destination
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Finds routes ordered by popularity based on order metrics.
|
|
2
|
+
#
|
|
3
|
+
# Routes are sorted by:
|
|
4
|
+
# 1. fulfilled_order_count (completed orders) - DESC
|
|
5
|
+
# 2. order_count (total orders including incomplete) - DESC
|
|
6
|
+
#
|
|
7
|
+
# @return [ActiveRecord::Relation<SpreeCmCommissioner::Route>] Routes with origin and destination places loaded,
|
|
8
|
+
# ordered from most to least popular
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# finder = SpreeCmCommissioner::Routes::FindPopular.new
|
|
12
|
+
# finder.execute # => Returns routes sorted by fulfillment and order counts
|
|
13
|
+
|
|
14
|
+
module SpreeCmCommissioner
|
|
15
|
+
module Routes
|
|
16
|
+
class FindPopular
|
|
17
|
+
def execute
|
|
18
|
+
SpreeCmCommissioner::Route
|
|
19
|
+
.includes(:origin_place, :destination_place)
|
|
20
|
+
.order(Arel.sql('COALESCE(fulfilled_order_count, 0) DESC'))
|
|
21
|
+
.order(Arel.sql('COALESCE(order_count, 0) DESC'))
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -12,14 +12,20 @@ module Spree
|
|
|
12
12
|
return false if @order.email.blank?
|
|
13
13
|
|
|
14
14
|
setup_tenant_and_store
|
|
15
|
+
if @tenant.present?
|
|
16
|
+
@name = @order.tenant.name
|
|
17
|
+
@logo = @order.tenant.active_vendor&.logo&.original_url
|
|
18
|
+
@brand_color = @order.tenant.preferred_brand_primary_color
|
|
19
|
+
end
|
|
15
20
|
@product_type = @order.products.first&.product_type || 'accommodation'
|
|
16
21
|
|
|
17
22
|
subject = build_subject(resend)
|
|
18
23
|
|
|
19
24
|
mail(to: @order.email,
|
|
20
|
-
from: from_email_address,
|
|
25
|
+
from: from_email_address,
|
|
26
|
+
subject: subject,
|
|
21
27
|
store_url: store_url
|
|
22
|
-
|
|
28
|
+
) do |format|
|
|
23
29
|
format.html { render layout: 'spree_cm_commissioner/layouts/order_mailer' }
|
|
24
30
|
format.text
|
|
25
31
|
end
|
|
@@ -38,10 +44,6 @@ module Spree
|
|
|
38
44
|
def setup_tenant_and_store
|
|
39
45
|
@tenant = @order.tenant
|
|
40
46
|
@current_store = @order.store
|
|
41
|
-
return if @tenant.blank?
|
|
42
|
-
|
|
43
|
-
@brand_color = @tenant.preferences[:brand_primary_color]
|
|
44
|
-
@vendor_logo_url = @tenant.active_vendor&.logo&.original_url
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
def build_subject(resend)
|