dscf-marketplace 0.3.3 → 0.3.5

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: 860d3ddc901bb2ca30262a59e16a674179bfa0dc7e349d23bc59e07488a0ccd3
4
- data.tar.gz: 6e8e95bd3ab0eff86e29a61f62fbbd031c22b17aaff6267f51b215d2171fc2f4
3
+ metadata.gz: ed0561954d684647c338a26994cf4b58d0671024866a05dfa897352e4e827e65
4
+ data.tar.gz: b959f769320523fdadcdb69e58664b9879fed6ec36b563b8155363ec0cb5856e
5
5
  SHA512:
6
- metadata.gz: 8581bfb7f3cb8cc254dc446f3577c33564b25f26ae88a0346249c51f4a38fa49c477c13c443d9e577c05a2cf3d4c4dd583c2fc387170b918a51d89a63cbab4e6
7
- data.tar.gz: f77483ec6c62d315d34e691bbd4903aefca0cbf7ca34978ee2c42348a3c2e4f84473051e6e60687bf2ccbe95dbcafef92544c8781bd1b5c927d5a72ca6fb5bca
6
+ metadata.gz: 8fbb075febd4bbbec9813858f235ad9b8be64d9e2df0a1adc16fdab225dc96295e4201d5d72d73e6fc18373e66341d075b42e3a026a819b850a6a3476d52466f
7
+ data.tar.gz: 247a76932d2cf383f5b3d6767899f2c96e5908f88198b50f041c31bd9cdbce81de49f1da2d3517947c8f348a3a5c56618832f04cd7b467e21653c4acef9f17b7
@@ -105,6 +105,60 @@ module Dscf
105
105
  end
106
106
  end
107
107
 
108
+ def accept
109
+ @obj = find_record
110
+ service = Dscf::Marketplace::DeliveryOrderService.new
111
+ begin
112
+ service.assign_driver(@obj, current_user)
113
+ render_success("delivery_orders.success.accepted", data: @obj)
114
+ rescue Dscf::Marketplace::DeliveryOrderService::InvalidStatusTransitionError => e
115
+ render_error("delivery_orders.errors.invalid_status_transition", message: e.message)
116
+ rescue Dscf::Marketplace::DeliveryOrderService::AssignmentError => e
117
+ render_error("delivery_orders.errors.assignment_failed", message: e.message)
118
+ rescue => e
119
+ render_error("delivery_orders.errors.accept_failed", message: e.message)
120
+ end
121
+ end
122
+
123
+ def convert_orders
124
+ order_ids = params[:order_ids]
125
+ vehicle_type = params[:vehicle_type]
126
+ pickup_address_id = params[:pickup_address_id]
127
+ delivery_notes = params[:delivery_notes]
128
+
129
+ # Validate required parameters
130
+ unless order_ids.present? && vehicle_type.present? && pickup_address_id.present?
131
+ render_error("delivery_orders.errors.convert_orders_missing_params")
132
+ return
133
+ end
134
+
135
+ # Find orders and pickup address
136
+ orders = Dscf::Marketplace::Order.where(id: order_ids)
137
+ pickup_address = Dscf::Core::Address.find_by(id: pickup_address_id)
138
+
139
+ unless pickup_address
140
+ render_error("delivery_orders.errors.pickup_address_not_found")
141
+ return
142
+ end
143
+
144
+ # Check if all orders exist
145
+ if orders.count != order_ids.length
146
+ missing_ids = order_ids - orders.pluck(:id)
147
+ render_error("delivery_orders.errors.orders_not_found", message: "Orders not found: #{missing_ids.join(", ")}")
148
+ return
149
+ end
150
+
151
+ service = Dscf::Marketplace::DeliveryOrderService.new
152
+ begin
153
+ delivery_order = service.convert_orders_to_delivery(orders, vehicle_type, pickup_address, delivery_notes)
154
+ render_success("delivery_orders.success.orders_converted", data: delivery_order)
155
+ rescue Dscf::Marketplace::DeliveryOrderService::ConversionError => e
156
+ render_error("delivery_orders.errors.orders_conversion_failed", message: e.message)
157
+ rescue => e
158
+ render_error("delivery_orders.errors.convert_orders_failed", message: e.message)
159
+ end
160
+ end
161
+
108
162
  private
109
163
 
110
164
  def model_params
@@ -3,13 +3,13 @@ module Dscf::Marketplace
3
3
  enum :status, {draft: 0, assigned: 1, picked_up: 2, in_transit: 3, delivered: 4, failed: 5}, default: :draft
4
4
  enum :vehicle_type, {motorcycle: 0, car: 1, van: 2, truck: 3}
5
5
 
6
- belongs_to :driver, class_name: "Dscf::Core::User"
6
+ belongs_to :driver, class_name: "Dscf::Core::User", optional: true
7
7
  belongs_to :pickup_address, class_name: "Dscf::Core::Address"
8
8
  belongs_to :delivery_vehicle, optional: true
