dscf-marketplace 0.7.0 → 0.7.2
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/application_controller.rb +1 -3
- data/app/controllers/dscf/marketplace/delivery_order_items_controller.rb +3 -0
- data/app/controllers/dscf/marketplace/delivery_orders_controller.rb +10 -0
- data/app/controllers/dscf/marketplace/delivery_stops_controller.rb +1 -0
- data/app/controllers/dscf/marketplace/delivery_vehicles_controller.rb +2 -0
- data/app/controllers/dscf/marketplace/listings_controller.rb +5 -0
- data/app/controllers/dscf/marketplace/orders_controller.rb +5 -0
- data/app/controllers/dscf/marketplace/products_controller.rb +1 -0
- data/app/controllers/dscf/marketplace/quotations_controller.rb +5 -0
- data/app/controllers/dscf/marketplace/request_for_quotations_controller.rb +6 -0
- data/app/controllers/dscf/marketplace/supplier_products_controller.rb +1 -0
- data/app/policies/dscf/marketplace/category_policy.rb +6 -0
- data/app/policies/dscf/marketplace/delivery_order_item_policy.rb +17 -0
- data/app/policies/dscf/marketplace/delivery_order_policy.rb +41 -0
- data/app/policies/dscf/marketplace/delivery_stop_policy.rb +9 -0
- data/app/policies/dscf/marketplace/delivery_vehicle_policy.rb +6 -0
- data/app/policies/dscf/marketplace/listing_policy.rb +25 -0
- data/app/policies/dscf/marketplace/location_policy.rb +9 -0
- data/app/policies/dscf/marketplace/order_item_policy.rb +6 -0
- data/app/policies/dscf/marketplace/order_policy.rb +25 -0
- data/app/policies/dscf/marketplace/product_policy.rb +13 -0
- data/app/policies/dscf/marketplace/quotation_item_policy.rb +6 -0
- data/app/policies/dscf/marketplace/quotation_policy.rb +25 -0
- data/app/policies/dscf/marketplace/request_for_quotation_policy.rb +25 -0
- data/app/policies/dscf/marketplace/rfq_item_policy.rb +6 -0
- data/app/policies/dscf/marketplace/supplier_product_policy.rb +9 -0
- data/app/policies/dscf/marketplace/unit_conversion_policy.rb +6 -0
- data/app/policies/dscf/marketplace/unit_policy.rb +6 -0
- data/db/migrate/20260310120000_add_active_and_description_to_dscf_core_roles.rb +8 -0
- data/db/migrate/20260310122000_add_missing_fields_to_dscf_core_user_roles.rb +10 -0
- data/db/seeds.rb +34 -339
- data/lib/dscf/marketplace/version.rb +1 -1
- metadata +20 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 81c4fc2b3cbb08308f4da22f26a56d9d7a3ca197325c340d491dacfe4adbaa6f
|
|
4
|
+
data.tar.gz: 1c89213f1171138ea6efc0c8566a60a6937348c7c934cfacc8ccecd53f35c310
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f812ce7f37138fbf88cfed6c03233193b12fef8a194f8cd632c8006b86814201af5877122679c9634920bcb4ba73291e7ea2171009be15265a38cd9dad524c5
|
|
7
|
+
data.tar.gz: e6ffd5232a4f43d7d4020f789a0ce6b400858ffd2801192a7008dab0ffd4f66f3dcd3488c0364f26d8861c2b451eb2d6f1f2edcfbd9b990363cd121b6905a3b6
|
|
@@ -5,6 +5,7 @@ module Dscf
|
|
|
5
5
|
|
|
6
6
|
def receiver_confirm
|
|
7
7
|
@obj = find_record
|
|
8
|
+
authorize @obj, :receiver_confirm?
|
|
8
9
|
if @obj.receiver_confirm!(params[:confirmed_quantity], params[:notes], current_user&.id)
|
|
9
10
|
render_success("delivery_order_items.success.receiver_confirmed", data: @obj)
|
|
10
11
|
else
|
|
@@ -14,6 +15,7 @@ module Dscf
|
|
|
14
15
|
|
|
15
16
|
def report_issue
|
|
16
17
|
@obj = find_record
|
|
18
|
+
authorize @obj, :report_issue?
|
|
17
19
|
issue_type = params[:issue_type]
|
|
18
20
|
quantity = params[:quantity]
|
|
19
21
|
description = params[:description]
|
|
@@ -27,6 +29,7 @@ module Dscf
|
|
|
27
29
|
|
|
28
30
|
def dispute_delivery
|
|
29
31
|
@obj = find_record
|
|
32
|
+
authorize @obj, :dispute_delivery?
|
|
30
33
|
reason = params[:reason]
|
|
31
34
|
|
|
32
35
|
if @obj.dispute_delivery!(reason, current_user&.id)
|
|
@@ -4,6 +4,7 @@ module Dscf
|
|
|
4
4
|
include Dscf::Core::Common
|
|
5
5
|
|
|
6
6
|
def index
|
|
7
|
+
authorize @clazz.new, :index?
|
|
7
8
|
# Custom implementation to avoid JSON field issues
|
|
8
9
|
delivery_orders = @clazz.all
|
|
9
10
|
|
|
@@ -46,6 +47,7 @@ module Dscf
|
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def filter
|
|
50
|
+
authorize @clazz.new, :filter?
|
|
49
51
|
delivery_orders = @clazz.all
|
|
50
52
|
|
|
51
53
|
# Apply Ransack filtering if q params present
|
|
@@ -70,11 +72,13 @@ module Dscf
|
|
|
70
72
|
|
|
71
73
|
def summary
|
|
72
74
|
@delivery_order = find_record
|
|
75
|
+
authorize @delivery_order, :summary?
|
|
73
76
|
render_success(data: @delivery_order.generate_handoff_summary_report)
|
|
74
77
|
end
|
|
75
78
|
|
|
76
79
|
def pickup
|
|
77
80
|
@obj = find_record
|
|
81
|
+
authorize @obj, :pickup?
|
|
78
82
|
if @obj.pickup!
|
|
79
83
|
render_success("delivery_orders.success.picked_up", data: @obj)
|
|
80
84
|
else
|
|
@@ -84,6 +88,7 @@ module Dscf
|
|
|
84
88
|
|
|
85
89
|
def start_delivery
|
|
86
90
|
@obj = find_record
|
|
91
|
+
authorize @obj, :start_delivery?
|
|
87
92
|
if @obj.start_delivery!
|
|
88
93
|
render_success("delivery_orders.success.delivery_started", data: @obj)
|
|
89
94
|
else
|
|
@@ -93,6 +98,7 @@ module Dscf
|
|
|
93
98
|
|
|
94
99
|
def complete_delivery
|
|
95
100
|
@obj = find_record
|
|
101
|
+
authorize @obj, :complete_delivery?
|
|
96
102
|
if @obj.complete_delivery!
|
|
97
103
|
render_success("delivery_orders.success.delivery_completed", data: @obj)
|
|
98
104
|
else
|
|
@@ -102,6 +108,7 @@ module Dscf
|
|
|
102
108
|
|
|
103
109
|
def mark_failed
|
|
104
110
|
@obj = find_record
|
|
111
|
+
authorize @obj, :mark_failed?
|
|
105
112
|
reason = params[:reason]
|
|
106
113
|
if @obj.mark_failed!(reason)
|
|
107
114
|
render_success("delivery_orders.success.marked_failed", data: @obj)
|
|
@@ -112,6 +119,7 @@ module Dscf
|
|
|
112
119
|
|
|
113
120
|
def accept
|
|
114
121
|
@obj = find_record
|
|
122
|
+
authorize @obj, :accept?
|
|
115
123
|
service = Dscf::Marketplace::DeliveryOrderService.new
|
|
116
124
|
begin
|
|
117
125
|
service.assign_driver(@obj, current_user)
|
|
@@ -126,6 +134,7 @@ module Dscf
|
|
|
126
134
|
end
|
|
127
135
|
|
|
128
136
|
def convert_orders
|
|
137
|
+
authorize @clazz.new, :convert_orders?
|
|
129
138
|
order_ids = params[:order_ids]
|
|
130
139
|
vehicle_type = params[:vehicle_type]
|
|
131
140
|
pickup_address_id = params[:pickup_address_id]
|
|
@@ -165,6 +174,7 @@ module Dscf
|
|
|
165
174
|
end
|
|
166
175
|
|
|
167
176
|
def my_driver_deliveries
|
|
177
|
+
authorize @clazz.new, :my_driver_deliveries?
|
|
168
178
|
# Verify user has driver role
|
|
169
179
|
unless Dscf::Marketplace::RoleService.user_has_driver_role?(current_user)
|
|
170
180
|
render_error("delivery_orders.errors.access_denied", message: "Only drivers can access this endpoint")
|
|
@@ -4,6 +4,7 @@ module Dscf
|
|
|
4
4
|
include Dscf::Core::Common
|
|
5
5
|
|
|
6
6
|
def create
|
|
7
|
+
authorize @clazz.new, :create?
|
|
7
8
|
vehicle = @clazz.new(model_params.except(:vehicle_license, :driver_license))
|
|
8
9
|
if vehicle.save
|
|
9
10
|
# Auto-assign Driver role to the vehicle's driver
|
|
@@ -42,6 +43,7 @@ module Dscf
|
|
|
42
43
|
|
|
43
44
|
def update
|
|
44
45
|
vehicle = @clazz.find(params[:id])
|
|
46
|
+
authorize vehicle, :update?
|
|
45
47
|
if vehicle.update(model_params.except(:vehicle_license, :driver_license))
|
|
46
48
|
# Handle vehicle license update/replacement
|
|
47
49
|
if params[:delivery_vehicle][:vehicle_license].present?
|
|
@@ -5,6 +5,7 @@ module Dscf
|
|
|
5
5
|
|
|
6
6
|
def activate
|
|
7
7
|
@obj = find_record
|
|
8
|
+
authorize @obj, :activate?
|
|
8
9
|
if @obj.update(status: :active)
|
|
9
10
|
render_success("listings.success.activated", data: @obj)
|
|
10
11
|
else
|
|
@@ -14,6 +15,7 @@ module Dscf
|
|
|
14
15
|
|
|
15
16
|
def pause
|
|
16
17
|
@obj = find_record
|
|
18
|
+
authorize @obj, :pause?
|
|
17
19
|
if @obj.update(status: :paused)
|
|
18
20
|
render_success("listings.success.paused", data: @obj)
|
|
19
21
|
else
|
|
@@ -23,6 +25,7 @@ module Dscf
|
|
|
23
25
|
|
|
24
26
|
def sold_out
|
|
25
27
|
@obj = find_record
|
|
28
|
+
authorize @obj, :sold_out?
|
|
26
29
|
if @obj.update(status: :sold_out)
|
|
27
30
|
render_success("listings.success.sold_out", data: @obj)
|
|
28
31
|
else
|
|
@@ -31,6 +34,7 @@ module Dscf
|
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
def my_listings
|
|
37
|
+
authorize @clazz.new, :my_listings?
|
|
34
38
|
service = MyResourceService.new(current_user)
|
|
35
39
|
listings = service.my_listings(params)
|
|
36
40
|
|
|
@@ -43,6 +47,7 @@ module Dscf
|
|
|
43
47
|
end
|
|
44
48
|
|
|
45
49
|
def listings_by_supplier
|
|
50
|
+
authorize @clazz.new, :listings_by_supplier?
|
|
46
51
|
supplier_id = params[:supplier_id]
|
|
47
52
|
|
|
48
53
|
# Validate supplier exists
|
|
@@ -4,6 +4,7 @@ module Dscf
|
|
|
4
4
|
include Dscf::Core::Common
|
|
5
5
|
|
|
6
6
|
def filter
|
|
7
|
+
authorize @clazz.new, :filter?
|
|
7
8
|
orders = @clazz.all
|
|
8
9
|
|
|
9
10
|
# Apply Ransack filtering if q params present
|
|
@@ -24,6 +25,7 @@ module Dscf
|
|
|
24
25
|
|
|
25
26
|
def confirm
|
|
26
27
|
@obj = find_record
|
|
28
|
+
authorize @obj, :confirm?
|
|
27
29
|
if @obj.confirm!
|
|
28
30
|
render_success("orders.success.confirmed", data: @obj)
|
|
29
31
|
else
|
|
@@ -33,6 +35,7 @@ module Dscf
|
|
|
33
35
|
|
|
34
36
|
def cancel
|
|
35
37
|
@obj = find_record
|
|
38
|
+
authorize @obj, :cancel?
|
|
36
39
|
if @obj.update(status: :cancelled)
|
|
37
40
|
@obj.order_items.update_all(status: OrderItem.statuses[:cancelled])
|
|
38
41
|
render_success("orders.success.cancelled", data: @obj)
|
|
@@ -43,6 +46,7 @@ module Dscf
|
|
|
43
46
|
|
|
44
47
|
def complete
|
|
45
48
|
@obj = find_record
|
|
49
|
+
authorize @obj, :complete?
|
|
46
50
|
if @obj.can_be_completed? && @obj.update(status: :completed)
|
|
47
51
|
@obj.order_items.update_all(status: OrderItem.statuses[:completed])
|
|
48
52
|
render_success("orders.success.completed", data: @obj)
|
|
@@ -52,6 +56,7 @@ module Dscf
|
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
def my_orders
|
|
59
|
+
authorize @clazz.new, :my_orders?
|
|
55
60
|
service = MyResourceService.new(current_user)
|
|
56
61
|
orders = service.my_orders(params)
|
|
57
62
|
|
|
@@ -4,6 +4,7 @@ module Dscf
|
|
|
4
4
|
include Dscf::Core::Common
|
|
5
5
|
|
|
6
6
|
def filter
|
|
7
|
+
authorize @clazz.new, :filter?
|
|
7
8
|
quotations = @clazz.all
|
|
8
9
|
|
|
9
10
|
# Apply Ransack filtering if q params present
|
|
@@ -24,6 +25,7 @@ module Dscf
|
|
|
24
25
|
|
|
25
26
|
def accept
|
|
26
27
|
@obj = find_record
|
|
28
|
+
authorize @obj, :accept?
|
|
27
29
|
|
|
28
30
|
fulfillment_type = params[:fulfillment_type]
|
|
29
31
|
dropoff_address_id = params[:dropoff_address_id]
|
|
@@ -57,6 +59,7 @@ module Dscf
|
|
|
57
59
|
|
|
58
60
|
def reject
|
|
59
61
|
@obj = find_record
|
|
62
|
+
authorize @obj, :reject?
|
|
60
63
|
if @obj.reject!
|
|
61
64
|
render_success("quotations.success.rejected", data: @obj)
|
|
62
65
|
else
|
|
@@ -66,6 +69,7 @@ module Dscf
|
|
|
66
69
|
|
|
67
70
|
def send_quotation
|
|
68
71
|
@obj = find_record
|
|
72
|
+
authorize @obj, :send_quotation?
|
|
69
73
|
if @obj.send_quotation!
|
|
70
74
|
render_success("quotations.success.sent", data: @obj)
|
|
71
75
|
else
|
|
@@ -74,6 +78,7 @@ module Dscf
|
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
def my_quotes
|
|
81
|
+
authorize @clazz.new, :my_quotes?
|
|
77
82
|
service = MyResourceService.new(current_user)
|
|
78
83
|
quotes = service.my_quotes(params)
|
|
79
84
|
|
|
@@ -4,6 +4,7 @@ module Dscf
|
|
|
4
4
|
include Dscf::Core::Common
|
|
5
5
|
|
|
6
6
|
def filter
|
|
7
|
+
authorize @clazz.new, :filter?
|
|
7
8
|
rfqs = @clazz.all
|
|
8
9
|
|
|
9
10
|
# Apply Ransack filtering if q params present
|
|
@@ -23,6 +24,7 @@ module Dscf
|
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def create
|
|
27
|
+
authorize @clazz.new, :create?
|
|
26
28
|
obj = @clazz.new(model_params)
|
|
27
29
|
if obj.save
|
|
28
30
|
obj = @clazz.includes(eager_loaded_associations).find(obj.id) if eager_loaded_associations.present?
|
|
@@ -41,6 +43,7 @@ module Dscf
|
|
|
41
43
|
|
|
42
44
|
def send_rfq
|
|
43
45
|
@obj = find_record
|
|
46
|
+
authorize @obj, :send_rfq?
|
|
44
47
|
if @obj.draft? && @obj.update(status: :sent)
|
|
45
48
|
render_success("request_for_quotations.success.sent", data: @obj)
|
|
46
49
|
else
|
|
@@ -50,6 +53,7 @@ module Dscf
|
|
|
50
53
|
|
|
51
54
|
def close
|
|
52
55
|
@obj = find_record
|
|
56
|
+
authorize @obj, :close?
|
|
53
57
|
if (@obj.sent? || @obj.responded?) && @obj.update(status: :closed)
|
|
54
58
|
render_success("request_for_quotations.success.closed", data: @obj)
|
|
55
59
|
else
|
|
@@ -58,6 +62,7 @@ module Dscf
|
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
def my_rfqs
|
|
65
|
+
authorize @clazz.new, :my_rfqs?
|
|
61
66
|
service = MyResourceService.new(current_user)
|
|
62
67
|
rfqs = service.my_rfqs(params)
|
|
63
68
|
|
|
@@ -71,6 +76,7 @@ module Dscf
|
|
|
71
76
|
|
|
72
77
|
def respond
|
|
73
78
|
@rfq = Dscf::Marketplace::RequestForQuotation.find(params[:id])
|
|
79
|
+
authorize @rfq, :respond?
|
|
74
80
|
service = RfqResponseService.new(current_user)
|
|
75
81
|
result = service.respond_to_rfq(@rfq, params.permit(:notes, :valid_until, :delivery_date, quotation_items_attributes: [ :rfq_item_id, :unit_id, :quantity, :unit_price, :notes ]))
|
|
76
82
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class DeliveryOrderItemPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def receiver_confirm?
|
|
5
|
+
user.has_permission?("delivery_order_items.receiver_confirm")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def report_issue?
|
|
9
|
+
user.has_permission?("delivery_order_items.report_issue")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def dispute_delivery?
|
|
13
|
+
user.has_permission?("delivery_order_items.dispute_delivery")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class DeliveryOrderPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def filter?
|
|
5
|
+
user.has_permission?("delivery_orders.filter")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def summary?
|
|
9
|
+
user.has_permission?("delivery_orders.summary")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def pickup?
|
|
13
|
+
user.has_permission?("delivery_orders.pickup")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start_delivery?
|
|
17
|
+
user.has_permission?("delivery_orders.start_delivery")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def complete_delivery?
|
|
21
|
+
user.has_permission?("delivery_orders.complete_delivery")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def mark_failed?
|
|
25
|
+
user.has_permission?("delivery_orders.mark_failed")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def accept?
|
|
29
|
+
user.has_permission?("delivery_orders.accept")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def convert_orders?
|
|
33
|
+
user.has_permission?("delivery_orders.convert_orders")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def my_driver_deliveries?
|
|
37
|
+
user.has_permission?("delivery_orders.my_driver_deliveries")
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class ListingPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def activate?
|
|
5
|
+
user.has_permission?("listings.activate")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def pause?
|
|
9
|
+
user.has_permission?("listings.pause")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def sold_out?
|
|
13
|
+
user.has_permission?("listings.sold_out")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def my_listings?
|
|
17
|
+
user.has_permission?("listings.my_listings")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def listings_by_supplier?
|
|
21
|
+
user.has_permission?("listings.listings_by_supplier")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class OrderPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def filter?
|
|
5
|
+
user.has_permission?("orders.filter")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def confirm?
|
|
9
|
+
user.has_permission?("orders.confirm")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cancel?
|
|
13
|
+
user.has_permission?("orders.cancel")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def complete?
|
|
17
|
+
user.has_permission?("orders.complete")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def my_orders?
|
|
21
|
+
user.has_permission?("orders.my_orders")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class ProductPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def filter?
|
|
5
|
+
user.has_permission?("products.filter")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def supplier_products?
|
|
9
|
+
user.has_permission?("products.supplier_products")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class QuotationPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def filter?
|
|
5
|
+
user.has_permission?("quotations.filter")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def accept?
|
|
9
|
+
user.has_permission?("quotations.accept")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def reject?
|
|
13
|
+
user.has_permission?("quotations.reject")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def send_quotation?
|
|
17
|
+
user.has_permission?("quotations.send_quotation")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def my_quotes?
|
|
21
|
+
user.has_permission?("quotations.my_quotes")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Dscf
|
|
2
|
+
module Marketplace
|
|
3
|
+
class RequestForQuotationPolicy < Dscf::Core::ApplicationPolicy
|
|
4
|
+
def filter?
|
|
5
|
+
user.has_permission?("request_for_quotations.filter")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def send_rfq?
|
|
9
|
+
user.has_permission?("request_for_quotations.send_rfq")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def close?
|
|
13
|
+
user.has_permission?("request_for_quotations.close")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def respond?
|
|
17
|
+
user.has_permission?("request_for_quotations.respond")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def my_rfqs?
|
|
21
|
+
user.has_permission?("request_for_quotations.my_rfqs")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class AddActiveAndDescriptionToDscfCoreRoles < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :dscf_core_roles, :description, :string, if_not_exists: true
|
|
4
|
+
add_column :dscf_core_roles, :active, :boolean, null: false, default: true, if_not_exists: true
|
|
5
|
+
|
|
6
|
+
add_index :dscf_core_roles, :active, if_not_exists: true
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class AddMissingFieldsToDscfCoreUserRoles < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :dscf_core_user_roles, :expires_at, :datetime, if_not_exists: true
|
|
4
|
+
add_index :dscf_core_user_roles, :expires_at, name: "expires_at_on_dc_ur_indx", if_not_exists: true
|
|
5
|
+
|
|
6
|
+
add_column :dscf_core_user_roles, :assigned_by_id, :bigint, if_not_exists: true
|
|
7
|
+
add_index :dscf_core_user_roles, :assigned_by_id, name: "assigned_by_on_dc_ur_indx", if_not_exists: true
|
|
8
|
+
add_foreign_key :dscf_core_user_roles, :dscf_core_users, column: :assigned_by_id, if_not_exists: true
|
|
9
|
+
end
|
|
10
|
+
end
|
data/db/seeds.rb
CHANGED
|
@@ -1,343 +1,38 @@
|
|
|
1
|
-
puts "
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# Categories
|
|
27
|
-
fruits_veg = Dscf::Marketplace::Category.create!(name: "Fruits & Vegetables")
|
|
28
|
-
dairy = Dscf::Marketplace::Category.create!(name: "Dairy Products")
|
|
29
|
-
Dscf::Marketplace::Category.create!(name: "Grains & Cereals")
|
|
30
|
-
Dscf::Marketplace::Category.create!(name: "Beverages")
|
|
31
|
-
|
|
32
|
-
puts "✅ Created #{Dscf::Marketplace::Unit.count} units and #{Dscf::Marketplace::Category.count} categories"
|
|
33
|
-
|
|
34
|
-
puts "👥 Creating users and personas..."
|
|
35
|
-
|
|
36
|
-
# Business Types
|
|
37
|
-
wholesale_type = Dscf::Core::BusinessType.find_or_create_by!(name: "Wholesale Distributor")
|
|
38
|
-
retail_type = Dscf::Core::BusinessType.find_or_create_by!(name: "Retail Store")
|
|
39
|
-
|
|
40
|
-
# Consumers
|
|
41
|
-
consumer1 = Dscf::Core::User.create!(
|
|
42
|
-
email: "abebe.consumer@example.com",
|
|
43
|
-
phone: "+251911123456"
|
|
44
|
-
)
|
|
45
|
-
consumer2 = Dscf::Core::User.create!(
|
|
46
|
-
email: "tigist.consumer@example.com",
|
|
47
|
-
phone: "+251922334567"
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
# Drivers
|
|
51
|
-
driver1 = Dscf::Core::User.create!(
|
|
52
|
-
email: "driver.ahmed@example.com",
|
|
53
|
-
phone: "+251933445678"
|
|
54
|
-
)
|
|
55
|
-
Dscf::Core::User.create!(
|
|
56
|
-
email: "driver.mariam@example.com",
|
|
57
|
-
phone: "+251944556789"
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
puts "✅ Created #{Dscf::Core::User.count} users (#{Dscf::Core::User.where("email LIKE ?", "%consumer%").count} consumers, #{Dscf::Core::User.where("email LIKE ?", "%driver%").count} drivers)"
|
|
61
|
-
|
|
62
|
-
puts "🏢 Creating businesses and linking to users..."
|
|
63
|
-
|
|
64
|
-
# Wholesalers
|
|
65
|
-
wholesale_user1 = Dscf::Core::User.create!(
|
|
66
|
-
email: "wholesale.addis@example.com",
|
|
67
|
-
phone: "+251955667890"
|
|
68
|
-
)
|
|
69
|
-
wholesaler1 = Dscf::Core::Business.create!(
|
|
70
|
-
name: "Addis Wholesale Distributors",
|
|
71
|
-
contact_email: "contact@addiswholesale.et",
|
|
72
|
-
contact_phone: "+251966778901",
|
|
73
|
-
tin_number: "1234567890",
|
|
74
|
-
business_type: wholesale_type,
|
|
75
|
-
user: wholesale_user1
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
wholesale_user2 = Dscf::Core::User.create!(
|
|
79
|
-
email: "wholesale.ethio@example.com",
|
|
80
|
-
phone: "+251977889012"
|
|
81
|
-
)
|
|
82
|
-
wholesaler2 = Dscf::Core::Business.create!(
|
|
83
|
-
name: "Ethio Agricultural Wholesale",
|
|
84
|
-
contact_email: "info@ethiowholesale.et",
|
|
85
|
-
contact_phone: "+251988990123",
|
|
86
|
-
tin_number: "0987654321",
|
|
87
|
-
business_type: wholesale_type,
|
|
88
|
-
user: wholesale_user2
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# Retailers
|
|
92
|
-
retail_user1 = Dscf::Core::User.create!(
|
|
93
|
-
email: "retail.meklit@example.com",
|
|
94
|
-
phone: "+251999001234"
|
|
95
|
-
)
|
|
96
|
-
Dscf::Core::Business.create!(
|
|
97
|
-
name: "Meklit Fresh Market",
|
|
98
|
-
contact_email: "meklit@freshmarket.et",
|
|
99
|
-
contact_phone: "+251910112345",
|
|
100
|
-
tin_number: "1122334455",
|
|
101
|
-
business_type: retail_type,
|
|
102
|
-
user: retail_user1
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
retail_user2 = Dscf::Core::User.create!(
|
|
106
|
-
email: "retail.bole@example.com",
|
|
107
|
-
phone: "+251921223456"
|
|
108
|
-
)
|
|
109
|
-
Dscf::Core::Business.create!(
|
|
110
|
-
name: "Bole Modern Supermarket",
|
|
111
|
-
contact_email: "info@bolesuper.et",
|
|
112
|
-
contact_phone: "+251932334567",
|
|
113
|
-
tin_number: "5566778899",
|
|
114
|
-
business_type: retail_type,
|
|
115
|
-
user: retail_user2
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
puts "✅ Created #{Dscf::Core::Business.count} businesses (#{Dscf::Core::Business.joins(:user).where("dscf_core_users.email LIKE ?", "%wholesale%").count} wholesalers, #{Dscf::Core::Business.joins(:user).where("dscf_core_users.email LIKE ?", "%retail%").count} retailers)"
|
|
119
|
-
|
|
120
|
-
puts "📦 Creating products and supplier listings..."
|
|
121
|
-
|
|
122
|
-
# Products from wholesalers
|
|
123
|
-
banana_product = wholesaler1.supplier_products.create!(
|
|
124
|
-
product: Dscf::Marketplace::Product.create!(
|
|
125
|
-
name: "Fresh Bananas",
|
|
126
|
-
category: fruits_veg,
|
|
127
|
-
unit: kg
|
|
128
|
-
)
|
|
129
|
-
)
|
|
130
|
-
banana_listing = Dscf::Marketplace::Listing.create!(
|
|
131
|
-
supplier_product: banana_product,
|
|
132
|
-
price: 25.00,
|
|
133
|
-
quantity: 1000,
|
|
134
|
-
status: :active
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
milk_product = wholesaler2.supplier_products.create!(
|
|
138
|
-
product: Dscf::Marketplace::Product.create!(
|
|
139
|
-
name: "Fresh Cow Milk",
|
|
140
|
-
category: dairy,
|
|
141
|
-
unit: liter
|
|
142
|
-
)
|
|
143
|
-
)
|
|
144
|
-
milk_listing = Dscf::Marketplace::Listing.create!(
|
|
145
|
-
supplier_product: milk_product,
|
|
146
|
-
price: 45.00,
|
|
147
|
-
quantity: 500,
|
|
148
|
-
status: :active
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
puts "✅ Created #{Dscf::Marketplace::Product.count} products and #{Dscf::Marketplace::Listing.count} active listings"
|
|
152
|
-
|
|
153
|
-
puts "📋 Creating RFQs and quotations..."
|
|
154
|
-
|
|
155
|
-
# RFQ from retailer to wholesalers
|
|
156
|
-
rfq = Dscf::Marketplace::RequestForQuotation.create!(
|
|
157
|
-
user: retail_user1,
|
|
158
|
-
status: :sent,
|
|
159
|
-
notes: "Monthly supply of fresh produce"
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
# RFQ items
|
|
163
|
-
rfq.rfq_items.create!(
|
|
164
|
-
product: banana_product.product,
|
|
165
|
-
unit: kg,
|
|
166
|
-
quantity: 200,
|
|
167
|
-
notes: "Premium quality bananas"
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
rfq.rfq_items.create!(
|
|
171
|
-
product: milk_product.product,
|
|
172
|
-
unit: liter,
|
|
173
|
-
quantity: 100,
|
|
174
|
-
notes: "Fresh morning milk"
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
# Quotations from wholesalers
|
|
178
|
-
quotation1 = Dscf::Marketplace::Quotation.create!(
|
|
179
|
-
request_for_quotation: rfq,
|
|
180
|
-
business: wholesaler1,
|
|
181
|
-
total_price: 5000.00,
|
|
182
|
-
delivery_date: 3.days.from_now.to_date,
|
|
183
|
-
valid_until: 10.days.from_now,
|
|
184
|
-
status: :accepted,
|
|
185
|
-
notes: "Competitive pricing for bulk orders"
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
quotation1.quotation_items.create!(
|
|
189
|
-
rfq_item: rfq.rfq_items.first,
|
|
190
|
-
product: banana_product.product,
|
|
191
|
-
unit: kg,
|
|
192
|
-
quantity: 200,
|
|
193
|
-
unit_price: 25.00
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
quotation2 = Dscf::Marketplace::Quotation.create!(
|
|
197
|
-
request_for_quotation: rfq,
|
|
198
|
-
business: wholesaler2,
|
|
199
|
-
total_price: 4500.00,
|
|
200
|
-
delivery_date: 2.days.from_now.to_date,
|
|
201
|
-
valid_until: 8.days.from_now,
|
|
202
|
-
status: :sent,
|
|
203
|
-
notes: "Direct from farm fresh milk"
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
quotation2.quotation_items.create!(
|
|
207
|
-
rfq_item: rfq.rfq_items.second,
|
|
208
|
-
product: milk_product.product,
|
|
209
|
-
unit: liter,
|
|
210
|
-
quantity: 100,
|
|
211
|
-
unit_price: 45.00
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
puts "✅ Created #{Dscf::Marketplace::RequestForQuotation.count} RFQs with #{Dscf::Marketplace::Quotation.count} quotations"
|
|
215
|
-
|
|
216
|
-
puts "🛒 Creating orders from consumers and retailers..."
|
|
217
|
-
|
|
218
|
-
# Addresses for orders
|
|
219
|
-
consumer_address = Dscf::Core::Address.create!(
|
|
220
|
-
user: consumer1,
|
|
221
|
-
address_type: :shipping,
|
|
222
|
-
country: "Ethiopia",
|
|
223
|
-
city: "Addis Ababa",
|
|
224
|
-
sub_city: "Bole",
|
|
225
|
-
woreda: "05",
|
|
226
|
-
kebele: "09",
|
|
227
|
-
house_numbers: "123",
|
|
228
|
-
po_box: "5678",
|
|
229
|
-
latitude: 9.0108,
|
|
230
|
-
longitude: 38.7613
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
retailer_address = Dscf::Core::Address.create!(
|
|
234
|
-
user: retail_user1,
|
|
235
|
-
address_type: :shipping,
|
|
236
|
-
country: "Ethiopia",
|
|
237
|
-
city: "Addis Ababa",
|
|
238
|
-
sub_city: "Piassa",
|
|
239
|
-
woreda: "01",
|
|
240
|
-
kebele: "12",
|
|
241
|
-
house_numbers: "456",
|
|
242
|
-
po_box: "9012",
|
|
243
|
-
latitude: 9.0308,
|
|
244
|
-
longitude: 38.7413
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
# Order from consumer via direct listing
|
|
248
|
-
consumer_order = Dscf::Marketplace::Order.create_from_listing(
|
|
249
|
-
milk_listing,
|
|
250
|
-
consumer1,
|
|
251
|
-
10,
|
|
252
|
-
consumer_address
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
# Order from retailer via accepted quotation
|
|
256
|
-
retailer_order = Dscf::Marketplace::Order.create_from_quotation(
|
|
257
|
-
quotation1,
|
|
258
|
-
retailer_address
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
puts "✅ Created #{Dscf::Marketplace::Order.count} orders (#{Dscf::Marketplace::Order.where(order_type: :direct_listing).count} direct, #{Dscf::Marketplace::Order.where(order_type: :rfq_based).count} RFQ-based)"
|
|
262
|
-
|
|
263
|
-
puts "🚚 Creating delivery orders with multiple dropoffs..."
|
|
264
|
-
|
|
265
|
-
# Pickup address
|
|
266
|
-
pickup_address = Dscf::Core::Address.create!(
|
|
267
|
-
user: wholesaler1.user,
|
|
268
|
-
address_type: :business,
|
|
269
|
-
country: "Ethiopia",
|
|
270
|
-
city: "Addis Ababa",
|
|
271
|
-
sub_city: "Kazanchis",
|
|
272
|
-
woreda: "03",
|
|
273
|
-
kebele: "15",
|
|
274
|
-
house_numbers: "789",
|
|
275
|
-
po_box: "3456",
|
|
276
|
-
latitude: 9.0208,
|
|
277
|
-
longitude: 38.7513
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
# Additional dropoff
|
|
281
|
-
extra_address = Dscf::Core::Address.create!(
|
|
282
|
-
user: consumer2,
|
|
283
|
-
address_type: :shipping,
|
|
284
|
-
country: "Ethiopia",
|
|
285
|
-
city: "Addis Ababa",
|
|
286
|
-
sub_city: "Merkato",
|
|
287
|
-
woreda: "07",
|
|
288
|
-
kebele: "21",
|
|
289
|
-
house_numbers: "101",
|
|
290
|
-
po_box: "7890",
|
|
291
|
-
latitude: 9.0008,
|
|
292
|
-
longitude: 38.7713
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
# Create delivery order
|
|
296
|
-
delivery_order = Dscf::Marketplace::DeliveryOrder.create!(
|
|
297
|
-
driver: driver1,
|
|
298
|
-
pickup_address: pickup_address,
|
|
299
|
-
status: :assigned,
|
|
300
|
-
vehicle_type: :motorcycle,
|
|
301
|
-
estimated_delivery_price: 150.00,
|
|
302
|
-
estimated_delivery_time: 2.hours.from_now
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
# Associate orders
|
|
306
|
-
consumer_order.update!(delivery_order: delivery_order)
|
|
307
|
-
retailer_order.update!(delivery_order: delivery_order)
|
|
308
|
-
|
|
309
|
-
# Create additional order for third dropoff
|
|
310
|
-
extra_order = Dscf::Marketplace::Order.create_from_listing(
|
|
311
|
-
banana_listing,
|
|
312
|
-
consumer2,
|
|
313
|
-
5,
|
|
314
|
-
extra_address
|
|
315
|
-
)
|
|
316
|
-
extra_order.update!(delivery_order: delivery_order)
|
|
317
|
-
|
|
318
|
-
# Create delivery order items
|
|
319
|
-
delivery_order.delivery_order_items.create!(
|
|
320
|
-
order_item: consumer_order.order_items.first,
|
|
321
|
-
pickup_address: pickup_address,
|
|
322
|
-
dropoff_address: consumer_address
|
|
323
|
-
)
|
|
1
|
+
puts "🌱 Seeding marketplace permissions and default USER role..."
|
|
2
|
+
|
|
3
|
+
Dscf::Core::PermissionRegistry.register("dscf-marketplace") do
|
|
4
|
+
resource :categories, actions: %i[index show create update destroy subcategories]
|
|
5
|
+
resource :products, actions: %i[index show create update destroy filter supplier_products]
|
|
6
|
+
resource :units, actions: %i[index show create update destroy]
|
|
7
|
+
resource :unit_conversions, actions: %i[index show create update destroy]
|
|
8
|
+
resource :supplier_products, actions: %i[index show create update destroy my_products]
|
|
9
|
+
resource :listings, actions: %i[index show create update destroy activate pause sold_out my_listings listings_by_supplier]
|
|
10
|
+
resource :request_for_quotations, actions: %i[index show create update destroy send_rfq close respond my_rfqs filter]
|
|
11
|
+
resource :rfq_items, actions: %i[index show create update destroy]
|
|
12
|
+
resource :quotations, actions: %i[index show create update destroy accept reject send_quotation my_quotes filter]
|
|
13
|
+
resource :quotation_items, actions: %i[index show create update destroy]
|
|
14
|
+
resource :orders, actions: %i[index show create update destroy confirm cancel complete my_orders filter]
|
|
15
|
+
resource :order_items, actions: %i[index show create update destroy]
|
|
16
|
+
resource :delivery_orders, actions: %i[
|
|
17
|
+
index show create update destroy pickup start_delivery complete_delivery mark_failed accept summary
|
|
18
|
+
my_driver_deliveries filter convert_orders
|
|
19
|
+
]
|
|
20
|
+
resource :delivery_stops, actions: %i[index show create update destroy verify]
|
|
21
|
+
resource :delivery_order_items, actions: %i[index show create update destroy receiver_confirm report_issue dispute_delivery]
|
|
22
|
+
resource :delivery_vehicles, actions: %i[index show create update destroy]
|
|
23
|
+
resource :locations, actions: %i[get_location]
|
|
24
|
+
end
|
|
324
25
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
26
|
+
user_role = Dscf::Core::Role.find_or_create_by!(code: "USER") do |role|
|
|
27
|
+
role.name = "User"
|
|
28
|
+
role.active = true
|
|
29
|
+
end
|
|
30
|
+
user_role.update!(name: "User", active: true)
|
|
330
31
|
|
|
331
|
-
|
|
332
|
-
order_item: extra_order.order_items.first,
|
|
333
|
-
pickup_address: pickup_address,
|
|
334
|
-
dropoff_address: extra_address
|
|
335
|
-
)
|
|
32
|
+
marketplace_permissions = Dscf::Core::Permission.where(engine: "dscf-marketplace")
|
|
336
33
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
rescue => e
|
|
340
|
-
puts "❌ Seed failed: #{e.message}"
|
|
341
|
-
puts e.backtrace
|
|
342
|
-
raise
|
|
34
|
+
marketplace_permissions.find_each do |permission|
|
|
35
|
+
Dscf::Core::RolePermission.find_or_create_by!(role: user_role, permission: permission)
|
|
343
36
|
end
|
|
37
|
+
|
|
38
|
+
puts "✅ Seeded #{marketplace_permissions.count} marketplace permissions and assigned to USER role."
|
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.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Asrat
|
|
@@ -453,6 +453,23 @@ files:
|
|
|
453
453
|
- app/models/dscf/marketplace/supplier_product.rb
|
|
454
454
|
- app/models/dscf/marketplace/unit.rb
|
|
455
455
|
- app/models/dscf/marketplace/unit_conversion.rb
|
|
456
|
+
- app/policies/dscf/marketplace/category_policy.rb
|
|
457
|
+
- app/policies/dscf/marketplace/delivery_order_item_policy.rb
|
|
458
|
+
- app/policies/dscf/marketplace/delivery_order_policy.rb
|
|
459
|
+
- app/policies/dscf/marketplace/delivery_stop_policy.rb
|
|
460
|
+
- app/policies/dscf/marketplace/delivery_vehicle_policy.rb
|
|
461
|
+
- app/policies/dscf/marketplace/listing_policy.rb
|
|
462
|
+
- app/policies/dscf/marketplace/location_policy.rb
|
|
463
|
+
- app/policies/dscf/marketplace/order_item_policy.rb
|
|
464
|
+
- app/policies/dscf/marketplace/order_policy.rb
|
|
465
|
+
- app/policies/dscf/marketplace/product_policy.rb
|
|
466
|
+
- app/policies/dscf/marketplace/quotation_item_policy.rb
|
|
467
|
+
- app/policies/dscf/marketplace/quotation_policy.rb
|
|
468
|
+
- app/policies/dscf/marketplace/request_for_quotation_policy.rb
|
|
469
|
+
- app/policies/dscf/marketplace/rfq_item_policy.rb
|
|
470
|
+
- app/policies/dscf/marketplace/supplier_product_policy.rb
|
|
471
|
+
- app/policies/dscf/marketplace/unit_conversion_policy.rb
|
|
472
|
+
- app/policies/dscf/marketplace/unit_policy.rb
|
|
456
473
|
- app/serializers/dscf/marketplace/category_serializer.rb
|
|
457
474
|
- app/serializers/dscf/marketplace/delivery_order_item_serializer.rb
|
|
458
475
|
- app/serializers/dscf/marketplace/delivery_order_serializer.rb
|
|
@@ -512,6 +529,8 @@ files:
|
|
|
512
529
|
- db/migrate/20251006055948_change_default_payment_method_on_orders.rb
|
|
513
530
|
- db/migrate/20251130143731_create_dscf_marketplace_delivery_stops.rb
|
|
514
531
|
- db/migrate/20251130144500_add_delivery_stop_to_delivery_order_items.rb
|
|
532
|
+
- db/migrate/20260310120000_add_active_and_description_to_dscf_core_roles.rb
|
|
533
|
+
- db/migrate/20260310122000_add_missing_fields_to_dscf_core_user_roles.rb
|
|
515
534
|
- db/seeds.rb
|
|
516
535
|
- lib/dscf/marketplace.rb
|
|
517
536
|
- lib/dscf/marketplace/engine.rb
|