dscf-marketplace 0.13.7 → 0.13.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21099282f07c99ae15cd4c526736df7c8e1597ff82caf3e1b540380417f093d0
4
- data.tar.gz: e870bcffce615ba356fec8fa15055aa545a3c7efc17cffe95d6bb61f9420d73b
3
+ metadata.gz: 41a9dcd1ca1d3229c9f74bc40ed5b2b0813108348f28b52a667bff5109c7169a
4
+ data.tar.gz: 4c370bed0af3b391d58e574ce1d17a5ad6cc13523de64fd666f255f19adb645a
5
5
  SHA512:
6
- metadata.gz: e3284d4198ad24bbe298fbf6a6a9c4be20a33e72ed0391d865f524859fd0064c925f8d0693f25bc23cf47504e1f180a0a52dc3fa0256ab8cf8b2ac0f5bfb0334
7
- data.tar.gz: 3667ca220153c9a32cc0162ef8018c9204fdb39005f4a109ce88f8e77f31c08d110d1f76d2d25009e6bc891b0c611eb124dfc688044a81a53efd7adcd6695397
6
+ metadata.gz: b41084c0c19ed13fcc4f4be329758ee2b88b9ad665e4bf9c68d6b7f5cb83c1ecff2b619faa64f632c77267780aafacb31448dd3f1c58bff324d9091bb526dd67
7
+ data.tar.gz: 27e1aabb04b76390501c595a54227d1fcc8a6bcdddfdb4b7fd0600a0be49b5d1dc63a8e638eb09f7c82b2c213d27e63ea1fa5b8cc0ab364a81b9b8260526c02c
@@ -2,7 +2,7 @@ module Dscf
2
2
  module Marketplace
3
3
  class SupplierSerializer < ActiveModel::Serializer
4
4
  attributes :id, :name, :code, :address, :contact_phone, :business_type,
5
- :business_id, :review_status, :document_urls, :created_at, :updated_at
5
+ :business_id, :review_status, :review_reason, :document_urls, :created_at, :updated_at
6
6
 
7
7
  belongs_to :business
8
8
  has_many :addresses
@@ -11,6 +11,15 @@ module Dscf
11
11
  object.review_status
12
12
  end
13
13
 
14
+ # Reason the admin gave on the latest review (modification request or
15
+ # rejection). Lives in the Review's jsonb `feedback` as {reason: "..."}.
16
+ # nil for approved/pending/draft. Lets the mobile "changes requested"
17
+ # screen show the admin's note without a push notification.
18
+ def review_reason
19
+ feedback = object.current_review_for(:default)&.feedback
20
+ feedback && (feedback["reason"] || feedback[:reason])
21
+ end
22
+
14
23
  def document_urls
15
24
  object.document_urls
16
25
  end
