dscf-marketplace 0.1.9 → 0.2.1
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/businesses_controller.rb +34 -0
- data/app/controllers/dscf/marketplace/delivery_order_items_controller.rb +64 -0
- data/app/controllers/dscf/marketplace/delivery_orders_controller.rb +72 -0
- data/app/controllers/dscf/marketplace/delivery_vehicles_controller.rb +28 -0
- data/app/controllers/dscf/marketplace/order_items_controller.rb +29 -0
- data/app/controllers/dscf/marketplace/quotation_items_controller.rb +28 -0
- data/app/controllers/dscf/marketplace/rfq_items_controller.rb +28 -0
- data/app/controllers/dscf/marketplace/supplier_products_controller.rb +29 -0
- data/app/controllers/dscf/marketplace/unit_conversions_controller.rb +28 -0
- data/app/controllers/dscf/marketplace/units_controller.rb +26 -0
- data/app/models/dscf/marketplace/delivery_order.rb +6 -0
- data/app/models/dscf/marketplace/quotation_item.rb +42 -10
- data/app/serializers/dscf/marketplace/business_serializer.rb +11 -0
- data/app/serializers/dscf/marketplace/delivery_order_item_serializer.rb +17 -0
- data/app/serializers/dscf/marketplace/delivery_order_serializer.rb +17 -0
- data/app/serializers/dscf/marketplace/delivery_vehicle_serializer.rb +12 -0
- data/app/serializers/dscf/marketplace/order_item_serializer.rb +16 -0
- data/app/serializers/dscf/marketplace/quotation_item_serializer.rb +16 -0
- data/app/serializers/dscf/marketplace/rfq_item_serializer.rb +14 -0
- data/app/serializers/dscf/marketplace/supplier_product_serializer.rb +13 -0
- data/app/serializers/dscf/marketplace/unit_conversion_serializer.rb +11 -0
- data/app/serializers/dscf/marketplace/unit_serializer.rb +9 -0
- data/config/locales/en.yml +12 -0
- data/config/routes.rb +10 -4
- data/lib/dscf/marketplace/version.rb +1 -1
- data/spec/factories/dscf/marketplace/delivery_order_items.rb +1 -1
- data/spec/factories/dscf/marketplace/quotation_items.rb +2 -2
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70190000bbbdf144579c8e6c27608664b18a4a8460ac43350f9dc1162c355b0a
|
4
|
+
data.tar.gz: 1e661035af4d825af27418bf07a7342eaa641d39ea6e20fd1cc62dd64aecbd75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a1fb37f55cd3d15a6a89098f435dd8f7797748440dff0f68aac15be45a92c1e3b7807ef2307013846cdab795153a8b956fdc50eaa569424a9ec88695f77763e
|
7
|
+
data.tar.gz: a18369805514a3d9d24562ada719551baf8e06621a5bb5b806afafd900f8245dbdc16568f6514ec77953055c6faece98fa937961ba05a28d9c8aaed853393828
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class BusinessesController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
def has_business
|
7
|
+
has_business = current_user&.businesses&.exists? || false
|
8
|
+
render_success("business.success.has_business_check", data: {has_business: has_business})
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def model_params
|
14
|
+
params.require(:business).permit(
|
15
|
+
:name, :description, :contact_email, :contact_phone, :tin_number,
|
16
|
+
:business_type_id, :user_id
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def eager_loaded_associations
|
21
|
+
[ :business_type, :user ]
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_serializer_includes
|
25
|
+
{
|
26
|
+
index: [ :business_type, :user ],
|
27
|
+
show: [ :business_type, :user ],
|
28
|
+
create: [ :business_type, :user ],
|
29
|
+
update: [ :business_type, :user ]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryOrderItemsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
def receiver_confirm
|
7
|
+
@obj = find_record
|
8
|
+
if @obj.receiver_confirm!(params[:confirmed_quantity], params[:notes], current_user&.id)
|
9
|
+
render_success("delivery_order_items.success.receiver_confirmed", data: @obj)
|
10
|
+
else
|
11
|
+
render_error("delivery_order_items.errors.receiver_confirm_failed")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def report_issue
|
16
|
+
@obj = find_record
|
17
|
+
issue_type = params[:issue_type]
|
18
|
+
quantity = params[:quantity]
|
19
|
+
description = params[:description]
|
20
|
+
|
21
|
+
if @obj.report_issue!(issue_type, quantity, description, current_user&.id)
|
22
|
+
render_success("delivery_order_items.success.issue_reported", data: @obj)
|
23
|
+
else
|
24
|
+
render_error("delivery_order_items.errors.report_issue_failed")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def dispute_delivery
|
29
|
+
@obj = find_record
|
30
|
+
reason = params[:reason]
|
31
|
+
|
32
|
+
if @obj.dispute_delivery!(reason, current_user&.id)
|
33
|
+
render_success("delivery_order_items.success.delivery_disputed", data: @obj)
|
34
|
+
else
|
35
|
+
render_error("delivery_order_items.errors.dispute_delivery_failed")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def model_params
|
42
|
+
params.require(:delivery_order_item).permit(
|
43
|
+
:delivery_order_id, :order_item_id, :pickup_address_id, :dropoff_address_id,
|
44
|
+
:quantity, :status, :pickup_verified_quantity, :dropoff_verified_quantity,
|
45
|
+
:damaged_quantity, :missing_quantity, :receiver_confirmed_by,
|
46
|
+
:receiver_confirmed_at, :receiver_notes, :handoff_checklist_completed
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def eager_loaded_associations
|
51
|
+
[ :delivery_order, :order_item, :pickup_address, :dropoff_address ]
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_serializer_includes
|
55
|
+
{
|
56
|
+
index: [ :delivery_order, :order_item ],
|
57
|
+
show: [ :delivery_order, :order_item, :pickup_address, :dropoff_address ],
|
58
|
+
create: [ :delivery_order, :order_item ],
|
59
|
+
update: [ :delivery_order, :order_item ]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryOrdersController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
def index
|
7
|
+
@objs = DeliveryOrder.all
|
8
|
+
render_success("delivery_orders.index.success", data: @objs, serializer_options: {include: default_serializer_includes[:index]})
|
9
|
+
end
|
10
|
+
|
11
|
+
def pickup
|
12
|
+
@obj = find_record
|
13
|
+
if @obj.pickup!
|
14
|
+
render_success("delivery_orders.success.picked_up", data: @obj)
|
15
|
+
else
|
16
|
+
render_error("delivery_orders.errors.pickup_failed")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def start_delivery
|
21
|
+
@obj = find_record
|
22
|
+
if @obj.start_delivery!
|
23
|
+
render_success("delivery_orders.success.delivery_started", data: @obj)
|
24
|
+
else
|
25
|
+
render_error("delivery_orders.errors.start_delivery_failed")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def complete_delivery
|
30
|
+
@obj = find_record
|
31
|
+
if @obj.complete_delivery!
|
32
|
+
render_success("delivery_orders.success.delivery_completed", data: @obj)
|
33
|
+
else
|
34
|
+
render_error("delivery_orders.errors.complete_delivery_failed")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def mark_failed
|
39
|
+
@obj = find_record
|
40
|
+
reason = params[:reason]
|
41
|
+
if @obj.mark_failed!(reason)
|
42
|
+
render_success("delivery_orders.success.marked_failed", data: @obj)
|
43
|
+
else
|
44
|
+
render_error("delivery_orders.errors.mark_failed_failed")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def model_params
|
51
|
+
params.require(:delivery_order).permit(
|
52
|
+
:driver_id, :pickup_address_id, :delivery_vehicle_id, :status,
|
53
|
+
:vehicle_type, :estimated_delivery_price, :actual_delivery_price,
|
54
|
+
:estimated_delivery_time, :actual_delivery_time, :delivery_notes
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def eager_loaded_associations
|
59
|
+
[ :driver, :pickup_address, :delivery_vehicle, :delivery_order_items, :marketplace_orders ]
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_serializer_includes
|
63
|
+
{
|
64
|
+
index: [ :driver, :pickup_address, :delivery_vehicle ],
|
65
|
+
show: [ :driver, :pickup_address, :delivery_vehicle, :delivery_order_items, :marketplace_orders ],
|
66
|
+
create: [ :driver, :pickup_address, :delivery_vehicle ],
|
67
|
+
update: [ :driver, :pickup_address, :delivery_vehicle ]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryVehiclesController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:delivery_vehicle).permit(
|
10
|
+
:driver_id, :plate_number, :vehicle_type, :year, :brand, :model, :color
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_loaded_associations
|
15
|
+
[ :driver, :delivery_orders ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_serializer_includes
|
19
|
+
{
|
20
|
+
index: [ :driver ],
|
21
|
+
show: [ :driver, :delivery_orders ],
|
22
|
+
create: [ :driver ],
|
23
|
+
update: [ :driver ]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class OrderItemsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:order_item).permit(
|
10
|
+
:order_id, :quotation_item_id, :listing_id,
|
11
|
+
:product_id, :unit_id, :quantity, :unit_price, :status
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def eager_loaded_associations
|
16
|
+
[ :order, :quotation_item, :listing, :product, :unit ]
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_serializer_includes
|
20
|
+
{
|
21
|
+
index: [ :product, :unit ],
|
22
|
+
show: [ :order, :quotation_item, :listing, :product, :unit ],
|
23
|
+
create: [ :product, :unit ],
|
24
|
+
update: [ :product, :unit ]
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class QuotationItemsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:quotation_item).permit(
|
10
|
+
:quotation_id, :rfq_item_id, :product_id, :unit_id, :quantity, :unit_price
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_loaded_associations
|
15
|
+
[ :quotation, :rfq_item, :product, :unit ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_serializer_includes
|
19
|
+
{
|
20
|
+
index: [ :quotation, :rfq_item, :product, :unit ],
|
21
|
+
show: [ :quotation, :rfq_item, :product, :unit ],
|
22
|
+
create: [ :quotation, :rfq_item, :product, :unit ],
|
23
|
+
update: [ :quotation, :rfq_item, :product, :unit ]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class RfqItemsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:rfq_item).permit(
|
10
|
+
:request_for_quotation_id, :product_id, :unit_id, :quantity, :notes
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_loaded_associations
|
15
|
+
[ :request_for_quotation, :product, :unit, :quotation_items ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_serializer_includes
|
19
|
+
{
|
20
|
+
index: [ :request_for_quotation, :product, :unit ],
|
21
|
+
show: [ :request_for_quotation, :product, :unit, :quotation_items ],
|
22
|
+
create: [ :request_for_quotation, :product, :unit ],
|
23
|
+
update: [ :request_for_quotation, :product, :unit ]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class SupplierProductsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:supplier_product).permit(
|
10
|
+
:business_id, :product_id, :supplier_price, :available_quantity,
|
11
|
+
:minimum_order_quantity, :status
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def eager_loaded_associations
|
16
|
+
[ :business, :product, :listings ]
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_serializer_includes
|
20
|
+
{
|
21
|
+
index: [ :business, :product ],
|
22
|
+
show: [ :business, :product, :listings ],
|
23
|
+
create: [ :business, :product ],
|
24
|
+
update: [ :business, :product ]
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class UnitConversionsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:unit_conversion).permit(
|
10
|
+
:from_unit_id, :to_unit_id, :conversion_factor, :notes
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_loaded_associations
|
15
|
+
[ :from_unit, :to_unit ]
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_serializer_includes
|
19
|
+
{
|
20
|
+
index: [ :from_unit, :to_unit ],
|
21
|
+
show: [ :from_unit, :to_unit ],
|
22
|
+
create: [ :from_unit, :to_unit ],
|
23
|
+
update: [ :from_unit, :to_unit ]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class UnitsController < ApplicationController
|
4
|
+
include Dscf::Core::Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:unit).permit(:code, :name, :unit_type)
|
10
|
+
end
|
11
|
+
|
12
|
+
def eager_loaded_associations
|
13
|
+
[ :unit_conversions ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_serializer_includes
|
17
|
+
{
|
18
|
+
index: [ :unit_conversions ],
|
19
|
+
show: [ :unit_conversions ],
|
20
|
+
create: [],
|
21
|
+
update: []
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -23,6 +23,12 @@ module Dscf::Marketplace
|
|
23
23
|
%w[id driver_id pickup_address_id delivery_vehicle_id status vehicle_type estimated_delivery_price actual_delivery_price estimated_delivery_time actual_delivery_time delivery_notes created_at updated_at]
|
24
24
|
end
|
25
25
|
|
26
|
+
# Override ransack to handle JSON fields
|
27
|
+
def self.ransack(params = {}, options = {})
|
28
|
+
params ||= {}
|
29
|
+
super(params.except("optimized_route"), options)
|
30
|
+
end
|
31
|
+
|
26
32
|
def self.ransackable_associations(_auth_object = nil)
|
27
33
|
%w[driver pickup_address delivery_vehicle delivery_order_items marketplace_orders]
|
28
34
|
end
|
@@ -13,13 +13,10 @@ module Dscf
|
|
13
13
|
validates :unit_id, presence: true
|
14
14
|
validates :unit_price, numericality: {greater_than: 0}, allow_nil: true
|
15
15
|
validates :subtotal, numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
16
|
-
|
17
16
|
validate :product_matches_rfq_item
|
18
17
|
validate :unit_compatible_with_product
|
19
|
-
before_save :calculate_subtotal, if: :unit_price_changed?
|
20
|
-
|
21
|
-
# Only validate subtotal calculation if both unit_price and quantity are present
|
22
18
|
validate :subtotal_matches_calculation, if: :should_validate_subtotal?
|
19
|
+
before_save :calculate_subtotal, if: :should_recalculate_subtotal?
|
23
20
|
|
24
21
|
scope :priced, -> { where.not(unit_price: nil) }
|
25
22
|
scope :unpriced, -> { where(unit_price: nil) }
|
@@ -76,8 +73,7 @@ module Dscf
|
|
76
73
|
def matches_rfq_request?
|
77
74
|
return false unless rfq_item
|
78
75
|
|
79
|
-
product_id == rfq_item.product_id &&
|
80
|
-
unit_id == rfq_item.unit_id
|
76
|
+
product_id == rfq_item.product_id && unit_id == rfq_item.unit_id
|
81
77
|
end
|
82
78
|
|
83
79
|
def can_create_order?
|
@@ -89,8 +85,35 @@ module Dscf
|
|
89
85
|
def calculate_subtotal
|
90
86
|
return unless unit_price && quantity
|
91
87
|
|
92
|
-
self.subtotal = unit_price * quantity
|
88
|
+
self.subtotal = (unit_price * quantity).round(2)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Calculate subtotal automatically if not set
|
92
|
+
def calculated_subtotal
|
93
|
+
return subtotal if subtotal.present?
|
94
|
+
return nil unless unit_price && quantity
|
95
|
+
|
96
|
+
(unit_price * quantity).round(2)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Override subtotal setter to allow validation to work
|
100
|
+
def subtotal=(value)
|
101
|
+
# Allow any value to be set for validation purposes
|
102
|
+
super
|
93
103
|
end
|
104
|
+
public :subtotal=
|
105
|
+
|
106
|
+
# Override subtotal getter to calculate if not set
|
107
|
+
def subtotal
|
108
|
+
stored_value = super
|
109
|
+
# If we have a stored value (including 0), return it
|
110
|
+
# Only calculate if it's nil and we have the required fields
|
111
|
+
return stored_value unless stored_value.nil?
|
112
|
+
return nil unless unit_price && quantity
|
113
|
+
|
114
|
+
(unit_price * quantity).round(2)
|
115
|
+
end
|
116
|
+
public :subtotal
|
94
117
|
|
95
118
|
def product_matches_rfq_item
|
96
119
|
return unless rfq_item_id && product_id
|
@@ -111,14 +134,23 @@ module Dscf
|
|
111
134
|
def subtotal_matches_calculation
|
112
135
|
return unless should_validate_subtotal?
|
113
136
|
|
114
|
-
|
115
|
-
|
137
|
+
# Calculate what the subtotal should be based on current unit_price and quantity
|
138
|
+
expected_subtotal = (unit_price * quantity).round(2)
|
139
|
+
|
140
|
+
# If subtotal is stored and doesn't match, that's an error
|
141
|
+
# If subtotal is nil, we'll let the before_save callback handle it
|
142
|
+
if subtotal.present? && subtotal.round(2) != expected_subtotal
|
116
143
|
errors.add(:subtotal, "must equal unit_price * quantity")
|
117
144
|
end
|
118
145
|
end
|
119
146
|
|
120
147
|
def should_validate_subtotal?
|
121
|
-
|
148
|
+
# Only validate if subtotal is explicitly set and we have unit_price and quantity
|
149
|
+
unit_price.present? && quantity.present? && subtotal.present? && subtotal_changed?
|
150
|
+
end
|
151
|
+
|
152
|
+
def should_recalculate_subtotal?
|
153
|
+
unit_price_changed? || quantity_changed?
|
122
154
|
end
|
123
155
|
end
|
124
156
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class BusinessSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :name, :description, :contact_email, :contact_phone,
|
5
|
+
:tin_number, :created_at, :updated_at
|
6
|
+
|
7
|
+
belongs_to :business_type
|
8
|
+
belongs_to :user
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryOrderItemSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :delivery_order_id, :order_item_id, :pickup_address_id, :dropoff_address_id,
|
5
|
+
:quantity, :status, :pickup_verified_quantity, :dropoff_verified_quantity,
|
6
|
+
:damaged_quantity, :missing_quantity, :receiver_confirmed_by,
|
7
|
+
:receiver_confirmed_at, :receiver_notes, :handoff_checklist_completed,
|
8
|
+
:created_at, :updated_at, :product_name, :unit_name, :verification_complete?,
|
9
|
+
:has_discrepancy?, :discrepancy_amount, :requires_resolution?
|
10
|
+
|
11
|
+
belongs_to :delivery_order
|
12
|
+
belongs_to :order_item
|
13
|
+
belongs_to :pickup_address
|
14
|
+
belongs_to :dropoff_address
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryOrderSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :driver_id, :pickup_address_id, :delivery_vehicle_id, :status,
|
5
|
+
:vehicle_type, :estimated_delivery_price, :actual_delivery_price,
|
6
|
+
:estimated_delivery_time, :actual_delivery_time, :delivery_notes,
|
7
|
+
:created_at, :updated_at, :total_items, :total_orders, :delivery_duration,
|
8
|
+
:on_time?, :all_handoffs_confirmed?
|
9
|
+
|
10
|
+
belongs_to :driver
|
11
|
+
belongs_to :pickup_address
|
12
|
+
belongs_to :delivery_vehicle
|
13
|
+
has_many :delivery_order_items
|
14
|
+
has_many :marketplace_orders
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class DeliveryVehicleSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :driver_id, :plate_number, :vehicle_type, :year, :brand,
|
5
|
+
:model, :color, :created_at, :updated_at, :display_name,
|
6
|
+
:total_deliveries, :success_rate
|
7
|
+
|
8
|
+
belongs_to :driver
|
9
|
+
has_many :delivery_orders
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class OrderItemSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :order_id, :quotation_item_id, :listing_id,
|
5
|
+
:product_id, :unit_id, :quantity, :unit_price,
|
6
|
+
:status, :created_at, :updated_at,
|
7
|
+
:subtotal, :product_name, :unit_name
|
8
|
+
|
9
|
+
belongs_to :order
|
10
|
+
belongs_to :quotation_item
|
11
|
+
belongs_to :listing
|
12
|
+
belongs_to :product
|
13
|
+
belongs_to :unit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class QuotationItemSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :quotation_id, :rfq_item_id, :product_id, :unit_id, :quantity,
|
5
|
+
:unit_price, :subtotal, :created_at, :updated_at, :product_name,
|
6
|
+
:product_sku, :unit_name, :unit_code, :rfq_requested_quantity,
|
7
|
+
:quantity_difference, :quantity_difference_percentage, :price_per_base_unit,
|
8
|
+
:matches_rfq_request?, :can_create_order?
|
9
|
+
|
10
|
+
belongs_to :quotation
|
11
|
+
belongs_to :rfq_item
|
12
|
+
belongs_to :product
|
13
|
+
belongs_to :unit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class RfqItemSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :request_for_quotation_id, :product_id, :unit_id, :quantity, :notes,
|
5
|
+
:created_at, :updated_at, :product_name, :product_sku, :unit_name,
|
6
|
+
:unit_code, :quotation_count, :has_quotations?, :quoted_price_range
|
7
|
+
|
8
|
+
belongs_to :request_for_quotation
|
9
|
+
belongs_to :product
|
10
|
+
belongs_to :unit
|
11
|
+
has_many :quotation_items
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class SupplierProductSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :business_id, :product_id, :supplier_price, :available_quantity,
|
5
|
+
:minimum_order_quantity, :status, :created_at, :updated_at,
|
6
|
+
:in_stock?, :price_per_unit, :display_name
|
7
|
+
|
8
|
+
belongs_to :business
|
9
|
+
belongs_to :product
|
10
|
+
has_many :listings
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Dscf
|
2
|
+
module Marketplace
|
3
|
+
class UnitConversionSerializer < ActiveModel::Serializer
|
4
|
+
attributes :id, :from_unit_id, :to_unit_id, :conversion_factor, :notes,
|
5
|
+
:created_at, :updated_at, :reverse_conversion_factor, :description
|
6
|
+
|
7
|
+
belongs_to :from_unit
|
8
|
+
belongs_to :to_unit
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/config/locales/en.yml
CHANGED
@@ -241,6 +241,18 @@ en:
|
|
241
241
|
update: "Failed to update delivery vehicle"
|
242
242
|
destroy: "Failed to delete delivery vehicle"
|
243
243
|
|
244
|
+
# Authentication
|
245
|
+
auth:
|
246
|
+
success:
|
247
|
+
otp_sent: "OTP sent successfully"
|
248
|
+
errors:
|
249
|
+
invalid_fin: "Invalid FIN number"
|
250
|
+
|
251
|
+
# Business
|
252
|
+
business:
|
253
|
+
success:
|
254
|
+
has_business_check: "Business check completed successfully"
|
255
|
+
|
244
256
|
# Global fallback messages
|
245
257
|
operations:
|
246
258
|
success:
|
data/config/routes.rb
CHANGED
@@ -16,6 +16,12 @@ Dscf::Marketplace::Engine.routes.draw do
|
|
16
16
|
|
17
17
|
resources :unit_conversions
|
18
18
|
|
19
|
+
resources :businesses do
|
20
|
+
collection do
|
21
|
+
get "has_business"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
19
25
|
# Trading Models
|
20
26
|
resources :supplier_products do
|
21
27
|
resources :listings, only: [ :index ]
|
@@ -39,7 +45,7 @@ Dscf::Marketplace::Engine.routes.draw do
|
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
42
|
-
resources :rfq_items, only: [ :show, :update, :destroy ]
|
48
|
+
resources :rfq_items, only: [ :index, :show, :update, :create, :destroy ]
|
43
49
|
|
44
50
|
resources :quotations do
|
45
51
|
resources :quotation_items, only: [ :index, :create ]
|
@@ -50,7 +56,7 @@ Dscf::Marketplace::Engine.routes.draw do
|
|
50
56
|
end
|
51
57
|
end
|
52
58
|
|
53
|
-
resources :quotation_items, only: [ :show, :update, :destroy ]
|
59
|
+
resources :quotation_items, only: [ :index, :show, :update, :create, :destroy ]
|
54
60
|
|
55
61
|
# Order Management
|
56
62
|
resources :orders do
|
@@ -62,7 +68,7 @@ Dscf::Marketplace::Engine.routes.draw do
|
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
65
|
-
resources :order_items, only: [ :show, :update ]
|
71
|
+
resources :order_items, only: [ :index, :show, :update, :create, :destroy ]
|
66
72
|
|
67
73
|
# Delivery System
|
68
74
|
resources :delivery_orders do
|
@@ -75,7 +81,7 @@ Dscf::Marketplace::Engine.routes.draw do
|
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
78
|
-
resources :delivery_order_items, only: [ :show, :update ] do
|
84
|
+
resources :delivery_order_items, only: [ :index, :show, :update, :create ] do
|
79
85
|
member do
|
80
86
|
post "receiver_confirm"
|
81
87
|
post "report_issue"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
FactoryBot.define do
|
2
2
|
factory :dscf_marketplace_delivery_order_item, class: "Dscf::Marketplace::DeliveryOrderItem" do
|
3
3
|
association :delivery_order, factory: :dscf_marketplace_delivery_order
|
4
|
-
association :order_item, factory: :dscf_marketplace_order_item
|
4
|
+
association :order_item, factory: [ :dscf_marketplace_order_item, :from_listing ]
|
5
5
|
pickup_address { create(:dscf_core_address) }
|
6
6
|
dropoff_address { create(:dscf_core_address) }
|
7
7
|
quantity { 10.0 }
|
@@ -10,8 +10,8 @@ FactoryBot.define do
|
|
10
10
|
|
11
11
|
after(:build) do |item|
|
12
12
|
# Only calculate subtotal if it's not explicitly set
|
13
|
-
if item
|
14
|
-
item.subtotal = item.unit_price * item.quantity
|
13
|
+
if item[:subtotal].nil? && item.unit_price && item.quantity
|
14
|
+
item.subtotal = (item.unit_price * item.quantity).round(2)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
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.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Asrat
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-09-
|
10
|
+
date: 2025-09-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rails
|
@@ -417,12 +417,22 @@ files:
|
|
417
417
|
- MIT-LICENSE
|
418
418
|
- Rakefile
|
419
419
|
- app/controllers/dscf/marketplace/application_controller.rb
|
420
|
+
- app/controllers/dscf/marketplace/businesses_controller.rb
|
420
421
|
- app/controllers/dscf/marketplace/categories_controller.rb
|
422
|
+
- app/controllers/dscf/marketplace/delivery_order_items_controller.rb
|
423
|
+
- app/controllers/dscf/marketplace/delivery_orders_controller.rb
|
424
|
+
- app/controllers/dscf/marketplace/delivery_vehicles_controller.rb
|
421
425
|
- app/controllers/dscf/marketplace/listings_controller.rb
|
426
|
+
- app/controllers/dscf/marketplace/order_items_controller.rb
|
422
427
|
- app/controllers/dscf/marketplace/orders_controller.rb
|
423
428
|
- app/controllers/dscf/marketplace/products_controller.rb
|
429
|
+
- app/controllers/dscf/marketplace/quotation_items_controller.rb
|
424
430
|
- app/controllers/dscf/marketplace/quotations_controller.rb
|
425
431
|
- app/controllers/dscf/marketplace/request_for_quotations_controller.rb
|
432
|
+
- app/controllers/dscf/marketplace/rfq_items_controller.rb
|
433
|
+
- app/controllers/dscf/marketplace/supplier_products_controller.rb
|
434
|
+
- app/controllers/dscf/marketplace/unit_conversions_controller.rb
|
435
|
+
- app/controllers/dscf/marketplace/units_controller.rb
|
426
436
|
- app/jobs/dscf/marketplace/application_job.rb
|
427
437
|
- app/mailers/dscf/marketplace/application_mailer.rb
|
428
438
|
- app/models/dscf/marketplace/application_record.rb
|
@@ -441,12 +451,22 @@ files:
|
|
441
451
|
- app/models/dscf/marketplace/supplier_product.rb
|
442
452
|
- app/models/dscf/marketplace/unit.rb
|
443
453
|
- app/models/dscf/marketplace/unit_conversion.rb
|
454
|
+
- app/serializers/dscf/marketplace/business_serializer.rb
|
444
455
|
- app/serializers/dscf/marketplace/category_serializer.rb
|
456
|
+
- app/serializers/dscf/marketplace/delivery_order_item_serializer.rb
|
457
|
+
- app/serializers/dscf/marketplace/delivery_order_serializer.rb
|
458
|
+
- app/serializers/dscf/marketplace/delivery_vehicle_serializer.rb
|
445
459
|
- app/serializers/dscf/marketplace/listing_serializer.rb
|
460
|
+
- app/serializers/dscf/marketplace/order_item_serializer.rb
|
446
461
|
- app/serializers/dscf/marketplace/order_serializer.rb
|
447
462
|
- app/serializers/dscf/marketplace/product_serializer.rb
|
463
|
+
- app/serializers/dscf/marketplace/quotation_item_serializer.rb
|
448
464
|
- app/serializers/dscf/marketplace/quotation_serializer.rb
|
449
465
|
- app/serializers/dscf/marketplace/request_for_quotation_serializer.rb
|
466
|
+
- app/serializers/dscf/marketplace/rfq_item_serializer.rb
|
467
|
+
- app/serializers/dscf/marketplace/supplier_product_serializer.rb
|
468
|
+
- app/serializers/dscf/marketplace/unit_conversion_serializer.rb
|
469
|
+
- app/serializers/dscf/marketplace/unit_serializer.rb
|
450
470
|
- config/locales/en.yml
|
451
471
|
- config/routes.rb
|
452
472
|
- db/migrate/20250827172043_create_dscf_marketplace_categories.rb
|