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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 483c018a55aced4c97a7dc9443c45721ba6571dd16100736e36281349bdb65a3
4
- data.tar.gz: 49feba6deeec8f69dd7ad693e61c7f6e8c648480b35a8da2d97acd3ddf9152db
3
+ metadata.gz: f6b077453f450386b96a2df3aac342c13fe4ec2bc97d4e34fa48b1e4918df3ed
4
+ data.tar.gz: 837589f60812fcf77b8a9958b344ec274458434ba63e695538746165349af8dd
5
5
  SHA512:
6
- metadata.gz: 72d2b07581b5bbc8942c0b133d7a01b81be9238adc3a303a68c60f421a89145cf7d634c07fd77f7f2fa7b637d3ade0dd39f687442d7c678edc22edd52bc9b694
7
- data.tar.gz: 4ac74190a143f232210958073b6720c5142da6f15052275121384dd162c08ea93f68f3e86ec59ddc2b161f5e745fdb9a7cc680a6f445d469bacf8b964300d42c
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
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Marketplace
3
- VERSION = "0.1.4".freeze
3
+ VERSION = "0.1.5".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :dscf_core_business_type, class: 'Dscf::Core::BusinessType' do
3
+ sequence(:name) { |n| "Business Type #{n}" }
4
+ end
5
+ 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,8 @@
1
+ FactoryBot.define do
2
+ factory :dscf_core_user, class: 'Dscf::Core::User' do
3
+ sequence(:email) { |n| "user#{n}@example.com" }
4
+ sequence(:phone) { |n| "+25191112345#{n}" }
5
+ temp_password { false }
6
+ password_digest { "password_digest" }
7
+ end
8
+ 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
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/