dscf-marketplace 0.3.97 โ 0.3.98
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/delivery_orders_controller.rb +3 -2
- data/app/serializers/dscf/marketplace/order_serializer.rb +21 -0
- data/db/seeds.rb +343 -0
- data/lib/dscf/marketplace/engine.rb +5 -0
- data/lib/dscf/marketplace/version.rb +1 -1
- data/spec/factories/dscf/core/users.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: 4bfb73ec9f2d2d71a3f41f63d961f78a647a54ed2e662c6c37fcf353cb616166
|
4
|
+
data.tar.gz: 2cda27a9e978ce5b4f46d5b75fbadb054640ec5623c6bd93683d56f760da332c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d1ca95ef3bba82e8595f2ebb897def65e6d2fc05ecd5f98334ebf5692573ee246cd6a8a0b3f80d6e780508f8320a58cd4cb370a82e071ebf32c8a79b62e3fa1
|
7
|
+
data.tar.gz: 2f0823dd0d008b7871bd5032d9a30aec45c388a2d56fdbff883256e4468ca579efda36a6d011d5b7415bd4de6ba58acb8d8f1d63f9d148c2e7158f609f52a61a
|
@@ -222,7 +222,7 @@ module Dscf
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def eager_loaded_associations
|
225
|
-
[ :driver, :pickup_address, :delivery_vehicle, :delivery_order_items
|
225
|
+
[ :driver, :pickup_address, :delivery_vehicle, :delivery_order_items ]
|
226
226
|
end
|
227
227
|
|
228
228
|
def default_serializer_includes
|
@@ -241,7 +241,8 @@ module Dscf
|
|
241
241
|
:delivery_vehicle,
|
242
242
|
:marketplace_orders,
|
243
243
|
{
|
244
|
-
delivery_order_items: [ :dropoff_address ]
|
244
|
+
delivery_order_items: [ :dropoff_address ],
|
245
|
+
marketplace_orders: [ :ordered_by, :ordered_to ]
|
245
246
|
}
|
246
247
|
],
|
247
248
|
create: [ :driver, :pickup_address, :delivery_vehicle ],
|
@@ -3,6 +3,7 @@ module Dscf
|
|
3
3
|
class OrderSerializer < ActiveModel::Serializer
|
4
4
|
attributes :id, :quotation_id, :listing_id, :user_id, :ordered_by_id, :ordered_to_id, :delivery_order_id, :dropoff_address_id,
|
5
5
|
:order_type, :status, :fulfillment_type, :total_amount,
|
6
|
+
:buyer_phone, :buyer_email, :seller_name, :seller_phone, :seller_email,
|
6
7
|
:created_at, :updated_at
|
7
8
|
|
8
9
|
belongs_to :quotation
|
@@ -13,6 +14,26 @@ module Dscf
|
|
13
14
|
belongs_to :delivery_order
|
14
15
|
belongs_to :dropoff_address
|
15
16
|
has_many :order_items
|
17
|
+
|
18
|
+
def buyer_phone
|
19
|
+
object.ordered_by&.phone
|
20
|
+
end
|
21
|
+
|
22
|
+
def buyer_email
|
23
|
+
object.ordered_by&.email
|
24
|
+
end
|
25
|
+
|
26
|
+
def seller_name
|
27
|
+
object.ordered_to&.name
|
28
|
+
end
|
29
|
+
|
30
|
+
def seller_phone
|
31
|
+
object.ordered_to&.contact_phone
|
32
|
+
end
|
33
|
+
|
34
|
+
def seller_email
|
35
|
+
object.ordered_to&.contact_email
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
18
39
|
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1,343 @@
|
|
1
|
+
puts "๐ Starting demo seed..."
|
2
|
+
begin
|
3
|
+
puts "๐งน Clearing existing demo data..."
|
4
|
+
Dscf::Marketplace::DeliveryOrderItem.delete_all
|
5
|
+
Dscf::Marketplace::DeliveryOrder.delete_all
|
6
|
+
Dscf::Marketplace::OrderItem.delete_all
|
7
|
+
Dscf::Marketplace::Order.delete_all
|
8
|
+
Dscf::Marketplace::QuotationItem.delete_all
|
9
|
+
Dscf::Marketplace::Quotation.delete_all
|
10
|
+
Dscf::Marketplace::RfqItem.delete_all
|
11
|
+
Dscf::Marketplace::RequestForQuotation.delete_all
|
12
|
+
Dscf::Marketplace::Listing.delete_all
|
13
|
+
Dscf::Marketplace::SupplierProduct.delete_all
|
14
|
+
Dscf::Marketplace::Product.delete_all
|
15
|
+
Dscf::Core::Business.delete_all
|
16
|
+
Dscf::Core::User.where.not(email: "admin@example.com").delete_all
|
17
|
+
Dscf::Core::Address.delete_all
|
18
|
+
|
19
|
+
puts "๐ฑ Creating base units and categories..."
|
20
|
+
|
21
|
+
# Units
|
22
|
+
kg = Dscf::Marketplace::Unit.create!(name: "Kilogram", code: "kg", unit_type: :weight)
|
23
|
+
Dscf::Marketplace::Unit.create!(name: "Piece", code: "pc", unit_type: :quantity)
|
24
|
+
liter = Dscf::Marketplace::Unit.create!(name: "Liter", code: "L", unit_type: :volume)
|
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
|
+
)
|
324
|
+
|
325
|
+
delivery_order.delivery_order_items.create!(
|
326
|
+
order_item: retailer_order.order_items.first,
|
327
|
+
pickup_address: pickup_address,
|
328
|
+
dropoff_address: retailer_address
|
329
|
+
)
|
330
|
+
|
331
|
+
delivery_order.delivery_order_items.create!(
|
332
|
+
order_item: extra_order.order_items.first,
|
333
|
+
pickup_address: pickup_address,
|
334
|
+
dropoff_address: extra_address
|
335
|
+
)
|
336
|
+
|
337
|
+
puts "โ
Created #{Dscf::Marketplace::DeliveryOrder.count} delivery orders with #{Dscf::Marketplace::DeliveryOrderItem.count} total dropoffs"
|
338
|
+
puts "๐ Demo seed completed! Created realistic supply chain with #{Dscf::Core::User.count} users, #{Dscf::Core::Business.count} businesses, and #{Dscf::Marketplace::Order.count} orders across the platform."
|
339
|
+
rescue => e
|
340
|
+
puts "โ Seed failed: #{e.message}"
|
341
|
+
puts e.backtrace
|
342
|
+
raise
|
343
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "dscf/core"
|
2
|
+
|
1
3
|
module Dscf
|
2
4
|
module Marketplace
|
3
5
|
class Engine < ::Rails::Engine
|
@@ -12,6 +14,9 @@ module Dscf
|
|
12
14
|
|
13
15
|
initializer :append_migrations do |app|
|
14
16
|
app.config.paths["db/migrate"].concat(config.paths["db/migrate"].expanded) unless app.root.to_s.match(root.to_s + File::SEPARATOR)
|
17
|
+
# Append dscf-core migrations
|
18
|
+
core_engine = Dscf::Core::Engine
|
19
|
+
app.config.paths["db/migrate"].concat(core_engine.config.paths["db/migrate"].expanded) unless app.root.to_s.match(root.to_s + File::SEPARATOR)
|
15
20
|
end
|
16
21
|
|
17
22
|
require "active_storage/engine"
|
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.
|
4
|
+
version: 0.3.98
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Asrat
|
@@ -504,6 +504,7 @@ files:
|
|
504
504
|
- db/migrate/20250916083536_make_driver_id_nullable_in_delivery_orders.rb
|
505
505
|
- db/migrate/20250917110618_add_dropoff_address_to_dscf_marketplace_orders.rb
|
506
506
|
- db/migrate/20250920105329_backfill_quotation_total_prices.rb
|
507
|
+
- db/seeds.rb
|
507
508
|
- lib/dscf/marketplace.rb
|
508
509
|
- lib/dscf/marketplace/engine.rb
|
509
510
|
- lib/dscf/marketplace/version.rb
|