9
9
  has_many :delivery_order_items, dependent: :destroy
10
10
  has_many :marketplace_orders, class_name: "Dscf::Marketplace::Order", dependent: :nullify
11
11
 
12
- validates :driver_id, presence: true
12
+ validates :driver_id, presence: true, unless: :draft?
13
13
  validates :pickup_address_id, presence: true
14
14
  validates :status, presence: true
15
15
  validates :vehicle_type, presence: true
@@ -0,0 +1,97 @@
1
+ module Dscf::Marketplace
2
+ class DeliveryOrderService
3
+ class InvalidStatusTransitionError < StandardError; end
4
+
5
+ class AssignmentError < StandardError; end
6
+
7
+ class ConversionError < StandardError; end
8
+
9
+ def assign_driver(delivery_order, driver)
10
+ raise ArgumentError, "Delivery order is required" unless delivery_order
11
+ raise ArgumentError, "Driver is required" unless driver
12
+
13
+ unless delivery_order.draft?
14
+ raise InvalidStatusTransitionError, "Can only assign driver to draft delivery orders"
15
+ end
16
+
17
+ delivery_order.driver_id = driver.id
18
+ delivery_order.status = :assigned
19
+
20
+ unless delivery_order.save
21
+ raise AssignmentError, "Failed to assign driver: #{delivery_order.errors.full_messages.join(", ")}"
22
+ end
23
+
24
+ delivery_order
25
+ end
26
+
27
+ def convert_orders_to_delivery(orders, vehicle_type, pickup_address, delivery_notes = nil)
28
+ raise ArgumentError, "Orders array is required" unless orders.present?
29
+ raise ArgumentError, "Vehicle type is required" unless vehicle_type.present?
30
+ raise ArgumentError, "Pickup address is required" unless pickup_address.present?
31
+
32
+ # Validate all orders can be converted
33
+ validate_orders_for_conversion(orders)
34
+
35
+ # Create delivery order in a transaction
36
+ DeliveryOrder.transaction do
37
+ delivery_order = create_delivery_order(vehicle_type, pickup_address, delivery_notes)
38
+ create_delivery_order_items(delivery_order, orders, pickup_address)
39
+ associate_orders_with_delivery(delivery_order, orders)
40
+
41
+ delivery_order
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def validate_orders_for_conversion(orders)
48
+ orders.each do |order|
49
+ unless order.delivery?
50
+ raise ConversionError, "Order #{order.id} is not a delivery order"
51
+ end
52
+
53
+ unless order.confirmed? || order.processing?
54
+ raise ConversionError, "Order #{order.id} must be confirmed or processing to be converted"
55
+ end
56
+
57
+ if order.delivery_order.present?
58
+ raise ConversionError, "Order #{order.id} is already associated with a delivery order"
59
+ end
60
+ end
61
+ end
62
+
63
+ def create_delivery_order(vehicle_type, pickup_address, delivery_notes)
64
+ DeliveryOrder.create!(
65
+ vehicle_type: vehicle_type,
66
+ pickup_address: pickup_address,
67
+ delivery_notes: delivery_notes,
68
+ status: :draft
69
+ )
70
+ end
71
+
72
+ def create_delivery_order_items(delivery_order, orders, pickup_address)
73
+ orders.each do |order|
74
+ order.order_items.each do |order_item|
75
+ # For now, use the pickup address as both pickup and dropoff
76
+ # In a real implementation, you'd need to get the buyer's delivery address
77
+ dropoff_address = pickup_address # Temporary fallback
78
+
79
+ DeliveryOrderItem.create!(
80
+ delivery_order: delivery_order,
81
+ order_item: order_item,
82
+ quantity: order_item.quantity,
83
+ pickup_address: pickup_address,
84
+ dropoff_address: dropoff_address,
85
+ status: :pending
86
+ )
87
+ end
88
+ end
89
+ end
90
+
91
+ def associate_orders_with_delivery(delivery_order, orders)
92
+ orders.each do |order|
93
+ order.update!(delivery_order: delivery_order)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -4,7 +4,7 @@
4
4
  # Pattern: {model_name}.{success|errors}.{action_name} - using plural for controller consistency
5
5
 
6
6
  en:
7
- # Core Models
7
+ # Core Models
8
8
  category:
9
9
  success:
10
10
  index: "Categories retrieved successfully"
@@ -234,28 +234,28 @@ en:
234
234
  update: "Failed to update order item"
235
235
  destroy: "Failed to delete order item"
236
236
 
237
- # Delivery Models
237
+ # Delivery Models
238
238
  delivery_order:
239
- success:
240
- index: "Delivery orders retrieved successfully"
241
- show: "Delivery order details retrieved successfully"
242
- create: "Delivery order created successfully"
243
- update: "Delivery order updated successfully"
244
- destroy: "Delivery order deleted successfully"
245
- pickup: "Delivery order picked up successfully"
246
- start_delivery: "Delivery started successfully"
247
- complete_delivery: "Delivery completed successfully"
248
- mark_failed: "Delivery marked as failed"
249
- errors:
250
- index: "Failed to retrieve delivery orders"
251
- show: "Failed to retrieve delivery order details"
252
- create: "Failed to create delivery order"
253
- update: "Failed to update delivery order"
254
- destroy: "Failed to delete delivery order"
255
- pickup: "Failed to pickup delivery order"
256
- start_delivery: "Failed to start delivery"
257
- complete_delivery: "Failed to complete delivery"
258
- mark_failed: "Failed to mark delivery as failed"
239
+ success:
240
+ index: "Delivery orders retrieved successfully"
241
+ show: "Delivery order details retrieved successfully"
242
+ create: "Delivery order created successfully"
243
+ update: "Delivery order updated successfully"
244
+ destroy: "Delivery order deleted successfully"
245
+ pickup: "Delivery order picked up successfully"
246
+ start_delivery: "Delivery started successfully"
247
+ complete_delivery: "Delivery completed successfully"
248
+ mark_failed: "Delivery marked as failed"
249
+ errors:
250
+ index: "Failed to retrieve delivery orders"
251
+ show: "Failed to retrieve delivery order details"
252
+ create: "Failed to create delivery order"
253
+ update: "Failed to update delivery order"
254
+ destroy: "Failed to delete delivery order"
255
+ pickup: "Failed to pickup delivery order"
256
+ start_delivery: "Failed to start delivery"
257
+ complete_delivery: "Failed to complete delivery"
258
+ mark_failed: "Failed to mark delivery as failed"
259
259
 
260
260
  delivery_orders:
261
261
  success:
@@ -268,7 +268,7 @@ en:
268
268
  delivery_started: "Delivery started successfully"
269
269
  delivery_completed: "Delivery completed successfully"
270
270
  marked_failed: "Delivery marked as failed"
271
- index.success: "Delivery orders retrieved successfully"
271
+ orders_converted: "Orders converted to delivery successfully"
272
272
  errors:
273
273
  index: "Failed to retrieve delivery orders"
274
274
  show: "Failed to retrieve delivery order details"
@@ -279,6 +279,15 @@ en:
279
279
  delivery_started: "Failed to start delivery"
280
280
  delivery_completed: "Failed to complete delivery"
281
281
  marked_failed: "Failed to mark delivery as failed"
282
+ pickup_failed: "Failed to pickup delivery order"
283
+ start_delivery_failed: "Failed to start delivery"
284
+ complete_delivery_failed: "Failed to complete delivery"
285
+ mark_failed_failed: "Failed to mark delivery as failed"
286
+ convert_orders_missing_params: "Missing required parameters: order_ids, vehicle_type, and pickup_address_id"
287
+ pickup_address_not_found: "Pickup address not found"
288
+ orders_not_found: "Some orders were not found"
289
+ orders_conversion_failed: "Failed to convert orders to delivery"
290
+ convert_orders_failed: "Unexpected error during order conversion"
282
291
 
283
292
  delivery_order_item:
284
293
  success:
data/config/routes.rb CHANGED
@@ -102,9 +102,11 @@ Dscf::Marketplace::Engine.routes.draw do
102
102
  post "start_delivery"
103
103
  post "complete_delivery"
104
104
  post "mark_failed"
105
+ post "accept"
105
106
  end
106
107
  collection do
107
108
  get "filter"
109
+ post "convert_orders"
108
110
  end
109
111
  end
110
112
 
@@ -0,0 +1,5 @@
1
+ class MakeDriverIdNullableInDeliveryOrders < ActiveRecord::Migration[8.0]
2
+ def change
3
+ change_column_null :dscf_marketplace_delivery_orders, :driver_id, true
4
+ end
5
+ end
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Marketplace
3
- VERSION = "0.3.3".freeze
3
+ VERSION = "0.3.5".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dscf-marketplace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asrat
@@ -469,6 +469,7 @@ files:
469
469
  - app/serializers/dscf/marketplace/unit_conversion_serializer.rb
470
470
  - app/serializers/dscf/marketplace/unit_serializer.rb
471
471
  - app/serializers/dscf/marketplace/user_serializer.rb
472
+ - app/services/dscf/marketplace/delivery_order_service.rb
472
473
  - app/services/dscf/marketplace/my_resource_service.rb
473
474
  - app/services/dscf/marketplace/rfq_response_service.rb
474
475
  - config/environments/production.rb
@@ -499,6 +500,7 @@ files:
499
500
  - db/migrate/20250903061154_add_ordered_fields_to_orders.rb
500
501
  - db/migrate/20250903061306_populate_ordered_fields_for_existing_orders.rb
501
502
  - db/migrate/20250909092700_add_notes_to_dscf_marketplace_quotation_items.rb
503
+ - db/migrate/20250916083536_make_driver_id_nullable_in_delivery_orders.rb
502
504
  - lib/dscf/marketplace.rb
503
505
  - lib/dscf/marketplace/engine.rb
504
506
  - lib/dscf/marketplace/version.rb