dscf-marketplace 0.1.8 → 0.1.9

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/dscf/marketplace/application_controller.rb +2 -0
  3. data/app/controllers/dscf/marketplace/categories_controller.rb +26 -0
  4. data/app/controllers/dscf/marketplace/listings_controller.rb +55 -0
  5. data/app/controllers/dscf/marketplace/orders_controller.rb +58 -0
  6. data/app/controllers/dscf/marketplace/products_controller.rb +30 -0
  7. data/app/controllers/dscf/marketplace/quotations_controller.rb +56 -0
  8. data/app/controllers/dscf/marketplace/request_for_quotations_controller.rb +46 -0
  9. data/app/models/dscf/marketplace/category.rb +9 -0
  10. data/app/models/dscf/marketplace/delivery_order.rb +9 -0
  11. data/app/models/dscf/marketplace/delivery_order_item.rb +9 -0
  12. data/app/models/dscf/marketplace/delivery_vehicle.rb +9 -0
  13. data/app/models/dscf/marketplace/listing.rb +9 -0
  14. data/app/models/dscf/marketplace/order.rb +9 -0
  15. data/app/models/dscf/marketplace/order_item.rb +9 -0
  16. data/app/models/dscf/marketplace/product.rb +9 -0
  17. data/app/models/dscf/marketplace/quotation.rb +9 -0
  18. data/app/models/dscf/marketplace/quotation_item.rb +10 -3
  19. data/app/models/dscf/marketplace/request_for_quotation.rb +9 -0
  20. data/app/models/dscf/marketplace/rfq_item.rb +9 -0
  21. data/app/models/dscf/marketplace/supplier_product.rb +9 -0
  22. data/app/models/dscf/marketplace/unit.rb +9 -0
  23. data/app/models/dscf/marketplace/unit_conversion.rb +9 -0
  24. data/app/serializers/dscf/marketplace/category_serializer.rb +11 -0
  25. data/app/serializers/dscf/marketplace/listing_serializer.rb +13 -0
  26. data/app/serializers/dscf/marketplace/order_serializer.rb +15 -0
  27. data/app/serializers/dscf/marketplace/product_serializer.rb +13 -0
  28. data/app/serializers/dscf/marketplace/quotation_serializer.rb +14 -0
  29. data/app/serializers/dscf/marketplace/request_for_quotation_serializer.rb +13 -0
  30. data/config/locales/en.yml +254 -0
  31. data/config/routes.rb +85 -0
  32. data/lib/dscf/marketplace/version.rb +1 -1
  33. metadata +14 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bbdcc2258fee7a63ff11ba8c87e73a47923e8dbb6d9737e55d6e3e9d7002822
4
- data.tar.gz: 184a09306eb3c9de61c2e9edc82cdd49ed735e7bf91acae09b5ace7cd7e9f3a1
3
+ metadata.gz: e5af5705a5f167b0e7f9f34ae086a62f92528d0634e53ca1b50e1ddd0894934b
4
+ data.tar.gz: c53e6675625b7a1225ed8cdaaf977e940325ff9d9fe934f84a47517b22b82302
5
5
  SHA512:
6
- metadata.gz: 503e6dcdb6f209cbc278219572beb1deadbbeff8910e979914b4cd316e176528bc91130b4917bc874e3de36afb9e0f4c56978ecc3aa0dd54f4e175ee8cd2a071
7
- data.tar.gz: e2790cb38d3a76cff511631c8b4fc7ae4b277e8faa2459241379ba3127438b242449438d363e5976dda72aa90a4d3b354e091ebf3d699bf4afb3e48a504689ef
6
+ metadata.gz: 69d7b1dc54ca8c0df0177243a8a9c2b9e410348b7aaf53464890c07f90c2e13a0c9313805992db5e7f80962c771cde51ab7889046fb93a7ad7c4d07c532880ad
7
+ data.tar.gz: c00490bed736cc44c717edc3cbb64de8f2ebac369fd6f1ec98ecf24f44d4c00d07b52aeda5062d04663ecd079948890d0fe160721c2f2295272790b588bde568
@@ -1,6 +1,8 @@
1
1
  module Dscf
2
2
  module Marketplace
3
3
  class ApplicationController < ActionController::API
4
+ include Dscf::Core::JsonResponse
5
+ include Dscf::Core::Authenticatable
4
6
  end
5
7
  end
6
8
  end
