dscf-marketplace 0.1.4 → 0.1.5
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/models/dscf/marketplace/listing.rb +55 -0
- data/app/models/dscf/marketplace/supplier_product.rb +47 -0
- data/db/migrate/20250828072514_create_dscf_marketplace_supplier_products.rb +32 -0
- data/db/migrate/20250828081657_create_dscf_marketplace_listings.rb +31 -0
- data/lib/dscf/marketplace/version.rb +1 -1
- data/spec/factories/dscf/core/business_types.rb +5 -0
- data/spec/factories/dscf/core/businesses.rb +11 -0
- data/spec/factories/dscf/core/users.rb +8 -0
- data/spec/factories/dscf/marketplace/listings.rb +10 -0
- data/spec/factories/dscf/marketplace/supplier_products.rb +10 -0
- metadata +10 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6b077453f450386b96a2df3aac342c13fe4ec2bc97d4e34fa48b1e4918df3ed
|
4
|
+
data.tar.gz: 837589f60812fcf77b8a9958b344ec274458434ba63e695538746165349af8dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f864dfe924f7002b4edc7686e3f227bfbf500ed63a1ecc67b3aa0d34fc76123d0b0d900495644da1552bd28539f7ec56db6fff44aa4c4e4320e8f72f741619a8
|
7
|
+
data.tar.gz: 5a5aae5e8036726d534492e592a984e2185eb8e4f4102596c7d918c61fb8c293e8b2da1c60954dbd200c5f88d709d3267fe9b523634938b91fb8137e8f162fc2
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Dscf::Marketplace
|
2
|
+
class Listing < ApplicationRecord
|
3
|
+
# References
|
4
|
+
belongs_to :business, class_name: "Dscf::Core::Business"
|
5
|
+
belongs_to :supplier_product, class_name: "Dscf::Marketplace::SupplierProduct"
|
6
|
+
|
7
|
+
# Relationships
|
8
|
+
has_many :order_items, class_name: "Dscf::Marketplace::OrderItem"
|
9
|
+
|
10
|
+
# Status enum
|
11
|
+
enum :status, {active: 0, draft: 1, paused: 2, sold_out: 3}, default: :draft
|
12
|
+
|
13
|
+
# Validations
|
14
|
+
validates :price, numericality: {greater_than: 0}, presence: true
|
15
|
+
validates :quantity, numericality: {greater_than: 0}, presence: true
|
16
|
+
validates :business_id, presence: true
|
17
|
+
validates :supplier_product_id, presence: true
|
18
|
+
|
19
|
+
# Scopes
|
20
|
+
scope :active, -> { where(status: :active) }
|
21
|
+
scope :by_business, ->(business_id) { where(business_id: business_id) }
|
22
|
+
scope :owned_by, ->(business) { where(business: business) }
|
23
|
+
|
24
|
+
# Custom methods
|
25
|
+
def total_value
|
26
|
+
price * quantity
|
27
|
+
end
|
28
|
+
|
29
|
+
def margin
|
30
|
+
return nil unless supplier_product&.supplier_price
|
31
|
+
price - supplier_product.supplier_price
|
32
|
+
end
|
33
|
+
|
34
|
+
def margin_percentage
|
35
|
+
return nil unless supplier_product&.supplier_price && supplier_product.supplier_price > 0
|
36
|
+
((margin / supplier_product.supplier_price) * 100).round(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
def available?
|
40
|
+
active? && quantity > 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def supplier_business
|
44
|
+
supplier_product&.business
|
45
|
+
end
|
46
|
+
|
47
|
+
def product
|
48
|
+
supplier_product&.product
|
49
|
+
end
|
50
|
+
|
51
|
+
def can_be_managed_by?(business)
|
52
|
+
self.business == business
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Dscf::Marketplace
|
2
|
+
class SupplierProduct < ApplicationRecord
|
3
|
+
# References
|
4
|
+
belongs_to :business, class_name: "Dscf::Core::Business"
|
5
|
+
belongs_to :product, class_name: "Dscf::Marketplace::Product"
|
6
|
+
|
7
|
+
# Relationships
|
8
|
+
has_many :listings, class_name: "Dscf::Marketplace::Listing"
|
9
|
+
has_many :order_items, class_name: "Dscf::Marketplace::OrderItem"
|
10
|
+
|
11
|
+
# Status enum
|
12
|
+
enum :status, {active: 0, inactive: 1, discontinued: 2}, default: :active
|
13
|
+
|
14
|
+
# Validations
|
15
|
+
validates :supplier_price, numericality: {greater_than: 0}, presence: true
|
16
|
+
validates :available_quantity, numericality: {greater_than_or_equal_to: 0}
|
17
|
+
validates :minimum_order_quantity, numericality: {greater_than: 0}, allow_nil: true
|
18
|
+
|
19
|
+
# Scopes
|
20
|
+
scope :active, -> { where(status: :active) }
|
21
|
+
scope :in_stock, -> { where("available_quantity > 0") }
|
22
|
+
scope :by_business, ->(business_id) { where(business_id: business_id) }
|
23
|
+
scope :by_product, ->(product_id) { where(product_id: product_id) }
|
24
|
+
|
25
|
+
# Custom methods
|
26
|
+
def in_stock?
|
27
|
+
available_quantity > 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def can_fulfill?(quantity)
|
31
|
+
available_quantity >= quantity
|
32
|
+
end
|
33
|
+
|
34
|
+
def price_per_unit
|
35
|
+
return nil unless supplier_price && product&.base_quantity
|
36
|
+
supplier_price / product.base_quantity
|
37
|
+
end
|
38
|
+
|
39
|
+
def display_name
|
40
|
+
"#{business.name} - #{product.name}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def available_for_order?(quantity = 1)
|
44
|
+
active? && can_fulfill?(quantity)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class CreateDscfMarketplaceSupplierProducts < ActiveRecord::Migration[8.0]
|
2
|
+
def change
|
3
|
+
create_table :dscf_marketplace_supplier_products do |t|
|
4
|
+
t.references :business,
|
5
|
+
index: {name: "business_on_dm_sp_indx"},
|
6
|
+
null: false,
|
7
|
+
foreign_key: {to_table: :dscf_core_businesses}
|
8
|
+
t.references :product,
|
9
|
+
index: {name: "product_on_dm_sp_indx"},
|
10
|
+
null: false,
|
11
|
+
foreign_key: {to_table: :dscf_marketplace_products}
|
12
|
+
|
13
|
+
# Ethiopian Birr pricing
|
14
|
+
t.decimal :supplier_price, precision: 15, scale: 2, null: false
|
15
|
+
|
16
|
+
# Inventory management
|
17
|
+
t.decimal :available_quantity, precision: 15, scale: 6, null: false, default: 0
|
18
|
+
t.decimal :minimum_order_quantity, precision: 15, scale: 6
|
19
|
+
|
20
|
+
# Status
|
21
|
+
t.integer :status, null: false, default: 0
|
22
|
+
|
23
|
+
t.timestamps
|
24
|
+
end
|
25
|
+
|
26
|
+
# Unique constraint - one supplier product per business-product combination
|
27
|
+
add_index :dscf_marketplace_supplier_products,
|
28
|
+
[ :business_id, :product_id ],
|
29
|
+
unique: true,
|
30
|
+
name: "unique_business_product_indx"
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class CreateDscfMarketplaceListings < ActiveRecord::Migration[8.0]
|
2
|
+
def change
|
3
|
+
create_table :dscf_marketplace_listings do |t|
|
4
|
+
t.references :business,
|
5
|
+
index: {name: "business_on_dm_listings_indx"},
|
6
|
+
null: false,
|
7
|
+
foreign_key: {to_table: :dscf_core_businesses}
|
8
|
+
t.references :supplier_product,
|
9
|
+
index: {name: "supplier_product_on_dm_listings_indx"},
|
10
|
+
null: false,
|
11
|
+
foreign_key: {to_table: :dscf_marketplace_supplier_products}
|
12
|
+
|
13
|
+
# Ethiopian Birr pricing
|
14
|
+
t.decimal :price, precision: 15, scale: 2, null: false
|
15
|
+
|
16
|
+
# Available quantity for sale
|
17
|
+
t.decimal :quantity, precision: 15, scale: 6, null: false
|
18
|
+
|
19
|
+
# Optional listing description
|
20
|
+
t.text :description
|
21
|
+
|
22
|
+
# Status
|
23
|
+
t.integer :status, null: false, default: 1 # draft
|
24
|
+
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
add_index :dscf_marketplace_listings, :status, name: "status_on_dm_listings_indx"
|
29
|
+
add_index :dscf_marketplace_listings, [ :business_id, :supplier_product_id ], name: "business_supplier_product_on_dm_listings_indx"
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :dscf_core_business, class: 'Dscf::Core::Business' do
|
3
|
+
sequence(:name) { |n| "Test Business #{n}" }
|
4
|
+
description { "Test business description" }
|
5
|
+
contact_email { "contact@example.com" }
|
6
|
+
contact_phone { "+251911123456" }
|
7
|
+
tin_number { "1234567890" }
|
8
|
+
business_type { create(:dscf_core_business_type) }
|
9
|
+
user { create(:dscf_core_user) }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :dscf_marketplace_listing, class: 'Dscf::Marketplace::Listing' do
|
3
|
+
business { create(:dscf_core_business) }
|
4
|
+
supplier_product { create(:dscf_marketplace_supplier_product) }
|
5
|
+
price { 500.00 }
|
6
|
+
quantity { 100.0 }
|
7
|
+
description { "High quality product listing" }
|
8
|
+
status { :draft }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
factory :dscf_marketplace_supplier_product, class: 'Dscf::Marketplace::SupplierProduct' do
|
3
|
+
business { create(:dscf_core_business) }
|
4
|
+
product { create(:dscf_marketplace_product) }
|
5
|
+
supplier_price { 500.00 }
|
6
|
+
available_quantity { 100.0 }
|
7
|
+
minimum_order_quantity { 10.0 }
|
8
|
+
status { :active }
|
9
|
+
end
|
10
|
+
end
|
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.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Asrat
|
@@ -422,7 +422,9 @@ files:
|
|
422
422
|
- app/mailers/dscf/marketplace/application_mailer.rb
|
423
423
|
- app/models/dscf/marketplace/application_record.rb
|
424
424
|
- app/models/dscf/marketplace/category.rb
|
425
|
+
- app/models/dscf/marketplace/listing.rb
|
425
426
|
- app/models/dscf/marketplace/product.rb
|
427
|
+
- app/models/dscf/marketplace/supplier_product.rb
|
426
428
|
- app/models/dscf/marketplace/unit.rb
|
427
429
|
- app/models/dscf/marketplace/unit_conversion.rb
|
428
430
|
- config/routes.rb
|
@@ -431,12 +433,19 @@ files:
|
|
431
433
|
- db/migrate/20250827182550_create_dscf_marketplace_units.rb
|
432
434
|
- db/migrate/20250827185656_create_dscf_marketplace_unit_conversions.rb
|
433
435
|
- db/migrate/20250828062945_create_dscf_marketplace_products.rb
|
436
|
+
- db/migrate/20250828072514_create_dscf_marketplace_supplier_products.rb
|
437
|
+
- db/migrate/20250828081657_create_dscf_marketplace_listings.rb
|
434
438
|
- lib/dscf/marketplace.rb
|
435
439
|
- lib/dscf/marketplace/engine.rb
|
436
440
|
- lib/dscf/marketplace/version.rb
|
437
441
|
- lib/tasks/dscf/marketplace_tasks.rake
|
442
|
+
- spec/factories/dscf/core/business_types.rb
|
443
|
+
- spec/factories/dscf/core/businesses.rb
|
444
|
+
- spec/factories/dscf/core/users.rb
|
438
445
|
- spec/factories/dscf/marketplace/categories.rb
|
446
|
+
- spec/factories/dscf/marketplace/listings.rb
|
439
447
|
- spec/factories/dscf/marketplace/products.rb
|
448
|
+
- spec/factories/dscf/marketplace/supplier_products.rb
|
440
449
|
- spec/factories/dscf/marketplace/unit_conversions.rb
|
441
450
|
- spec/factories/dscf/marketplace/units.rb
|
442
451
|
homepage: https://mksaddis.com/
|