@@ -0,0 +1,274 @@
1
+ # ════════════════════════════════════════════════════════════════════════════
2
+ # ANTIGRAVITY SEEDS — Clean, collision-free, and fully idempotent demo data
3
+ # ════════════════════════════════════════════════════════════════════════════
4
+ # NOTE: This script does NOT delete any existing tables or database records.
5
+ # It safely finds-or-creates our custom test ecosystem.
6
+
7
+ puts "🌱 Initializing Antigravity test data safely..."
8
+
9
+ # ── 1. Find Existing Super Admin ──
10
+ admin = Dscf::Core::User.find_by(email: "admin@dscf.com")
11
+ unless admin
12
+ puts "❌ admin@dscf.com not found! Creating default admin as fallback..."
13
+ admin = Dscf::Core::User.create!(
14
+ email: "admin@dscf.com",
15
+ phone: "+251999000000",
16
+ password: "Admin@2024",
17
+ verified_at: Time.current,
18
+ temp_password: false
19
+ )
20
+ end
21
+
22
+ sa_role = Dscf::Core::Role.find_or_create_by!(code: "SUPER_ADMIN") { |r| r.name = "Super Admin"; r.active = true }
23
+ Dscf::Core::UserRole.find_or_create_by!(user: admin, role: sa_role)
24
+
25
+ # Ensure SUPER_ADMIN has basic orders permissions
26
+ orders_perms = Dscf::Core::Permission.where(resource: "orders")
27
+ orders_perms.each do |perm|
28
+ Dscf::Core::RolePermission.find_or_create_by!(role: sa_role, permission: perm)
29
+ end
30
+ puts "✅ Super Admin configured."
31
+
32
+ # ── 2. Find or Create Custom Antigravity Users safely ──
33
+ retailer_user = Dscf::Core::User.find_by(email: "antigravity.retailer@example.com")
34
+ unless retailer_user
35
+ phone = "+251977111111"
36
+ # Avoid phone collisions if already taken
37
+ while Dscf::Core::User.exists?(phone: phone)
38
+ phone = "+251977111#{rand(100..999)}"
39
+ end
40
+
41
+ retailer_user = Dscf::Core::User.create!(
42
+ email: "antigravity.retailer@example.com",
43
+ phone: phone,
44
+ password: "password",
45
+ verified_at: Time.current,
46
+ temp_password: false
47
+ )
48
+ end
49
+
50
+ supplier_user = Dscf::Core::User.find_by(email: "antigravity.supplier@example.com")
51
+ unless supplier_user
52
+ phone = "+251977222222"
53
+ # Avoid phone collisions if already taken
54
+ while Dscf::Core::User.exists?(phone: phone)
55
+ phone = "+251977222#{rand(100..999)}"
56
+ end
57
+
58
+ supplier_user = Dscf::Core::User.create!(
59
+ email: "antigravity.supplier@example.com",
60
+ phone: phone,
61
+ password: "password",
62
+ verified_at: Time.current,
63
+ temp_password: false
64
+ )
65
+ end
66
+
67
+ # Assign default USER role
68
+ user_role = Dscf::Core::Role.find_or_create_by!(code: "USER") { |r| r.name = "User"; r.active = true }
69
+ Dscf::Core::UserRole.find_or_create_by!(user: retailer_user, role: user_role)
70
+ Dscf::Core::UserRole.find_or_create_by!(user: supplier_user, role: user_role)
71
+
72
+ # Assign marketplace permissions to USER role
73
+ Dscf::Core::Permission.where(engine: "dscf-marketplace").find_each do |perm|
74
+ Dscf::Core::RolePermission.find_or_create_by!(role: user_role, permission: perm)
75
+ end
76
+
77
+ puts "✅ Custom users verified/created."
78
+
79
+ # ── 3. Find or Create Custom Businesses safely ──
80
+ bt_manufacturer = Dscf::Core::BusinessType.find_or_create_by!(name: "Manufacturer")
81
+ bt_retailer = Dscf::Core::BusinessType.find_or_create_by!(name: "Retailer")
82
+
83
+ retailer_biz = Dscf::Core::Business.find_by(tin_number: "TIN-AG-RET-001")
84
+ unless retailer_biz
85
+ phone = "+251977111112"
86
+ while Dscf::Core::Business.exists?(contact_phone: phone)
87
+ phone = "+251977111#{rand(100..999)}"
88
+ end
89
+
90
+ retailer_biz = Dscf::Core::Business.create!(
91
+ name: "Antigravity Supermarket",
92
+ user: retailer_user,
93
+ business_type: bt_retailer,
94
+ contact_phone: phone,
95
+ description: "Antigravity Premium Retailer Store",
96
+ tin_number: "TIN-AG-RET-001"
97
+ )
98
+ end
99
+
100
+ supplier_biz = Dscf::Core::Business.find_by(tin_number: "TIN-AG-SUP-001")
101
+ unless supplier_biz
102
+ phone = "+251977222223"
103
+ while Dscf::Core::Business.exists?(contact_phone: phone)
104
+ phone = "+251977222#{rand(100..999)}"
105
+ end
106
+
107
+ supplier_biz = Dscf::Core::Business.create!(
108
+ name: "Antigravity Coffee & Textile Wholesaler",
109
+ user: supplier_user,
110
+ business_type: bt_manufacturer,
111
+ contact_phone: phone,
112
+ description: "Premium Antigravity Wholesaler Export",
113
+ tin_number: "TIN-AG-SUP-001"
114
+ )
115
+ end
116
+
117
+ aggregator_biz = Dscf::Core::Business.find_by(tin_number: "TIN-AG-AGG-001")
118
+ unless aggregator_biz
119
+ phone = "+251977333333"
120
+ while Dscf::Core::Business.exists?(contact_phone: phone)
121
+ phone = "+251977333#{rand(100..999)}"
122
+ end
123
+
124
+ aggregator_biz = Dscf::Core::Business.create!(
125
+ name: "Antigravity Aggregators",
126
+ user: admin,
127
+ business_type: bt_manufacturer,
128
+ contact_phone: phone,
129
+ description: "Official Antigravity Marketplace Aggregator Hub",
130
+ tin_number: "TIN-AG-AGG-001"
131
+ )
132
+ end
133
+
134
+ puts "✅ Custom businesses verified/created."
135
+
136
+ # ── 4. Categories & Units ──
137
+ cat_coffee = Dscf::Marketplace::Category.find_or_create_by!(name: "Antigravity Coffee") do |c|
138
+ c.description = "Specialty roasted Ethiopian coffee"
139
+ end
140
+
141
+ cat_textile = Dscf::Marketplace::Category.find_or_create_by!(name: "Antigravity Textiles") do |c|
142
+ c.description = "Premium handwoven fabrics"
143
+ end
144
+
145
+ u_kg = Dscf::Marketplace::Unit.find_or_create_by!(code: "KG") do |u|
146
+ u.name = "Kilogram"
147
+ u.unit_type = :weight
148
+ end
149
+
150
+ u_meter = Dscf::Marketplace::Unit.find_or_create_by!(code: "M") do |u|
151
+ u.name = "Meter"
152
+ u.unit_type = :dimension
153
+ end
154
+
155
+ puts "✅ Categories & Units verified/created."
156
+
157
+ # ── 5. Products ──
158
+ p1 = Dscf::Marketplace::Product.find_or_create_by!(sku: "AG-COF-SID") do |p|
159
+ p.name = "Antigravity Sidamo Roasted Coffee"
160
+ p.description = "Premium washed Sidamo — Medium Roast"
161
+ p.category = cat_coffee
162
+ p.unit = u_kg
163
+ p.base_quantity = 1.0
164
+ p.gross_weight = 1.2
165
+ end
166
+
167
+ p2 = Dscf::Marketplace::Product.find_or_create_by!(sku: "AG-TEX-GAB") do |p|
168
+ p.name = "Antigravity Traditional Gabi Fabric"
169
+ p.description = "Handwoven thick cotton Gabi"
170
+ p.category = cat_textile
171
+ p.unit = u_meter
172
+ p.base_quantity = 1.0
173
+ p.gross_weight = 0.8
174
+ end
175
+
176
+ puts "✅ Products verified/created."
177
+
178
+ # ── 6. Supplier Record ──
179
+ supplier_record = Dscf::Marketplace::Supplier.find_or_create_by!(business_id: supplier_biz.id) do |s|
180
+ s.name = "Antigravity Wholesaler Outlet"
181
+ s.business_type = :manufacturer
182
+ s.contact_phone = supplier_biz.contact_phone
183
+ s.address = "Bole Sub-city, Addis Ababa"
184
+ end
185
+
186
+ # ── 7. Supplier Products ──
187
+ sp1 = Dscf::Marketplace::SupplierProduct.find_or_create_by!(business_id: supplier_biz.id, product_id: p1.id) do |sp|
188
+ sp.supplier = supplier_record
189
+ sp.supplier_price = 400
190
+ sp.available_quantity = 1000
191
+ sp.minimum_order_quantity = 5
192
+ sp.status = :active
193
+ end
194
+
195
+ sp2 = Dscf::Marketplace::SupplierProduct.find_or_create_by!(business_id: supplier_biz.id, product_id: p2.id) do |sp|
196
+ sp.supplier = supplier_record
197
+ sp.supplier_price = 300
198
+ sp.available_quantity = 500
199
+ sp.minimum_order_quantity = 2
200
+ sp.status = :active
201
+ end
202
+
203
+ puts "✅ Supplier Products verified/created."
204
+
205
+ # ── 8. Aggregator Listings (Sprint 2 Core Target) ──
206
+ al1 = Dscf::Marketplace::AggregatorListing.find_or_create_by!(aggregator_id: aggregator_biz.id, supplier_product_id: sp1.id) do |al|
207
+ al.price = 550
208
+ al.quantity = 200
209
+ al.status = 0 # active/published
210
+ end
211
+
212
+ al2 = Dscf::Marketplace::AggregatorListing.find_or_create_by!(aggregator_id: aggregator_biz.id, supplier_product_id: sp2.id) do |al|
213
+ al.price = 420
214
+ al.quantity = 150
215
+ al.status = 0 # active/published
216
+ end
217
+
218
+ puts "✅ Aggregator Listings verified/created."
219
+
220
+ # ── 9. Direct Listings ──
221
+ Dscf::Marketplace::Listing.find_or_create_by!(business_id: supplier_biz.id, supplier_product_id: sp1.id) do |l|
222
+ l.price = 500
223
+ l.quantity = 300
224
+ l.status = :active
225
+ l.description = "Direct Sidamo Roasted Coffee from Antigravity Outlet"
226
+ end
227
+
228
+ Dscf::Marketplace::Listing.find_or_create_by!(business_id: supplier_biz.id, supplier_product_id: sp2.id) do |l|
229
+ l.price = 380
230
+ l.quantity = 200
231
+ l.status = :active
232
+ l.description = "Direct Traditional Handwoven Gabi from Antigravity Outlet"
233
+ end
234
+
235
+ puts "✅ Direct Listings verified/created."
236
+
237
+ # ── 10. Demo Addresses & Agents ──
238
+ address = Dscf::Core::Address.find_by(user_id: retailer_user.id)
239
+ unless address
240
+ address = Dscf::Core::Address.create!(
241
+ user: retailer_user,
242
+ address_type: :shipping,
243
+ country: "Ethiopia",
244
+ city: "Addis Ababa",
245
+ sub_city: "Bole Sub-city",
246
+ woreda: "Woreda 03",
247
+ house_numbers: "Suite 4B"
248
+ )
249
+ end
250
+
251
+ agent = Dscf::Marketplace::Agent.find_by(onboarded_by_id: aggregator_biz.id)
252
+ unless agent
253
+ agent_phone = "+251977444444"
254
+ while Dscf::Marketplace::Agent.exists?(phone: agent_phone)
255
+ agent_phone = "+251977444#{rand(100..999)}"
256
+ end
257
+
258
+ Dscf::Marketplace::Agent.create!(
259
+ name: "Antigravity Logistics Agent",
260
+ phone: agent_phone,
261
+ service_area: "Bole Sub-city",
262
+ status: :active,
263
+ verification_status: :verified,
264
+ onboarded_by: aggregator_biz
265
+ )
266
+ end
267
+
268
+ puts "🎉 ALL ANTIGRAVITY SEEDS COMPLETED SUCCESSFULLY WITHOUT DELETING ANY DATA."
269
+ puts "--------------------------------------------------------"
270
+ puts "🔑 CREDENTIALS TO USE:"
271
+ puts "Buyer (Retailer): antigravity.retailer@example.com / password"
272
+ puts "Supplier (Wholesaler): antigravity.supplier@example.com / password"
273
+ puts "Super Admin: admin@dscf.com / Admin@2024"
274
+ puts "--------------------------------------------------------"
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Marketplace
3
- VERSION = "0.13.7".freeze
3
+ VERSION = "0.13.8".freeze
4
4
  end
5
5
  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.13.7
4
+ version: 0.13.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asrat
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-07-04 00:00:00.000000000 Z
10
+ date: 2026-07-08 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -536,6 +536,7 @@ files:
536
536
  - config/environments/production.rb
537
537
  - config/locales/en.yml
538
538
  - config/routes.rb
539
+ - db/antigravity_seeds.rb
539
540
  - db/demo_seeds.rb
540
541
  - db/migrate/20250827172043_create_dscf_marketplace_categories.rb
541
542
  - db/migrate/20250827173526_update_dscf_marketplace_categories_indexes.rb