dscf-marketplace 0.10.0 → 0.11.0
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/app/controllers/dscf/marketplace/orders_controller.rb +46 -1
- data/app/models/dscf/marketplace/order_item.rb +5 -2
- data/app/serializers/dscf/marketplace/order_item_serializer.rb +2 -1
- data/app/services/dscf/marketplace/order_splitting_service.rb +44 -1
- data/config/routes.rb +3 -0
- data/db/migrate/20260703000001_add_supplier_adjustment_to_order_items.rb +10 -0
- data/lib/dscf/marketplace/engine.rb +1 -1
- data/lib/dscf/marketplace/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0a4b240effc7edee8fd220eb4eca3ed1d9856b81bf1b52ae0d9825dc5457e11
|
|
4
|
+
data.tar.gz: 8d86a1061e2e9712836c589f4d1cda3b94b36b8d7c1a84a7e64f01705b69884f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d79fd32300f658a1b29f8dd38d921461d4fa1c33c1a9501c03edd2c25e144260c45ba4fa7f1ce4e609a2a23e230787eec1c929ca6f5d8df271623648f1f489e
|
|
7
|
+
data.tar.gz: ccb0a00956391215272d0a403cd536468d7d56aab7f5b69cfc0854d0f3d869c7479823f17bb4396d99d92721460b10ffb165918312f25e9606c60235c53f6152
|
|
@@ -194,6 +194,47 @@ module Dscf
|
|
|
194
194
|
render_error(errors: e.message, status: :unprocessable_entity)
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
+
def adjust_item
|
|
198
|
+
obj = find_record
|
|
199
|
+
authorize obj, :supplier_confirm?
|
|
200
|
+
|
|
201
|
+
item = obj.order_items.find(params[:order_item_id])
|
|
202
|
+
Dscf::Marketplace::OrderSplittingService.adjust_item(
|
|
203
|
+
obj, item,
|
|
204
|
+
unit_price: params[:unit_price],
|
|
205
|
+
quantity: params[:quantity],
|
|
206
|
+
note: params[:note]
|
|
207
|
+
)
|
|
208
|
+
create_notification_for_order(obj, :supplier_adjusted, reason: params[:note])
|
|
209
|
+
render_success(data: obj.reload, serializer_options: { include: default_serializer_includes[:show] || [] })
|
|
210
|
+
rescue => e
|
|
211
|
+
render_error(errors: e.message, status: :unprocessable_entity)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def accept_adjustment
|
|
215
|
+
obj = find_record
|
|
216
|
+
authorize obj, :split?
|
|
217
|
+
|
|
218
|
+
item = obj.order_items.find(params[:order_item_id])
|
|
219
|
+
Dscf::Marketplace::OrderSplittingService.accept_item_adjustment(obj, item)
|
|
220
|
+
create_notification_for_order(obj, :adjustment_accepted)
|
|
221
|
+
render_success(data: obj.reload, serializer_options: { include: default_serializer_includes[:show] || [] })
|
|
222
|
+
rescue => e
|
|
223
|
+
render_error(errors: e.message, status: :unprocessable_entity)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def reject_adjustment
|
|
227
|
+
obj = find_record
|
|
228
|
+
authorize obj, :split?
|
|
229
|
+
|
|
230
|
+
item = obj.order_items.find(params[:order_item_id])
|
|
231
|
+
Dscf::Marketplace::OrderSplittingService.reject_item_adjustment(obj, item, reason: params[:reason])
|
|
232
|
+
create_notification_for_order(obj, :adjustment_rejected, reason: params[:reason])
|
|
233
|
+
render_success(data: obj.reload, serializer_options: { include: default_serializer_includes[:show] || [] })
|
|
234
|
+
rescue => e
|
|
235
|
+
render_error(errors: e.message, status: :unprocessable_entity)
|
|
236
|
+
end
|
|
237
|
+
|
|
197
238
|
def retailer_confirm
|
|
198
239
|
obj = find_record
|
|
199
240
|
authorize obj, :confirm? # reuse existing or add specific
|
|
@@ -227,13 +268,17 @@ module Dscf
|
|
|
227
268
|
when :split_ready then "Order ##{order.id} ready for supplier confirmation"
|
|
228
269
|
when :supplier_confirmed then "Supplier confirmed order ##{order.id}"
|
|
229
270
|
when :supplier_rejected then "Supplier rejected item in order ##{order.id}"
|
|
271
|
+
when :supplier_adjusted then "Supplier proposed an adjustment on order ##{order.id}"
|
|
272
|
+
when :adjustment_accepted then "Adjustment accepted on order ##{order.id}"
|
|
273
|
+
when :adjustment_rejected then "Adjustment rejected on order ##{order.id}"
|
|
230
274
|
when :retailer_confirmed then "Retailer confirmed order ##{order.id}"
|
|
231
275
|
when :retailer_rejected then "Retailer cancelled order ##{order.id}"
|
|
232
276
|
else "Order ##{order.id} update"
|
|
233
277
|
end
|
|
234
278
|
|
|
235
279
|
body = case action
|
|
236
|
-
when :supplier_rejected, :retailer_rejected
|
|
280
|
+
when :supplier_rejected, :retailer_rejected, :supplier_adjusted, :adjustment_rejected
|
|
281
|
+
"Reason: #{reason}" if reason
|
|
237
282
|
else "Status: #{order.status}"
|
|
238
283
|
end
|
|
239
284
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
module Dscf::Marketplace
|
|
2
2
|
class OrderItem < ApplicationRecord
|
|
3
|
-
|
|
3
|
+
# :adjusted — the supplier proposed a revised price/quantity that is awaiting
|
|
4
|
+
# the aggregator's accept/reject follow-up. Distinct from confirmed/cancelled so
|
|
5
|
+
# supplier_confirmation_complete? holds the order until the aggregator responds.
|
|
6
|
+
enum :status, {pending: 0, confirmed: 1, processing: 2, fulfilled: 3, cancelled: 4, adjusted: 5}
|
|
4
7
|
enum :validation_status, {
|
|
5
8
|
validated: 0,
|
|
6
9
|
no_longer_listed: 1,
|
|
@@ -26,7 +29,7 @@ module Dscf::Marketplace
|
|
|
26
29
|
|
|
27
30
|
# Ransack configuration for secure filtering
|
|
28
31
|
def self.ransackable_attributes(_auth_object = nil)
|
|
29
|
-
%w[id order_id quotation_item_id listing_id product_id unit_id quantity unit_price status validation_status validation_note resolved_unit_price resolved_quantity source_type source_id created_at updated_at]
|
|
32
|
+
%w[id order_id quotation_item_id listing_id product_id unit_id quantity unit_price status validation_status validation_note resolved_unit_price resolved_quantity source_type source_id supplier_adjusted_unit_price supplier_adjusted_quantity supplier_adjustment_note created_at updated_at]
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
def self.ransackable_associations(_auth_object = nil)
|
|
@@ -5,7 +5,8 @@ module Dscf
|
|
|
5
5
|
:product_id, :unit_id, :quantity, :unit_price,
|
|
6
6
|
:status, :validation_status, :validation_note, :resolved_unit_price, :resolved_quantity,
|
|
7
7
|
:source_type, :source_id, :source_name, :created_at, :updated_at,
|
|
8
|
-
:subtotal, :product_name, :unit_name, :thumbnail_url, :images_urls
|
|
8
|
+
:subtotal, :product_name, :unit_name, :thumbnail_url, :images_urls,
|
|
9
|
+
:supplier_adjusted_unit_price, :supplier_adjusted_quantity, :supplier_adjustment_note
|
|
9
10
|
|
|
10
11
|
belongs_to :order
|
|
11
12
|
belongs_to :quotation_item
|
|
@@ -32,7 +32,8 @@ module Dscf
|
|
|
32
32
|
|
|
33
33
|
def self.supplier_confirm(order, confirmed: true, reason: nil)
|
|
34
34
|
if confirmed
|
|
35
|
-
|
|
35
|
+
# In full impl, mark specific allocation as confirmed
|
|
36
|
+
# For now advance whole if appropriate
|
|
36
37
|
else
|
|
37
38
|
order.order_items.where(status: :processing).update_all(status: OrderItem.statuses[:cancelled])
|
|
38
39
|
end
|
|
@@ -57,6 +58,48 @@ module Dscf
|
|
|
57
58
|
order.mark_waiting_retailer_confirmation! if order.supplier_confirmation_complete?
|
|
58
59
|
order_item
|
|
59
60
|
end
|
|
61
|
+
|
|
62
|
+
# Supplier proposes revised terms instead of confirming/rejecting outright.
|
|
63
|
+
# The item goes to :adjusted holding the proposal; because :adjusted is neither
|
|
64
|
+
# confirmed nor cancelled, supplier_confirmation_complete? keeps the order in
|
|
65
|
+
# waiting_supplier_confirmation until the aggregator follows up (accept/reject).
|
|
66
|
+
def self.adjust_item(order, order_item, unit_price: nil, quantity: nil, note: nil)
|
|
67
|
+
order_item.supplier_adjusted_unit_price = unit_price if unit_price.present?
|
|
68
|
+
order_item.supplier_adjusted_quantity = quantity if quantity.present?
|
|
69
|
+
order_item.supplier_adjustment_note = note
|
|
70
|
+
order_item.status = :adjusted
|
|
71
|
+
order_item.save!
|
|
72
|
+
order_item
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Aggregator accepts the supplier's proposal: the adjusted price/quantity become
|
|
76
|
+
# the line's actual terms, the item is confirmed, and the order total recomputes
|
|
77
|
+
# (Order#calculate_total_amount runs on save). Advances once all items responded.
|
|
78
|
+
def self.accept_item_adjustment(order, order_item)
|
|
79
|
+
order_item.unit_price = order_item.supplier_adjusted_unit_price if order_item.supplier_adjusted_unit_price.present?
|
|
80
|
+
order_item.quantity = order_item.supplier_adjusted_quantity if order_item.supplier_adjusted_quantity.present?
|
|
81
|
+
order_item.supplier_adjusted_unit_price = nil
|
|
82
|
+
order_item.supplier_adjusted_quantity = nil
|
|
83
|
+
order_item.status = :confirmed
|
|
84
|
+
order_item.save!
|
|
85
|
+
|
|
86
|
+
order.reload
|
|
87
|
+
order.save! # recompute total_amount from the revised line
|
|
88
|
+
order.mark_waiting_retailer_confirmation! if order.supplier_confirmation_complete?
|
|
89
|
+
order_item
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Aggregator rejects the proposal — the line can't be fulfilled on agreeable
|
|
93
|
+
# terms, so it is cancelled (mirrors a not-confirm). Advances if all responded.
|
|
94
|
+
def self.reject_item_adjustment(order, order_item, reason: nil)
|
|
95
|
+
order_item.supplier_adjustment_note = reason if reason.present?
|
|
96
|
+
order_item.status = :cancelled
|
|
97
|
+
order_item.save!
|
|
98
|
+
|
|
99
|
+
order.reload
|
|
100
|
+
order.mark_waiting_retailer_confirmation! if order.supplier_confirmation_complete?
|
|
101
|
+
order_item
|
|
102
|
+
end
|
|
60
103
|
end
|
|
61
104
|
end
|
|
62
105
|
end
|
data/config/routes.rb
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class AddSupplierAdjustmentToDscfMarketplaceOrderItems < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
# When a supplier can't fulfil an allocation at the aggregator's terms, they
|
|
4
|
+
# propose a revised price/quantity instead of outright rejecting. The proposal
|
|
5
|
+
# is held here (item status -> :adjusted) until the aggregator accepts or rejects.
|
|
6
|
+
add_column :dscf_marketplace_order_items, :supplier_adjusted_unit_price, :decimal, precision: 15, scale: 6
|
|
7
|
+
add_column :dscf_marketplace_order_items, :supplier_adjusted_quantity, :decimal, precision: 15, scale: 6
|
|
8
|
+
add_column :dscf_marketplace_order_items, :supplier_adjustment_note, :text
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -36,7 +36,7 @@ module Dscf
|
|
|
36
36
|
resource :rfq_items, actions: %i[index show create update destroy]
|
|
37
37
|
resource :quotations, actions: %i[index show create update destroy accept reject send_quotation my_quotes filter]
|
|
38
38
|
resource :quotation_items, actions: %i[index show create update destroy]
|
|
39
|
-
resource :orders, actions: %i[index show create update destroy confirm cancel complete my_orders filter validate resolve_item assign_source split supplier_confirm retailer_confirm]
|
|
39
|
+
resource :orders, actions: %i[index show create update destroy confirm cancel complete my_orders filter validate resolve_item assign_source split supplier_confirm confirm_item adjust_item accept_adjustment reject_adjustment retailer_confirm]
|
|
40
40
|
resource :order_items, actions: %i[index show create update destroy]
|
|
41
41
|
resource :delivery_orders, actions: %i[
|
|
42
42
|
index show create update destroy pickup start_delivery complete_delivery mark_failed accept summary
|
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.
|
|
4
|
+
version: 0.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Asrat
|
|
@@ -593,6 +593,7 @@ files:
|
|
|
593
593
|
- db/migrate/20260619210002_add_user_id_to_dscf_marketplace_retailers.rb
|
|
594
594
|
- db/migrate/20260622000001_add_validation_and_source_fields_to_dscf_marketplace_order_items.rb
|
|
595
595
|
- db/migrate/20260702000001_unify_aggregator_listing_source.rb
|
|
596
|
+
- db/migrate/20260703000001_add_supplier_adjustment_to_order_items.rb
|
|
596
597
|
- db/seeds.rb
|
|
597
598
|
- lib/dscf/marketplace.rb
|
|
598
599
|
- lib/dscf/marketplace/engine.rb
|