dscf-marketplace 0.7.3 → 0.7.4
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6868f5b7cbade52d287939591c2011a7140b76eda6f3223ba7f66a3a51fb3d08
|
|
4
|
+
data.tar.gz: dd56581029c76743ec281f4de717f00410a38d780b68ad57a13a11cd36e8ddd2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d7737babebba09f37154720fea2502464ad2c71cac4007114a40d3d22529efc664091d8f96a26086140bdd66696cfffa0bf7b1d828b6764f833e1497327940e
|
|
7
|
+
data.tar.gz: a2f2b76706da91f693a76cbe47e6b913b97819777f81ef3dacd354a83e59d8106dfcca11402af054493c1dcda586edca8b998858adbcfaeb11297aea302ffff2
|
|
@@ -9,7 +9,7 @@ module Dscf::Marketplace
|
|
|
9
9
|
def assign_driver(delivery_order, driver)
|
|
10
10
|
raise ArgumentError, "Delivery order is required" unless delivery_order
|
|
11
11
|
raise ArgumentError, "Driver is required" unless driver
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
validate_assignment(delivery_order)
|
|
14
14
|
|
|
15
15
|
delivery_order.driver_id = driver.id
|
|
@@ -35,9 +35,15 @@ module Dscf::Marketplace
|
|
|
35
35
|
delivery_order = create_delivery_order(vehicle_type, pickup_address, delivery_notes)
|
|
36
36
|
create_delivery_stops_and_items(delivery_order, orders, pickup_address)
|
|
37
37
|
associate_orders_with_delivery(delivery_order, orders)
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
|
|
38
|
+
|
|
39
|
+
# Best-effort route optimization using Gebeta Maps.
|
|
40
|
+
begin
|
|
41
|
+
RouteOptimizationService.new(delivery_order).optimize!
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
Rails.logger.warn(
|
|
44
|
+
"[DeliveryOrderService] Route optimization skipped for delivery_order=#{delivery_order.id}: #{e.class} - #{e.message}"
|
|
45
|
+
)
|
|
46
|
+
end
|
|
41
47
|
|
|
42
48
|
delivery_order
|
|
43
49
|
end
|
|
@@ -79,7 +85,7 @@ module Dscf::Marketplace
|
|
|
79
85
|
def create_delivery_stops_and_items(delivery_order, orders, pickup_address)
|
|
80
86
|
# Group orders by dropoff address to create stops
|
|
81
87
|
orders_by_address = orders.group_by(&:dropoff_address_id)
|
|
82
|
-
|
|
88
|
+
|
|
83
89
|
orders_by_address.each do |dropoff_address_id, address_orders|
|
|
84
90
|
# Create stop
|
|
85
91
|
stop = DeliveryStop.create!(
|
|
@@ -87,7 +93,7 @@ module Dscf::Marketplace
|
|
|
87
93
|
dropoff_address_id: dropoff_address_id,
|
|
88
94
|
status: :pending
|
|
89
95
|
)
|
|
90
|
-
|
|
96
|
+
|
|
91
97
|
# Create items for this stop
|
|
92
98
|
address_orders.each do |order|
|
|
93
99
|
order.order_items.reload.each do |order_item|
|
|
@@ -10,83 +10,71 @@ module Dscf
|
|
|
10
10
|
def optimize!
|
|
11
11
|
return unless delivery_order.pickup_address && delivery_order.delivery_stops.any?
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
stops
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# ],
|
|
36
|
-
# "total_distance": 13.474, # In KM? Diagnostic showed 13.474 for small distance. Need to verify unit.
|
|
37
|
-
# "time_taken": 1033.263,
|
|
38
|
-
# "Direction": [[lat,lon], ...]
|
|
39
|
-
# }
|
|
40
|
-
|
|
41
|
-
# 'best_order' includes the start point at index 0 (usually without original_index or it's 0/1 based?)
|
|
42
|
-
# Based on diagnostic: "original_index": 2 for the 3rd point (index 2).
|
|
43
|
-
# So original_index is 0-based index from the input array.
|
|
44
|
-
|
|
45
|
-
best_order = response["best_order"]
|
|
46
|
-
|
|
47
|
-
# Filter out the pickup location (which should be the first one, or original_index == 0)
|
|
48
|
-
# We only want to re-sequence the STOPS.
|
|
49
|
-
# Stops in 'stops' array correspond to input indices 1..N.
|
|
50
|
-
|
|
51
|
-
ordered_stops_data = best_order.select { |node| node["original_index"].to_i > 0 }
|
|
52
|
-
|
|
13
|
+
stops = []
|
|
14
|
+
locations = []
|
|
15
|
+
|
|
16
|
+
stops = ordered_stops
|
|
17
|
+
locations = build_locations(stops)
|
|
18
|
+
|
|
19
|
+
apply_remote_optimization(stops, locations)
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
Rails.logger.warn(
|
|
22
|
+
"[RouteOptimizationService] Falling back to local route for delivery_order=#{delivery_order.id}: #{e.class} - #{e.message}"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
apply_local_fallback(stops, locations)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def apply_remote_optimization(stops, locations)
|
|
31
|
+
response = GebetaService.new.tsp(locations)
|
|
32
|
+
best_order = Array(response["best_order"])
|
|
33
|
+
ordered_stops_data = best_order.select { |node| node["original_index"].to_i.positive? }
|
|
34
|
+
|
|
53
35
|
ActiveRecord::Base.transaction do
|
|
54
36
|
ordered_stops_data.each_with_index do |node, seq_num|
|
|
55
|
-
original_idx = node["original_index"]
|
|
56
|
-
# stops array is 0-indexed, corresponding to input indices 1, 2, 3...
|
|
57
|
-
# If original_idx is 1, it means stops[0]. If 2, stops[1].
|
|
37
|
+
original_idx = node["original_index"].to_i
|
|
58
38
|
stop = stops[original_idx - 1]
|
|
59
|
-
|
|
60
|
-
if stop
|
|
61
|
-
stop.update!(sequence_number: seq_num + 1)
|
|
62
|
-
end
|
|
39
|
+
stop.update!(sequence_number: seq_num + 1) if stop
|
|
63
40
|
end
|
|
64
41
|
|
|
65
|
-
# Update DeliveryOrder metrics
|
|
66
|
-
# Check units:
|
|
67
|
-
# time_taken: 1033.263 (likely seconds ~ 17 mins for decent distance).
|
|
68
|
-
# total_distance: 13.474. If this is KM, it's reasonable. (Distance between 9.02,38.80 and 9.028,38.75 is ~ small).
|
|
69
|
-
# If meters, 13 meters is too small. 1000 seconds for 13 meters is wrong.
|
|
70
|
-
# So total_distance is likely KM.
|
|
71
|
-
|
|
72
42
|
distance_km = response["total_distance"].to_f
|
|
73
|
-
|
|
43
|
+
|
|
74
44
|
delivery_order.update!(
|
|
75
45
|
estimated_delivery_time: Time.current + response["time_taken"].to_f.seconds,
|
|
76
|
-
estimated_delivery_price: calculate_price(distance_km * 1000),
|
|
77
|
-
optimized_route: response["Direction"]
|
|
46
|
+
estimated_delivery_price: calculate_price(distance_km * 1000),
|
|
47
|
+
optimized_route: response["Direction"]
|
|
78
48
|
)
|
|
79
49
|
end
|
|
80
50
|
end
|
|
81
51
|
|
|
82
|
-
|
|
52
|
+
def apply_local_fallback(stops, locations)
|
|
53
|
+
ActiveRecord::Base.transaction do
|
|
54
|
+
stops.each_with_index do |stop, index|
|
|
55
|
+
stop.update!(sequence_number: index + 1)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
delivery_order.update!(optimized_route: locations)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def ordered_stops
|
|
63
|
+
delivery_order.delivery_stops.includes(:dropoff_address).order(:id).to_a
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def build_locations(stops)
|
|
67
|
+
pickup_coords = [ delivery_order.pickup_address.latitude.to_f, delivery_order.pickup_address.longitude.to_f ]
|
|
68
|
+
stop_coords = stops.map { |stop| [ stop.dropoff_address.latitude.to_f, stop.dropoff_address.longitude.to_f ] }
|
|
69
|
+
|
|
70
|
+
[ pickup_coords ] + stop_coords
|
|
71
|
+
end
|
|
83
72
|
|
|
84
|
-
# Placeholder pricing logic
|
|
85
73
|
def calculate_price(distance_meters)
|
|
86
74
|
base_rate = 50.0
|
|
87
|
-
km_rate = 10.0
|
|
75
|
+
km_rate = 10.0
|
|
88
76
|
distance_km = distance_meters / 1000.0
|
|
89
|
-
|
|
77
|
+
|
|
90
78
|
base_rate + (distance_km * km_rate)
|
|
91
79
|
end
|
|
92
80
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dscf-marketplace
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Asrat
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-04-
|
|
10
|
+
date: 2026-04-24 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|