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.
- checksums.yaml +4 -4
- data/app/controllers/dscf/marketplace/application_controller.rb +2 -0
- data/app/controllers/dscf/marketplace/categories_controller.rb +26 -0
- data/app/controllers/dscf/marketplace/listings_controller.rb +55 -0
- data/app/controllers/dscf/marketplace/orders_controller.rb +58 -0
- data/app/controllers/dscf/marketplace/products_controller.rb +30 -0
- data/app/controllers/dscf/marketplace/quotations_controller.rb +56 -0
- data/app/controllers/dscf/marketplace/request_for_quotations_controller.rb +46 -0
- data/app/models/dscf/marketplace/category.rb +9 -0
- data/app/models/dscf/marketplace/delivery_order.rb +9 -0
- data/app/models/dscf/marketplace/delivery_order_item.rb +9 -0
- data/app/models/dscf/marketplace/delivery_vehicle.rb +9 -0
- data/app/models/dscf/marketplace/listing.rb +9 -0
- data/app/models/dscf/marketplace/order.rb +9 -0
- data/app/models/dscf/marketplace/order_item.rb +9 -0
- data/app/models/dscf/marketplace/product.rb +9 -0
- data/app/models/dscf/marketplace/quotation.rb +9 -0
- data/app/models/dscf/marketplace/quotation_item.rb +10 -3
- data/app/models/dscf/marketplace/request_for_quotation.rb +9 -0
- data/app/models/dscf/marketplace/rfq_item.rb +9 -0
- data/app/models/dscf/marketplace/supplier_product.rb +9 -0
- data/app/models/dscf/marketplace/unit.rb +9 -0
- data/app/models/dscf/marketplace/unit_conversion.rb +9 -0
- data/app/serializers/dscf/marketplace/category_serializer.rb +11 -0
- data/app/serializers/dscf/marketplace/listing_serializer.rb +13 -0
- data/app/serializers/dscf/marketplace/order_serializer.rb +15 -0
- data/app/serializers/dscf/marketplace/product_serializer.rb +13 -0
- data/app/serializers/dscf/marketplace/quotation_serializer.rb +14 -0
- data/app/serializers/dscf/marketplace/request_for_quotation_serializer.rb +13 -0
- data/config/locales/en.yml +254 -0
- data/config/routes.rb +85 -0
- data/lib/dscf/marketplace/version.rb +1 -1
- metadata +14 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5af5705a5f167b0e7f9f34ae086a62f92528d0634e53ca1b50e1ddd0894934b
|
4
|
+
data.tar.gz: c53e6675625b7a1225ed8cdaaf977e940325ff9d9fe934f84a47517b22b82302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69d7b1dc54ca8c0df0177243a8a9c2b9e410348b7aaf53464890c07f90c2e13a0c9313805992db5e7f80962c771cde51ab7889046fb93a7ad7c4d07c532880ad
|
7
|
+
data.tar.gz: c00490bed736cc44c717edc3cbb64de8f2ebac369fd6f1ec98ecf24f44d4c00d07b52aeda5062d04663ecd079948890d0fe160721c2f2295272790b588bde568
|
@@ -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
|
-
|
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
|
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.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
|