@@ -0,0 +1,26 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class CategoriesController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ private
7
+
8
+ def model_params
9
+ params.require(:category).permit(:name, :description, :parent_id)
10
+ end
11
+
12
+ def eager_loaded_associations
13
+ [ :parent, :subcategories, :products ]
14
+ end
15
+
16
+ def default_serializer_includes
17
+ {
18
+ index: [ :parent ],
19
+ show: [ :parent, :subcategories, :products ],
20
+ create: [ :parent ],
21
+ update: [ :parent ]
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,55 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class ListingsController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ def activate
7
+ @obj = find_record
8
+ if @obj.update(status: :active)
9
+ render_success("listings.success.activated", data: @obj)
10
+ else
11
+ render_error("listings.errors.activate_failed")
12
+ end
13
+ end
14
+
15
+ def pause
16
+ @obj = find_record
17
+ if @obj.update(status: :paused)
18
+ render_success("listings.success.paused", data: @obj)
19
+ else
20
+ render_error("listings.errors.pause_failed")
21
+ end
22
+ end
23
+
24
+ def sold_out
25
+ @obj = find_record
26
+ if @obj.update(status: :sold_out)
27
+ render_success("listings.success.sold_out", data: @obj)
28
+ else
29
+ render_error("listings.errors.sold_out_failed")
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def model_params
36
+ params.require(:listing).permit(
37
+ :business_id, :supplier_product_id, :price, :quantity, :status
38
+ )
39
+ end
40
+
41
+ def eager_loaded_associations
42
+ [ :business, :supplier_product, :order_items ]
43
+ end
44
+
45
+ def default_serializer_includes
46
+ {
47
+ index: [ :business, :supplier_product ],
48
+ show: [ :business, :supplier_product, :order_items ],
49
+ create: [ :business, :supplier_product ],
50
+ update: [ :business, :supplier_product ]
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class OrdersController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ def confirm
7
+ @obj = find_record
8
+ if @obj.confirm!
9
+ render_success("orders.success.confirmed", data: @obj)
10
+ else
11
+ render_error("orders.errors.confirm_failed")
12
+ end
13
+ end
14
+
15
+ def cancel
16
+ @obj = find_record
17
+ if @obj.update(status: :cancelled)
18
+ @obj.order_items.update_all(status: OrderItem.statuses[:cancelled])
19
+ render_success("orders.success.cancelled", data: @obj)
20
+ else
21
+ render_error("orders.errors.cancel_failed")
22
+ end
23
+ end
24
+
25
+ def complete
26
+ @obj = find_record
27
+ if @obj.can_be_completed? && @obj.update(status: :completed)
28
+ @obj.order_items.update_all(status: OrderItem.statuses[:completed])
29
+ render_success("orders.success.completed", data: @obj)
30
+ else
31
+ render_error("orders.errors.complete_failed")
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def model_params
38
+ params.require(:order).permit(
39
+ :quotation_id, :listing_id, :user_id, :delivery_order_id,
40
+ :order_type, :status, :fulfillment_type
41
+ )
42
+ end
43
+
44
+ def eager_loaded_associations
45
+ [ :quotation, :listing, :user, :delivery_order, :order_items ]
46
+ end
47
+
48
+ def default_serializer_includes
49
+ {
50
+ index: [ :user, :quotation, :listing ],
51
+ show: [ :user, :quotation, :listing, :delivery_order, :order_items ],
52
+ create: [ :user, :quotation, :listing ],
53
+ update: [ :user, :quotation, :listing ]
54
+ }
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class ProductsController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ private
7
+
8
+ def model_params
9
+ params.require(:product).permit(
10
+ :sku, :name, :description, :category_id, :unit_id,
11
+ :base_price, :base_quantity, :business_only,
12
+ :thumbnail, images: []
13
+ )
14
+ end
15
+
16
+ def eager_loaded_associations
17
+ [ :category, :unit, :supplier_products ]
18
+ end
19
+
20
+ def default_serializer_includes
21
+ {
22
+ index: [ :category, :unit ],
23
+ show: [ :category, :unit, :supplier_products ],
24
+ create: [ :category, :unit ],
25
+ update: [ :category, :unit ]
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,56 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class QuotationsController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ def accept
7
+ @obj = find_record
8
+ if @obj.accept!
9
+ render_success("quotations.success.accepted", data: @obj)
10
+ else
11
+ render_error("quotations.errors.accept_failed")
12
+ end
13
+ end
14
+
15
+ def reject
16
+ @obj = find_record
17
+ if @obj.reject!
18
+ render_success("quotations.success.rejected", data: @obj)
19
+ else
20
+ render_error("quotations.errors.reject_failed")
21
+ end
22
+ end
23
+
24
+ def send_quotation
25
+ @obj = find_record
26
+ if @obj.send_quotation!
27
+ render_success("quotations.success.sent", data: @obj)
28
+ else
29
+ render_error("quotations.errors.send_failed")
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def model_params
36
+ params.require(:quotation).permit(
37
+ :request_for_quotation_id, :business_id, :total_price,
38
+ :delivery_date, :valid_until, :status, :notes
39
+ )
40
+ end
41
+
42
+ def eager_loaded_associations
43
+ [ :request_for_quotation, :business, :quotation_items, :order ]
44
+ end
45
+
46
+ def default_serializer_includes
47
+ {
48
+ index: [ :request_for_quotation, :business ],
49
+ show: [ :request_for_quotation, :business, :quotation_items, :order ],
50
+ create: [ :request_for_quotation, :business ],
51
+ update: [ :request_for_quotation, :business ]
52
+ }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class RequestForQuotationsController < ApplicationController
4
+ include Dscf::Core::Common
5
+
6
+ def send_rfq
7
+ @obj = find_record
8
+ if @obj.draft? && @obj.update(status: :sent)
9
+ render_success("request_for_quotations.success.sent", data: @obj)
10
+ else
11
+ render_error("request_for_quotations.errors.send_failed")
12
+ end
13
+ end
14
+
15
+ def close
16
+ @obj = find_record
17
+ if (@obj.sent? || @obj.responded?) && @obj.update(status: :closed)
18
+ render_success("request_for_quotations.success.closed", data: @obj)
19
+ else
20
+ render_error("request_for_quotations.errors.close_failed")
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def model_params
27
+ params.require(:request_for_quotation).permit(
28
+ :user_id, :selected_quotation_id, :status, :notes
29
+ )
30
+ end
31
+
32
+ def eager_loaded_associations
33
+ [ :user, :selected_quotation, :rfq_items, :quotations ]
34
+ end
35
+
36
+ def default_serializer_includes
37
+ {
38
+ index: [ :user ],
39
+ show: [ :user, :selected_quotation, :rfq_items, :quotations ],
40
+ create: [ :user ],
41
+ update: [ :user ]
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -12,6 +12,15 @@ module Dscf
12
12
 
13
13
  scope :root_categories, -> { where(parent_id: nil) }
14
14
 
15
+ # Ransack configuration for secure filtering
16
+ def self.ransackable_attributes(_auth_object = nil)
17
+ %w[id name description parent_id created_at updated_at]
18
+ end
19
+
20
+ def self.ransackable_associations(_auth_object = nil)
21
+ %w[parent subcategories products]
22
+ end
23
+
15
24
  def root?
16
25
  parent_id.nil?
17
26
  end
@@ -18,6 +18,15 @@ module Dscf::Marketplace
18
18
 
19
19
  before_save :calculate_actual_delivery_price, if: :status_changed?
20
20
 
21
+ # Ransack configuration for secure filtering
22
+ def self.ransackable_attributes(_auth_object = nil)
23
+ %w[id driver_id pickup_address_id delivery_vehicle_id status vehicle_type estimated_delivery_price actual_delivery_price estimated_delivery_time actual_delivery_time delivery_notes created_at updated_at]
24
+ end
25
+
26
+ def self.ransackable_associations(_auth_object = nil)
27
+ %w[driver pickup_address delivery_vehicle delivery_order_items marketplace_orders]
28
+ end
29
+
21
30
  def pickup!
22
31
  return false unless assigned?
23
32
  update!(status: :picked_up, actual_delivery_time: Time.current)
@@ -20,6 +20,15 @@ module Dscf::Marketplace
20
20
 
21
21
  before_save :calculate_verification_totals
22
22
 
23
+ # Ransack configuration for secure filtering
24
+ def self.ransackable_attributes(_auth_object = nil)
25
+ %w[id delivery_order_id order_item_id pickup_address_id dropoff_address_id quantity status pickup_verified_quantity dropoff_verified_quantity damaged_quantity missing_quantity receiver_confirmed_by receiver_confirmed_at receiver_notes handoff_checklist_completed created_at updated_at]
26
+ end
27
+
28
+ def self.ransackable_associations(_auth_object = nil)
29
+ %w[delivery_order order_item pickup_address dropoff_address]
30
+ end
31
+
23
32
  def pending?
24
33
  status == "pending"
25
34
  end
@@ -14,6 +14,15 @@ module Dscf
14
14
  validates :model, length: {maximum: 50}, allow_blank: true
15
15
  validates :color, length: {maximum: 30}, allow_blank: true
16
16
 
17
+ # Ransack configuration for secure filtering
18
+ def self.ransackable_attributes(_auth_object = nil)
19
+ %w[id driver_id plate_number vehicle_type year brand model color created_at updated_at]
20
+ end
21
+
22
+ def self.ransackable_associations(_auth_object = nil)
23
+ %w[driver delivery_orders]
24
+ end
25
+
17
26
  def motorcycle?
18
27
  vehicle_type == "motorcycle"
19
28
  end
@@ -21,6 +21,15 @@ module Dscf::Marketplace
21
21
  scope :by_business, ->(business_id) { where(business_id: business_id) }
22
22
  scope :owned_by, ->(business) { where(business: business) }
23
23
 
24
+ # Ransack configuration for secure filtering
25
+ def self.ransackable_attributes(_auth_object = nil)
26
+ %w[id business_id supplier_product_id price quantity status created_at updated_at]
27
+ end
28
+
29
+ def self.ransackable_associations(_auth_object = nil)
30
+ %w[business supplier_product order_items]
31
+ end
32
+
24
33
  # Custom methods
25
34
  def total_value
26
35
  price * quantity
@@ -18,6 +18,15 @@ module Dscf::Marketplace
18
18
 
19
19
  before_save :calculate_total_amount
20
20
 
21
+ # Ransack configuration for secure filtering
22
+ def self.ransackable_attributes(_auth_object = nil)
23
+ %w[id quotation_id listing_id user_id delivery_order_id order_type status fulfillment_type total_amount created_at updated_at]
24
+ end
25
+
26
+ def self.ransackable_associations(_auth_object = nil)
27
+ %w[quotation listing user delivery_order order_items]
28
+ end
29
+
21
30
  def self.create_from_quotation(quotation)
22
31
  return nil unless quotation.accepted?
23
32
 
@@ -15,6 +15,15 @@ module Dscf::Marketplace
15
15
  validates :unit, presence: true
16
16
  validate :quotation_item_or_listing_present
17
17
 
18
+ # Ransack configuration for secure filtering
19
+ def self.ransackable_attributes(_auth_object = nil)
20
+ %w[id order_id quotation_item_id listing_id product_id unit_id quantity unit_price status created_at updated_at]
21
+ end
22
+
23
+ def self.ransackable_associations(_auth_object = nil)
24
+ %w[order quotation_item listing product unit]
25
+ end
26
+
18
27
  def subtotal
19
28
  quantity * unit_price
20
29
  end
@@ -27,6 +27,15 @@ module Dscf
27
27
  scope :by_category, ->(category_id) { where(category_id: category_id) }
28
28
  scope :by_unit, ->(unit_id) { where(unit_id: unit_id) }
29
29
 
30
+ # Ransack configuration for secure filtering
31
+ def self.ransackable_attributes(_auth_object = nil)
32
+ %w[id sku name description category_id unit_id base_price base_quantity business_only created_at updated_at]
33
+ end
34
+
35
+ def self.ransackable_associations(_auth_object = nil)
36
+ %w[category unit supplier_products listings order_items rfq_items quotation_items]
37
+ end
38
+
30
39
  def display_name
31
40
  "#{name} (#{sku})"
32
41
  end
@@ -22,6 +22,15 @@ module Dscf
22
22
  scope :valid_quotations, -> { where("valid_until > ?", Time.current) }
23
23
  scope :expired_quotations, -> { where("valid_until <= ?", Time.current) }
24
24
 
25
+ # Ransack configuration for secure filtering
26
+ def self.ransackable_attributes(_auth_object = nil)
27
+ %w[id request_for_quotation_id business_id total_price delivery_date valid_until status notes created_at updated_at]
28
+ end
29
+
30
+ def self.ransackable_associations(_auth_object = nil)
31
+ %w[request_for_quotation business quotation_items order]
32
+ end
33
+
25
34
  def calculate_total_price
26
35
  self.total_price = quotation_items.sum(&:subtotal).to_f
27
36
  end
@@ -6,8 +6,6 @@ module Dscf
6
6
  belongs_to :product, class_name: "Dscf::Marketplace::Product"
7
7
  belongs_to :unit, class_name: "Dscf::Marketplace::Unit"
8
8
 
9
-
10
-
11
9
  validates :quotation_id, presence: true
12
10
  validates :rfq_item_id, presence: true
13
11
  validates :product_id, presence: true
@@ -28,6 +26,15 @@ module Dscf
28
26
  scope :by_product, ->(product_id) { where(product_id: product_id) }
29
27
  scope :by_unit, ->(unit_id) { where(unit_id: unit_id) }
30
28
 
29
+ # Ransack configuration for secure filtering
30
+ def self.ransackable_attributes(_auth_object = nil)
31
+ %w[id quotation_id rfq_item_id product_id unit_id quantity unit_price subtotal created_at updated_at]
32
+ end
33
+
34
+ def self.ransackable_associations(_auth_object = nil)
35
+ %w[quotation rfq_item product unit]
36
+ end
37
+
31
38
  def product_name
32
39
  product&.name
33
40
  end
@@ -70,7 +77,7 @@ module Dscf
70
77
  return false unless rfq_item
71
78
 
72
79
  product_id == rfq_item.product_id &&
73
- unit_id == rfq_item.unit_id
80
+ unit_id == rfq_item.unit_id
74
81
  end
75
82
 
76
83
  def can_create_order?
@@ -14,6 +14,15 @@ module Dscf
14
14
  validate :selected_quotation_belongs_to_this_rfq
15
15
  scope :by_user, ->(user_id) { where(user_id: user_id) }
16
16
 
17
+ # Ransack configuration for secure filtering
18
+ def self.ransackable_attributes(_auth_object = nil)
19
+ %w[id user_id selected_quotation_id status notes created_at updated_at]
20
+ end
21
+
22
+ def self.ransackable_associations(_auth_object = nil)
23
+ %w[user selected_quotation rfq_items quotations]
24
+ end
25
+
17
26
  def draft?
18
27
  status == "draft"
19
28
  end
@@ -18,6 +18,15 @@ module Dscf
18
18
  scope :by_product, ->(product_id) { where(product_id: product_id) }
19
19
  scope :by_unit, ->(unit_id) { where(unit_id: unit_id) }
20
20
 
21
+ # Ransack configuration for secure filtering
22
+ def self.ransackable_attributes(_auth_object = nil)
23
+ %w[id request_for_quotation_id product_id unit_id quantity notes created_at updated_at]
24
+ end
25
+
26
+ def self.ransackable_associations(_auth_object = nil)
27
+ %w[request_for_quotation product unit quotation_items]
28
+ end
29
+
21
30
  def product_name
22
31
  product&.name
23
32
  end
@@ -22,6 +22,15 @@ module Dscf::Marketplace
22
22
  scope :by_business, ->(business_id) { where(business_id: business_id) }
23
23
  scope :by_product, ->(product_id) { where(product_id: product_id) }
24
24
 
25
+ # Ransack configuration for secure filtering
26
+ def self.ransackable_attributes(_auth_object = nil)
27
+ %w[id business_id product_id supplier_price available_quantity minimum_order_quantity status created_at updated_at]
28
+ end
29
+
30
+ def self.ransackable_associations(_auth_object = nil)
31
+ %w[business product listings order_items]
32
+ end
33
+
25
34
  # Custom methods
26
35
  def in_stock?
27
36
  available_quantity > 0
@@ -24,6 +24,15 @@ module Dscf
24
24
 
25
25
  scope :by_type, ->(type) { where(unit_type: unit_types[type]) }
26
26
 
27
+ # Ransack configuration for secure filtering
28
+ def self.ransackable_attributes(_auth_object = nil)
29
+ %w[id code name unit_type created_at updated_at]
30
+ end
31
+
32
+ def self.ransackable_associations(_auth_object = nil)
33
+ %w[unit_conversions products supplier_products listings order_items rfq_items quotation_items]
34
+ end
35
+
27
36
  def display_name
28
37
  "#{name} (#{code})"
29
38
  end
@@ -11,6 +11,15 @@ module Dscf
11
11
 
12
12
  validate :units_must_be_different
13
13
 
14
+ # Ransack configuration for secure filtering
15
+ def self.ransackable_attributes(_auth_object = nil)
16
+ %w[id from_unit_id to_unit_id conversion_factor notes created_at updated_at]
17
+ end
18
+
19
+ def self.ransackable_associations(_auth_object = nil)
20
+ %w[from_unit to_unit]
21
+ end
22
+
14
23
  def units_must_be_different
15
24
  return unless from_unit_id && to_unit_id
16
25
 
@@ -0,0 +1,11 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class CategorySerializer < ActiveModel::Serializer
4
+ attributes :id, :name, :description, :parent_id, :created_at, :updated_at
5
+
6
+ belongs_to :parent, serializer: CategorySerializer
7
+ has_many :subcategories, serializer: CategorySerializer
8
+ has_many :products
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class ListingSerializer < ActiveModel::Serializer
4
+ attributes :id, :business_id, :supplier_product_id, :price, :quantity,
5
+ :status, :created_at, :updated_at, :total_value, :margin,
6
+ :margin_percentage, :available?
7
+
8
+ belongs_to :business
9
+ belongs_to :supplier_product
10
+ has_many :order_items
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class OrderSerializer < ActiveModel::Serializer
4
+ attributes :id, :quotation_id, :listing_id, :user_id, :delivery_order_id,
5
+ :order_type, :status, :fulfillment_type, :total_amount,
6
+ :created_at, :updated_at
7
+
8
+ belongs_to :quotation
9
+ belongs_to :listing
10
+ belongs_to :user
11
+ belongs_to :delivery_order
12
+ has_many :order_items
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class ProductSerializer < ActiveModel::Serializer
4
+ attributes :id, :sku, :name, :description, :category_id, :unit_id,
5
+ :base_price, :base_quantity, :business_only, :created_at, :updated_at,
6
+ :display_name, :price_per_unit, :thumbnail_url, :images_urls
7
+
8
+ belongs_to :category
9
+ belongs_to :unit
10
+ has_many :supplier_products
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class QuotationSerializer < ActiveModel::Serializer
4
+ attributes :id, :request_for_quotation_id, :business_id, :total_price,
5
+ :delivery_date, :valid_until, :status, :notes, :created_at,
6
+ :updated_at, :days_until_expiry, :delivery_in_days, :complete?
7
+
8
+ belongs_to :request_for_quotation
9
+ belongs_to :business
10
+ has_many :quotation_items
11
+ has_one :order
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Dscf
2
+ module Marketplace
3
+ class RequestForQuotationSerializer < ActiveModel::Serializer
4
+ attributes :id, :user_id, :selected_quotation_id, :status, :notes,
5
+ :created_at, :updated_at, :total_items, :has_responses?
6
+
7
+ belongs_to :user
8
+ belongs_to :selected_quotation
9
+ has_many :rfq_items
10
+ has_many :quotations
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,254 @@
1
+ # DSCF Marketplace Locale File
2
+ # This file contains I18n messages for automatic message resolution
3
+ # Pattern: {model_name}.{success|errors}.{action_name}
4
+
5
+ en:
6
+ # Core Models
7
+ category:
8
+ success:
9
+ index: "Categories retrieved successfully"
10
+ show: "Category details retrieved successfully"
11
+ create: "Category created successfully"
12
+ update: "Category updated successfully"
13
+ destroy: "Category deleted successfully"
14
+ errors:
15
+ index: "Failed to retrieve categories"
16
+ show: "Failed to retrieve category details"
17
+ create: "Failed to create category"
18
+ update: "Failed to update category"
19
+ destroy: "Failed to delete category"
20
+
21
+ product:
22
+ success:
23
+ index: "Products retrieved successfully"
24
+ show: "Product details retrieved successfully"
25
+ create: "Product created successfully"
26
+ update: "Product updated successfully"
27
+ destroy: "Product deleted successfully"
28
+ errors:
29
+ index: "Failed to retrieve products"
30
+ show: "Failed to retrieve product details"
31
+ create: "Failed to create product"
32
+ update: "Failed to update product"
33
+ destroy: "Failed to delete product"
34
+
35
+ unit:
36
+ success:
37
+ index: "Units retrieved successfully"
38
+ show: "Unit details retrieved successfully"
39
+ create: "Unit created successfully"
40
+ update: "Unit updated successfully"
41
+ destroy: "Unit deleted successfully"
42
+ errors:
43
+ index: "Failed to retrieve units"
44
+ show: "Failed to retrieve unit details"
45
+ create: "Failed to create unit"
46
+ update: "Failed to update unit"
47
+ destroy: "Failed to delete unit"
48
+
49
+ unit_conversion:
50
+ success:
51
+ index: "Unit conversions retrieved successfully"
52
+ show: "Unit conversion details retrieved successfully"
53
+ create: "Unit conversion created successfully"
54
+ update: "Unit conversion updated successfully"
55
+ destroy: "Unit conversion deleted successfully"
56
+ errors:
57
+ index: "Failed to retrieve unit conversions"
58
+ show: "Failed to retrieve unit conversion details"
59
+ create: "Failed to create unit conversion"
60
+ update: "Failed to update unit conversion"
61
+ destroy: "Failed to delete unit conversion"
62
+
63
+ # Trading Models
64
+ supplier_product:
65
+ success:
66
+ index: "Supplier products retrieved successfully"
67
+ show: "Supplier product details retrieved successfully"
68
+ create: "Supplier product created successfully"
69
+ update: "Supplier product updated successfully"
70
+ destroy: "Supplier product deleted successfully"
71
+ errors:
72
+ index: "Failed to retrieve supplier products"
73
+ show: "Failed to retrieve supplier product details"
74
+ create: "Failed to create supplier product"
75
+ update: "Failed to update supplier product"
76
+ destroy: "Failed to delete supplier product"
77
+
78
+ listing:
79
+ success:
80
+ index: "Listings retrieved successfully"
81
+ show: "Listing details retrieved successfully"
82
+ create: "Listing created successfully"
83
+ update: "Listing updated successfully"
84
+ destroy: "Listing deleted successfully"
85
+ errors:
86
+ index: "Failed to retrieve listings"
87
+ show: "Failed to retrieve listing details"
88
+ create: "Failed to create listing"
89
+ update: "Failed to update listing"
90
+ destroy: "Failed to delete listing"
91
+
92
+ request_for_quotation:
93
+ success:
94
+ index: "RFQs retrieved successfully"
95
+ show: "RFQ details retrieved successfully"
96
+ create: "RFQ created successfully"
97
+ update: "RFQ updated successfully"
98
+ destroy: "RFQ deleted successfully"
99
+ errors:
100
+ index: "Failed to retrieve RFQs"
101
+ show: "Failed to retrieve RFQ details"
102
+ create: "Failed to create RFQ"
103
+ update: "Failed to update RFQ"
104
+ destroy: "Failed to delete RFQ"
105
+
106
+ rfq_item:
107
+ success:
108
+ index: "RFQ items retrieved successfully"
109
+ show: "RFQ item details retrieved successfully"
110
+ create: "RFQ item created successfully"
111
+ update: "RFQ item updated successfully"
112
+ destroy: "RFQ item deleted successfully"
113
+ errors:
114
+ index: "Failed to retrieve RFQ items"
115
+ show: "Failed to retrieve RFQ item details"
116
+ create: "Failed to create RFQ item"
117
+ update: "Failed to update RFQ item"
118
+ destroy: "Failed to delete RFQ item"
119
+
120
+ quotation:
121
+ success:
122
+ index: "Quotations retrieved successfully"
123
+ show: "Quotation details retrieved successfully"
124
+ create: "Quotation created successfully"
125
+ update: "Quotation updated successfully"
126
+ destroy: "Quotation deleted successfully"
127
+ accept: "Quotation accepted successfully"
128
+ reject: "Quotation rejected successfully"
129
+ send_quotation: "Quotation sent successfully"
130
+ errors:
131
+ index: "Failed to retrieve quotations"
132
+ show: "Failed to retrieve quotation details"
133
+ create: "Failed to create quotation"
134
+ update: "Failed to update quotation"
135
+ destroy: "Failed to delete quotation"
136
+ accept: "Failed to accept quotation"
137
+ reject: "Failed to reject quotation"
138
+ send_quotation: "Failed to send quotation"
139
+
140
+ quotation_item:
141
+ success:
142
+ index: "Quotation items retrieved successfully"
143
+ show: "Quotation item details retrieved successfully"
144
+ create: "Quotation item created successfully"
145
+ update: "Quotation item updated successfully"
146
+ destroy: "Quotation item deleted successfully"
147
+ errors:
148
+ index: "Failed to retrieve quotation items"
149
+ show: "Failed to retrieve quotation item details"
150
+ create: "Failed to create quotation item"
151
+ update: "Failed to update quotation item"
152
+ destroy: "Failed to delete quotation item"
153
+
154
+ # Order Models
155
+ order:
156
+ success:
157
+ index: "Orders retrieved successfully"
158
+ show: "Order details retrieved successfully"
159
+ create: "Order created successfully"
160
+ update: "Order updated successfully"
161
+ destroy: "Order deleted successfully"
162
+ confirm: "Order confirmed successfully"
163
+ cancel: "Order cancelled successfully"
164
+ errors:
165
+ index: "Failed to retrieve orders"
166
+ show: "Failed to retrieve order details"
167
+ create: "Failed to create order"
168
+ update: "Failed to update order"
169
+ destroy: "Failed to delete order"
170
+ confirm: "Failed to confirm order"
171
+ cancel: "Failed to cancel order"
172
+
173
+ order_item:
174
+ success:
175
+ index: "Order items retrieved successfully"
176
+ show: "Order item details retrieved successfully"
177
+ create: "Order item created successfully"
178
+ update: "Order item updated successfully"
179
+ destroy: "Order item deleted successfully"
180
+ errors:
181
+ index: "Failed to retrieve order items"
182
+ show: "Failed to retrieve order item details"
183
+ create: "Failed to create order item"
184
+ update: "Failed to update order item"
185
+ destroy: "Failed to delete order item"
186
+
187
+ # Delivery Models
188
+ delivery_order:
189
+ success:
190
+ index: "Delivery orders retrieved successfully"
191
+ show: "Delivery order details retrieved successfully"
192
+ create: "Delivery order created successfully"
193
+ update: "Delivery order updated successfully"
194
+ destroy: "Delivery order deleted successfully"
195
+ pickup: "Delivery order picked up successfully"
196
+ start_delivery: "Delivery started successfully"
197
+ complete_delivery: "Delivery completed successfully"
198
+ mark_failed: "Delivery marked as failed"
199
+ errors:
200
+ index: "Failed to retrieve delivery orders"
201
+ show: "Failed to retrieve delivery order details"
202
+ create: "Failed to create delivery order"
203
+ update: "Failed to update delivery order"
204
+ destroy: "Failed to delete delivery order"
205
+ pickup: "Failed to pickup delivery order"
206
+ start_delivery: "Failed to start delivery"
207
+ complete_delivery: "Failed to complete delivery"
208
+ mark_failed: "Failed to mark delivery as failed"
209
+
210
+ delivery_order_item:
211
+ success:
212
+ index: "Delivery order items retrieved successfully"
213
+ show: "Delivery order item details retrieved successfully"
214
+ create: "Delivery order item created successfully"
215
+ update: "Delivery order item updated successfully"
216
+ destroy: "Delivery order item deleted successfully"
217
+ receiver_confirm: "Item confirmed by receiver successfully"
218
+ report_issue: "Issue reported successfully"
219
+ dispute_delivery: "Delivery disputed successfully"
220
+ errors:
221
+ index: "Failed to retrieve delivery order items"
222
+ show: "Failed to retrieve delivery order item details"
223
+ create: "Failed to create delivery order item"
224
+ update: "Failed to update delivery order item"
225
+ destroy: "Failed to delete delivery order item"
226
+ receiver_confirm: "Failed to confirm item"
227
+ report_issue: "Failed to report issue"
228
+ dispute_delivery: "Failed to dispute delivery"
229
+
230
+ delivery_vehicle:
231
+ success:
232
+ index: "Delivery vehicles retrieved successfully"
233
+ show: "Delivery vehicle details retrieved successfully"
234
+ create: "Delivery vehicle created successfully"
235
+ update: "Delivery vehicle updated successfully"
236
+ destroy: "Delivery vehicle deleted successfully"
237
+ errors:
238
+ index: "Failed to retrieve delivery vehicles"
239
+ show: "Failed to retrieve delivery vehicle details"
240
+ create: "Failed to create delivery vehicle"
241
+ update: "Failed to update delivery vehicle"
242
+ destroy: "Failed to delete delivery vehicle"
243
+
244
+ # Global fallback messages
245
+ operations:
246
+ success:
247
+ completed: "Operation completed successfully"
248
+ errors:
249
+ failed: "Operation failed"
250
+
251
+ errors:
252
+ validation_failed: "Validation failed"
253
+ operation_failed: "Operation failed"
254
+ record_not_found: "Record not found"
data/config/routes.rb CHANGED
@@ -1,2 +1,87 @@
1
1
  Dscf::Marketplace::Engine.routes.draw do
2
+ # Core Models
3
+ resources :categories do
4
+ resources :products, only: [ :index ]
5
+ get "subcategories", on: :member
6
+ end
7
+
8
+ resources :products do
9
+ resources :listings, only: [ :index ]
10
+ get "supplier_products", on: :member
11
+ end
12
+
13
+ resources :units do
14
+ resources :unit_conversions, only: [ :index ]
15
+ end
16
+
17
+ resources :unit_conversions
18
+
19
+ # Trading Models
20
+ resources :supplier_products do
21
+ resources :listings, only: [ :index ]
22
+ end
23
+
24
+ resources :listings do
25
+ member do
26
+ post "activate"
27
+ post "pause"
28
+ post "sold_out"
29
+ end
30
+ end
31
+
32
+ # RFQ System
33
+ resources :request_for_quotations do
34
+ resources :rfq_items, only: [ :index, :create ]
35
+ resources :quotations, only: [ :index ]
36
+ member do
37
+ post "send_rfq"
38
+ post "close"
39
+ end
40
+ end
41
+
42
+ resources :rfq_items, only: [ :show, :update, :destroy ]
43
+
44
+ resources :quotations do
45
+ resources :quotation_items, only: [ :index, :create ]
46
+ member do
47
+ post "accept"
48
+ post "reject"
49
+ post "send_quotation"
50
+ end
51
+ end
52
+
53
+ resources :quotation_items, only: [ :show, :update, :destroy ]
54
+
55
+ # Order Management
56
+ resources :orders do
57
+ resources :order_items, only: [ :index ]
58
+ member do
59
+ post "confirm"
60
+ post "cancel"
61
+ post "complete"
62
+ end
63
+ end
64
+
65
+ resources :order_items, only: [ :show, :update ]
66
+
67
+ # Delivery System
68
+ resources :delivery_orders do
69
+ resources :delivery_order_items, only: [ :index ]
70
+ member do
71
+ post "pickup"
72
+ post "start_delivery"
73
+ post "complete_delivery"
74
+ post "mark_failed"
75
+ end
76
+ end
77
+
78
+ resources :delivery_order_items, only: [ :show, :update ] do
79
+ member do
80
+ post "receiver_confirm"
81
+ post "report_issue"
82
+ post "dispute_delivery"
83
+ end
84
+ end
85
+
86
+ resources :delivery_vehicles
2
87
  end
@@ -1,5 +1,5 @@
1
1
  module Dscf
2
2
  module Marketplace
3
- VERSION = "0.1.8".freeze
3
+ VERSION = "0.1.9".freeze
4
4
  end
5
5
  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.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asrat
@@ -417,6 +417,12 @@ files:
417
417
  - MIT-LICENSE
418
418
  - Rakefile
419
419
  - app/controllers/dscf/marketplace/application_controller.rb
420
+ - app/controllers/dscf/marketplace/categories_controller.rb
421
+ - app/controllers/dscf/marketplace/listings_controller.rb
422
+ - app/controllers/dscf/marketplace/orders_controller.rb
423
+ - app/controllers/dscf/marketplace/products_controller.rb
424
+ - app/controllers/dscf/marketplace/quotations_controller.rb
425
+ - app/controllers/dscf/marketplace/request_for_quotations_controller.rb
420
426
  - app/jobs/dscf/marketplace/application_job.rb
421
427
  - app/mailers/dscf/marketplace/application_mailer.rb
422
428
  - app/models/dscf/marketplace/application_record.rb
@@ -435,6 +441,13 @@ files:
435
441
  - app/models/dscf/marketplace/supplier_product.rb
436
442
  - app/models/dscf/marketplace/unit.rb
437
443
  - app/models/dscf/marketplace/unit_conversion.rb
444
+ - app/serializers/dscf/marketplace/category_serializer.rb
445
+ - app/serializers/dscf/marketplace/listing_serializer.rb
446
+ - app/serializers/dscf/marketplace/order_serializer.rb
447
+ - app/serializers/dscf/marketplace/product_serializer.rb
448
+ - app/serializers/dscf/marketplace/quotation_serializer.rb
449
+ - app/serializers/dscf/marketplace/request_for_quotation_serializer.rb
450
+ - config/locales/en.yml
438
451
  - config/routes.rb
439
452
  - db/migrate/20250827172043_create_dscf_marketplace_categories.rb
440
453
  - db/migrate/20250827173526_update_dscf_marketplace_categories_indexes.rb