cats_core 1.4.1 → 1.4.4
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/cats/core/commodities_controller.rb +1 -1
- data/app/controllers/cats/core/commodity_categories_controller.rb +5 -0
- data/app/controllers/cats/core/dispatch_plan_items_controller.rb +1 -1
- data/app/controllers/cats/core/dispatch_plans_controller.rb +1 -1
- data/app/controllers/cats/core/dispatch_transactions_controller.rb +1 -1
- data/app/controllers/cats/core/dispatches_controller.rb +1 -1
- data/app/controllers/cats/core/monthly_plans_controller.rb +3 -5
- data/app/controllers/cats/core/stacks_controller.rb +2 -2
- data/app/controllers/cats/core/unit_conversions_controller.rb +13 -0
- data/app/models/cats/core/commodity.rb +1 -22
- data/app/models/cats/core/dispatch_plan.rb +2 -4
- data/app/models/cats/core/dispatch_plan_item.rb +3 -1
- data/app/models/cats/core/gift_certificate.rb +5 -2
- data/app/models/cats/core/location.rb +3 -1
- data/app/models/cats/core/monthly_plan.rb +24 -2
- data/app/models/cats/core/route.rb +9 -1
- data/app/models/cats/core/stack.rb +31 -4
- data/app/models/cats/core/transport_bid.rb +5 -1
- data/app/models/cats/core/transport_bid_item.rb +2 -0
- data/app/models/cats/core/transport_offer.rb +1 -0
- data/app/models/cats/core/unit_conversion.rb +25 -0
- data/app/models/concerns/cats/core/dispatchable.rb +2 -2
- data/app/notifications/cats/core/allocation_notification.rb +2 -2
- data/app/notifications/cats/core/dispatch_notification.rb +1 -1
- data/app/serializers/cats/core/commodity_serializer.rb +2 -2
- data/app/serializers/cats/core/dispatch_plan_serializer.rb +1 -2
- data/app/serializers/cats/core/unit_conversion_serializer.rb +7 -0
- data/app/services/cats/core/stack_service.rb +21 -33
- data/config/routes.rb +3 -1
- data/db/migrate/20210717032602_create_cats_core_gift_certificates.rb +6 -1
- data/db/migrate/20210717033223_create_cats_core_commodities.rb +1 -0
- data/db/migrate/20210718043328_create_cats_core_dispatch_plans.rb +0 -5
- data/db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb +4 -0
- data/db/migrate/20211215121151_create_cats_core_transport_bids.rb +3 -2
- data/db/migrate/20211215124452_create_cats_core_transport_bid_items.rb +4 -0
- data/db/migrate/20211229160125_create_cats_core_transport_offers.rb +2 -0
- data/db/migrate/20220416143416_create_cats_core_unit_conversions.rb +19 -0
- data/lib/cats/core/version.rb +1 -1
- data/spec/factories/cats/core/commodities.rb +1 -0
- data/spec/factories/cats/core/dispatch_plan_items.rb +1 -0
- data/spec/factories/cats/core/dispatch_plans.rb +14 -2
- data/spec/factories/cats/core/gift_certificates.rb +2 -0
- data/spec/factories/cats/core/stacking_rules.rb +3 -3
- data/spec/factories/cats/core/transport_bid_items.rb +1 -0
- data/spec/factories/cats/core/transport_bids.rb +3 -2
- data/spec/factories/cats/core/unit_conversions.rb +7 -0
- metadata +8 -9
- data/app/models/cats/core/allocation.rb +0 -78
- data/app/models/cats/core/allocation_item.rb +0 -42
- data/db/migrate/20210718042823_create_cats_core_allocations.rb +0 -25
- data/db/migrate/20210718043204_create_cats_core_allocation_items.rb +0 -19
- data/spec/factories/cats/core/allocation_items.rb +0 -9
- data/spec/factories/cats/core/allocations.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05ec37047a728927e68df2e0a0ae34dd16cca869cfe658314ea5fb0738ae894b
|
4
|
+
data.tar.gz: 272f1c6cb33e96a8407cab42c3b9bd8b01540156feee9bf4d6012b5b97600b52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19a5247f29b37ca8dc8a0176719b22b924069166168ddcf684a84ca0bcbd45ae170a164516ffada4cb2066b428ece538f89c8daa45bfb2db15bd432fb9676dab
|
7
|
+
data.tar.gz: b41ed1c8028112b527cd21b01821187260ba85ab2647fe7f477422a69f40a72420aed74d6741d3525f5812d110354b85bc12cf23b54163ce921286be1d185e10
|
@@ -34,7 +34,7 @@ module Cats
|
|
34
34
|
def model_params
|
35
35
|
params.require(:payload).permit(:batch_no, :description, :unit_of_measure_id, :source_id,
|
36
36
|
:source_type, :quantity, :best_use_before, :volume_per_metric_ton,
|
37
|
-
:arrival_status)
|
37
|
+
:arrival_status, :shipping_reference)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -9,6 +9,11 @@ module Cats
|
|
9
9
|
render json: { success: true, data: data }
|
10
10
|
end
|
11
11
|
|
12
|
+
def all
|
13
|
+
data = Cats::Core::CommodityCategory.all
|
14
|
+
render json: { success: true, data: data }
|
15
|
+
end
|
16
|
+
|
12
17
|
def root
|
13
18
|
data = Cats::Core::CommodityCategory.roots
|
14
19
|
render json: { success: true, data: serialize(data) }
|
@@ -14,7 +14,7 @@ module Cats
|
|
14
14
|
# user to give us a source.
|
15
15
|
def create_allocation
|
16
16
|
dispatch = Dispatch.find(model_params[:dispatch_id])
|
17
|
-
commodity = dispatch.dispatch_plan_item.
|
17
|
+
commodity = dispatch.dispatch_plan_item.commodity
|
18
18
|
transaction = DispatchTransaction.new(model_params)
|
19
19
|
|
20
20
|
# Fetch supplier stack by commodity
|
@@ -17,12 +17,10 @@ module Cats
|
|
17
17
|
|
18
18
|
def approve
|
19
19
|
plan = Cats::Core::MonthlyPlan.find(params[:id])
|
20
|
-
|
21
|
-
render json: { success: false, error: 'Empty plan cannot be approved.' }, status: :unprocessable_entity
|
22
|
-
return
|
23
|
-
end
|
24
|
-
plan.update(status: Cats::Core::Plan::APPROVED)
|
20
|
+
plan.approve
|
25
21
|
render json: { success: true, data: serialize(plan) }
|
22
|
+
rescue StandardError => e
|
23
|
+
render json: { success: false, error: e.message }, status: :unprocessable_entity
|
26
24
|
end
|
27
25
|
|
28
26
|
def generate
|
@@ -13,9 +13,9 @@ module Cats
|
|
13
13
|
render json: { success: true, data: serialize(query.result) }
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def items_for_location
|
17
17
|
service = StackService.new
|
18
|
-
commodities = service.
|
18
|
+
commodities = service.items_for_location(current_user)
|
19
19
|
render json: { success: true, data: serialize(commodities) }
|
20
20
|
end
|
21
21
|
|
@@ -31,8 +31,6 @@ module Cats
|
|
31
31
|
belongs_to :unit_of_measure
|
32
32
|
belongs_to :source, polymorphic: true
|
33
33
|
|
34
|
-
has_many :allocations
|
35
|
-
|
36
34
|
validates :best_use_before, presence: true
|
37
35
|
validates :batch_no, presence: true, uniqueness: true
|
38
36
|
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
@@ -40,7 +38,7 @@ module Cats
|
|
40
38
|
validates :arrival_status, presence: true, inclusion: { in: ARRIVAL_STATUSES }
|
41
39
|
validates :status, presence: true, inclusion: { in: STATUSES }
|
42
40
|
|
43
|
-
delegate(:abbreviation, to: :unit_of_measure, prefix:
|
41
|
+
delegate(:abbreviation, to: :unit_of_measure, prefix: 'unit')
|
44
42
|
delegate(:reference_no, to: :source, prefix: true)
|
45
43
|
|
46
44
|
def name
|
@@ -74,25 +72,6 @@ module Cats
|
|
74
72
|
end
|
75
73
|
result
|
76
74
|
end
|
77
|
-
|
78
|
-
def allocate(ignore_errors: true)
|
79
|
-
statuses = Allocation.where(commodity_id: id).map(&:allocation_status).uniq
|
80
|
-
unless statuses.count == 1 && statuses[0] == APPROVED
|
81
|
-
return if ignore_errors
|
82
|
-
|
83
|
-
raise(StandardError, 'There are allocations in "Draft" state.')
|
84
|
-
end
|
85
|
-
|
86
|
-
quantity = allocations.sum(:quantity)
|
87
|
-
unless quantity == self.quantity
|
88
|
-
return if ignore_errors
|
89
|
-
|
90
|
-
raise(StandardError, 'Total allocations quantity is not the same as commodity quantity.')
|
91
|
-
end
|
92
|
-
|
93
|
-
self.status = ALLOCATED
|
94
|
-
save!
|
95
|
-
end
|
96
75
|
end
|
97
76
|
end
|
98
77
|
end
|
@@ -8,7 +8,6 @@ module Cats
|
|
8
8
|
belongs_to :dispatchable, polymorphic: true, optional: true
|
9
9
|
belongs_to :prepared_by, class_name: 'Cats::Core::User'
|
10
10
|
belongs_to :approved_by, class_name: 'Cats::Core::User', optional: true
|
11
|
-
belongs_to :commodity
|
12
11
|
|
13
12
|
has_many :dispatch_plan_items
|
14
13
|
|
@@ -16,7 +15,6 @@ module Cats
|
|
16
15
|
validates :status, inclusion: { in: STATUSES }
|
17
16
|
validate :validate_dispatchable, on: :create
|
18
17
|
|
19
|
-
delegate(:batch_no, :name, :quantity, to: :commodity, prefix: true)
|
20
18
|
delegate(:request_reference, to: :dispatchable, allow_nil: true)
|
21
19
|
delegate(:request_quantity, to: :dispatchable, allow_nil: true)
|
22
20
|
|
@@ -44,12 +42,12 @@ module Cats
|
|
44
42
|
|
45
43
|
# Raise error if the total dispatch plan quantity is not equal to the
|
46
44
|
# dispatchable quantity
|
47
|
-
if dispatchable && dispatchable.quantity != quantity
|
45
|
+
if dispatchable.instance_of?(RhnRequest) && dispatchable.quantity != quantity
|
48
46
|
raise(StandardError, 'Requested quantity and plan quantity do not match.')
|
49
47
|
end
|
50
48
|
|
51
49
|
self.status = APPROVED
|
52
|
-
dispatchable&.allocate
|
50
|
+
dispatchable&.allocate if dispatchable.instance_of?(RhnRequest)
|
53
51
|
save!
|
54
52
|
end
|
55
53
|
|
@@ -10,6 +10,8 @@ module Cats
|
|
10
10
|
belongs_to :source, class_name: 'Cats::Core::Location'
|
11
11
|
belongs_to :destination, class_name: 'Cats::Core::Location'
|
12
12
|
belongs_to :dispatch_plan
|
13
|
+
belongs_to :commodity
|
14
|
+
|
13
15
|
has_many :dispatches
|
14
16
|
has_many :hub_authorizations
|
15
17
|
|
@@ -18,7 +20,7 @@ module Cats
|
|
18
20
|
validates :status, presence: true, inclusion: { in: STATUSES }
|
19
21
|
|
20
22
|
delegate(:reference_no, to: :dispatch_plan, prefix: :plan, allow_nil: true)
|
21
|
-
delegate(:
|
23
|
+
delegate(:batch_no, :name, to: :commodity, prefix: true)
|
22
24
|
delegate(:name, to: :source, prefix: true)
|
23
25
|
delegate(:name, to: :destination, prefix: true)
|
24
26
|
delegate(:location_type, to: :source, prefix: true)
|
@@ -4,21 +4,24 @@ module Cats
|
|
4
4
|
belongs_to :donation, optional: true
|
5
5
|
belongs_to :commodity_category
|
6
6
|
belongs_to :unit_of_measure
|
7
|
+
belongs_to :currency
|
7
8
|
belongs_to :destination_warehouse, class_name: 'Cats::Core::Location'
|
8
9
|
|
9
10
|
validates :reference_no, presence: true, uniqueness: true
|
10
|
-
validates :gift_date, :quantity, :requested_by, :
|
11
|
+
validates :gift_date, :quantity, :requested_by, :customs_office, presence: true
|
11
12
|
validates :quantity, numericality: { greater_than: 0 }
|
12
13
|
|
13
14
|
delegate(:name, to: :commodity_category, prefix: true)
|
14
15
|
delegate(:name, to: :destination_warehouse, prefix: true)
|
15
16
|
delegate(:abbreviation, to: :unit_of_measure, prefix: true)
|
17
|
+
delegate(:code, to: :currency, prefix: true)
|
16
18
|
|
17
19
|
before_validation :set_commodity_category
|
18
20
|
after_create :update_donation
|
19
21
|
|
20
22
|
def update_donation
|
21
|
-
|
23
|
+
return unless donation
|
24
|
+
|
22
25
|
return if donation.active
|
23
26
|
|
24
27
|
donation.active = true
|
@@ -4,11 +4,12 @@ module Cats
|
|
4
4
|
REGION = 'Region'.freeze
|
5
5
|
ZONE = 'Zone'.freeze
|
6
6
|
WOREDA = 'Woreda'.freeze
|
7
|
+
FDP = 'Fdp'.freeze
|
7
8
|
KEBELE = 'Kebele'.freeze
|
8
9
|
HUB = 'Hub'.freeze
|
9
10
|
WAREHOUSE = 'Warehouse'.freeze
|
10
11
|
|
11
|
-
LOCATION_TYPES = [REGION, ZONE, WOREDA, KEBELE, HUB, WAREHOUSE].freeze
|
12
|
+
LOCATION_TYPES = [REGION, ZONE, WOREDA, KEBELE, HUB, WAREHOUSE, FDP].freeze
|
12
13
|
|
13
14
|
has_ancestry
|
14
15
|
|
@@ -23,6 +24,7 @@ module Cats
|
|
23
24
|
ZONE => [REGION],
|
24
25
|
WOREDA => [REGION, ZONE],
|
25
26
|
KEBELE => [REGION, ZONE, WOREDA],
|
27
|
+
FDP => [REGION, ZONE, WOREDA],
|
26
28
|
HUB => [REGION, ZONE, WOREDA, KEBELE],
|
27
29
|
WAREHOUSE => [REGION, ZONE, WOREDA, KEBELE, HUB]
|
28
30
|
}
|
@@ -3,6 +3,13 @@ module Cats
|
|
3
3
|
class MonthlyPlan < ApplicationRecord
|
4
4
|
include Dispatchable
|
5
5
|
|
6
|
+
DRAFT = 'Draft'.freeze
|
7
|
+
APPROVED = 'Approved'.freeze
|
8
|
+
RESERVED = 'Reserved'.freeze
|
9
|
+
NEEDS_APPROVED = 'Needs Approved'.freeze
|
10
|
+
|
11
|
+
STATUSES = [DRAFT, APPROVED, RESERVED, NEEDS_APPROVED].freeze
|
12
|
+
|
6
13
|
belongs_to :plan
|
7
14
|
belongs_to :region, class_name: 'Cats::Core::Location'
|
8
15
|
|
@@ -11,7 +18,7 @@ module Cats
|
|
11
18
|
has_many :monthly_rations
|
12
19
|
|
13
20
|
validates :reference_no, presence: true, uniqueness: true
|
14
|
-
validates :status, presence: true, inclusion: { in:
|
21
|
+
validates :status, presence: true, inclusion: { in: MonthlyPlan::STATUSES }
|
15
22
|
validates :no_of_days, :month, presence: true, numericality: { greater_than: 0 }
|
16
23
|
validate :validate_month, :validate_region
|
17
24
|
|
@@ -26,6 +33,21 @@ module Cats
|
|
26
33
|
nil
|
27
34
|
end
|
28
35
|
|
36
|
+
def approve
|
37
|
+
raise(StandardError, 'Plan is not in draft state.') unless status == DRAFT
|
38
|
+
|
39
|
+
raise(StandardError, 'Empty plan cannot be approved.') if monthly_plan_items.count.zero?
|
40
|
+
|
41
|
+
update!(status: APPROVED)
|
42
|
+
end
|
43
|
+
|
44
|
+
def reserve
|
45
|
+
raise(StandardError, 'Plan is not approved.') unless status == APPROVED
|
46
|
+
|
47
|
+
self.status = RESERVED
|
48
|
+
save!
|
49
|
+
end
|
50
|
+
|
29
51
|
def validate_month
|
30
52
|
return unless month
|
31
53
|
|
@@ -35,7 +57,7 @@ module Cats
|
|
35
57
|
def validate_region
|
36
58
|
return unless region
|
37
59
|
|
38
|
-
errors.add(:region, 'is not valid.') unless region.location_type ==
|
60
|
+
errors.add(:region, 'is not valid.') unless region.location_type == Location::REGION
|
39
61
|
end
|
40
62
|
end
|
41
63
|
end
|
@@ -8,7 +8,7 @@ module Cats
|
|
8
8
|
belongs_to :destination, class_name: 'Cats::Core::Location'
|
9
9
|
|
10
10
|
validates :source_id, uniqueness: { scope: :destination_id }
|
11
|
-
validate :validate_region, :validate_source, :validate_destination
|
11
|
+
validate :validate_region, :validate_source, :validate_destination, :validate_route
|
12
12
|
|
13
13
|
delegate(:name, to: :region, prefix: true)
|
14
14
|
|
@@ -35,6 +35,14 @@ module Cats
|
|
35
35
|
|
36
36
|
errors.add(:destination, 'cannot be a region.') if destination.location_type == Location::REGION
|
37
37
|
end
|
38
|
+
|
39
|
+
def validate_route
|
40
|
+
return unless source
|
41
|
+
|
42
|
+
return unless destination
|
43
|
+
|
44
|
+
errors.add(:base, 'Source and destination cannot be the same') if source == destination
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -20,7 +20,8 @@ module Cats
|
|
20
20
|
validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
|
21
21
|
validates :stack_status, inclusion: { in: STACK_STATUSES }
|
22
22
|
validate :validate_coordinates, :validate_dimensions, :validate_distance_from_wall, :validate_overlap,
|
23
|
-
:validate_space_between_stack,
|
23
|
+
:validate_space_between_stack, :validate_max_height, :validate_max_length, :validate_max_width,
|
24
|
+
:validate_distance_from_ceiling, unless: -> { store && store.code == 'SUP-STORE' }
|
24
25
|
|
25
26
|
delegate :batch_no, to: :commodity, prefix: true
|
26
27
|
|
@@ -48,9 +49,9 @@ module Cats
|
|
48
49
|
space_between_stack: 1,
|
49
50
|
distance_from_gangway: 2,
|
50
51
|
distance_from_ceiling: 1,
|
51
|
-
maximum_height:
|
52
|
-
maximum_length:
|
53
|
-
maximum_width:
|
52
|
+
maximum_height: 7,
|
53
|
+
maximum_length: 12,
|
54
|
+
maximum_width: 12,
|
54
55
|
distance_from_wall: 1
|
55
56
|
)
|
56
57
|
rule
|
@@ -92,6 +93,32 @@ module Cats
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
96
|
+
def validate_max_height
|
97
|
+
return unless height
|
98
|
+
|
99
|
+
errors.add(:height, 'exceeds stacking rule height.') if height > stacking_rules.maximum_height
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate_max_length
|
103
|
+
return unless length
|
104
|
+
|
105
|
+
errors.add(:length, 'exceeds stacking rule length.') if length > stacking_rules.maximum_length
|
106
|
+
end
|
107
|
+
|
108
|
+
def validate_max_width
|
109
|
+
return unless width
|
110
|
+
|
111
|
+
errors.add(:width, 'exceeds stacking rule width.') if width > stacking_rules.maximum_width
|
112
|
+
end
|
113
|
+
|
114
|
+
def validate_distance_from_ceiling
|
115
|
+
return unless height && store
|
116
|
+
|
117
|
+
return unless store.height - height < stacking_rules.distance_from_ceiling
|
118
|
+
|
119
|
+
errors.add(:height, 'of stack is close to the ceiling.')
|
120
|
+
end
|
121
|
+
|
95
122
|
# A method that checks if an overlap exists b/n two stacks.
|
96
123
|
# An overlap b/n stacks does not occur if one of the stacks is completely above the other stack or
|
97
124
|
# if one of the stacks is on the left side of the other stack.
|
@@ -16,7 +16,7 @@ module Cats
|
|
16
16
|
belongs_to :transport_plan
|
17
17
|
|
18
18
|
validates :reference_no, presence: true, uniqueness: true
|
19
|
-
validates :start_date, :end_date, :status, :bid_bond_amount, presence: true
|
19
|
+
validates :start_date, :end_date, :opening_date, :status, :bid_bond_amount, presence: true
|
20
20
|
validates :bid_bond_amount, numericality: { greater_than_or_equal_to: 0 }
|
21
21
|
validates :status, inclusion: { in: STATUSES }
|
22
22
|
validate :validate_start_date_against_end_date
|
@@ -46,6 +46,10 @@ module Cats
|
|
46
46
|
save!
|
47
47
|
self
|
48
48
|
end
|
49
|
+
|
50
|
+
def quantity
|
51
|
+
transport_bid_items.sum(:quantity)
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
@@ -3,6 +3,7 @@ module Cats
|
|
3
3
|
class TransportBidItem < ApplicationRecord
|
4
4
|
belongs_to :transport_bid
|
5
5
|
belongs_to :transport_plan_item
|
6
|
+
belongs_to :unit, class_name: 'Cats::Core::UnitOfMeasure'
|
6
7
|
|
7
8
|
has_many :offer_items
|
8
9
|
|
@@ -10,6 +11,7 @@ module Cats
|
|
10
11
|
validates :transport_plan_item_id, uniqueness: true
|
11
12
|
|
12
13
|
delegate(:reference_no, to: :transport_bid, prefix: true)
|
14
|
+
delegate(:abbreviation, to: :unit, prefix: true)
|
13
15
|
|
14
16
|
def route
|
15
17
|
transport_plan_item.route.name
|
@@ -7,6 +7,7 @@ module Cats
|
|
7
7
|
|
8
8
|
validates :offer_date, :bid_bond_amount, presence: true
|
9
9
|
validates :bid_bond_amount, numericality: { greater_than_or_equal_to: 0 }
|
10
|
+
validates :transport_bid_id, uniqueness: { scope: :transporter_id }
|
10
11
|
|
11
12
|
delegate(:name, to: :transporter, prefix: true)
|
12
13
|
delegate(:reference_no, to: :transport_bid, prefix: 'bid')
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Cats
|
2
|
+
module Core
|
3
|
+
class UnitConversion < ApplicationRecord
|
4
|
+
belongs_to :from, class_name: 'Cats::Core::UnitOfMeasure'
|
5
|
+
belongs_to :to, class_name: 'Cats::Core::UnitOfMeasure'
|
6
|
+
|
7
|
+
validates :factor, presence: true
|
8
|
+
validates :from_id, uniqueness: { scope: :to_id }
|
9
|
+
validates :factor, numericality: { greater_than: 0 }
|
10
|
+
|
11
|
+
delegate(:abbreviation, to: :from, prefix: true)
|
12
|
+
delegate(:abbreviation, to: :to, prefix: true)
|
13
|
+
|
14
|
+
def self.convert(from, to, value)
|
15
|
+
return value if from == to
|
16
|
+
|
17
|
+
conversion = find_by(from: from, to: to)
|
18
|
+
error = "Conversion factor from #{from.abbreviation} to #{to.abbreviation} not found."
|
19
|
+
raise(StandardError, error) unless conversion
|
20
|
+
|
21
|
+
value * conversion.factor
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# A concern to represent entities that lead to dispatch plan.
|
2
|
-
# All classes including this concern must implement `request_reference()
|
3
|
-
# and `request_quantity()` methods, which will be used to generate
|
2
|
+
# All classes including this concern must implement `request_reference()`,
|
3
|
+
# `reserve()`, and `request_quantity()` methods, which will be used to generate
|
4
4
|
# reference information in dispatch plan serializer.
|
5
5
|
module Cats
|
6
6
|
module Core
|
@@ -12,14 +12,14 @@ module Cats
|
|
12
12
|
|
13
13
|
def message
|
14
14
|
allocation_item = params[:allocation_item]
|
15
|
-
commodity = allocation_item.
|
15
|
+
commodity = allocation_item.commodity.name
|
16
16
|
source = allocation_item.source.name
|
17
17
|
destination = allocation_item.destination.name
|
18
18
|
title = "Allocation Notification - #{commodity}"
|
19
19
|
date = Date.today
|
20
20
|
body = <<~BODY
|
21
21
|
Commodity with the following specification has been allocated to you:
|
22
|
-
Batch No. = #{allocation_item.
|
22
|
+
Batch No. = #{allocation_item.commodity.batch_no}
|
23
23
|
Commodity = #{commodity}
|
24
24
|
Quantity = #{allocation_item.quantity}
|
25
25
|
The commodity is expected to be delivered from #{source} to #{destination}
|
@@ -7,7 +7,7 @@ module Cats
|
|
7
7
|
|
8
8
|
def message
|
9
9
|
dispatch = params[:dispatch]
|
10
|
-
commodity = dispatch.dispatch_plan_item.
|
10
|
+
commodity = dispatch.dispatch_plan_item.commodity
|
11
11
|
title = "Dispatch Notification - #{commodity.name}"
|
12
12
|
date = Date.today
|
13
13
|
body = <<~BODY
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Cats
|
2
2
|
module Core
|
3
3
|
class CommoditySerializer < ActiveModel::Serializer
|
4
|
-
attributes :id, :name, :batch_no, :description, :unit_of_measure_id, :
|
4
|
+
attributes :id, :name, :batch_no, :description, :unit_of_measure_id, :unit_abbreviation, :source_id,
|
5
5
|
:source_type, :source_reference_no, :quantity, :best_use_before, :volume_per_metric_ton,
|
6
|
-
:arrival_status, :status
|
6
|
+
:arrival_status, :status, :shipping_reference
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -2,8 +2,7 @@ module Cats
|
|
2
2
|
module Core
|
3
3
|
class DispatchPlanSerializer < ActiveModel::Serializer
|
4
4
|
attributes :id, :reference_no, :status, :dispatchable_id, :dispatchable_type, :request_reference,
|
5
|
-
:request_quantity, :
|
6
|
-
:upstream
|
5
|
+
:request_quantity, :upstream
|
7
6
|
end
|
8
7
|
end
|
9
8
|
end
|
@@ -1,47 +1,35 @@
|
|
1
1
|
module Cats
|
2
2
|
module Core
|
3
3
|
class StackService
|
4
|
-
def
|
4
|
+
def items_for_location(user)
|
5
5
|
details = user.details
|
6
6
|
|
7
7
|
key_available = details.keys.any? { |key| %w[stores warehouse hub].include?(key) }
|
8
8
|
raise(StandardError, 'User does not have associated location.') unless key_available
|
9
9
|
|
10
|
-
if details['hub']
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
hub = warehouse.parent
|
23
|
-
end
|
24
|
-
allocation_items =
|
25
|
-
Cats::Core::AllocationItem
|
26
|
-
.joins(allocation: :commodity)
|
27
|
-
.where(destination: hub, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
|
28
|
-
.or(
|
29
|
-
Cats::Core::AllocationItem
|
30
|
-
.joins(allocation: :commodity)
|
31
|
-
.where(destination: warehouse, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
|
32
|
-
)
|
33
|
-
end
|
10
|
+
hub = if details['hub']
|
11
|
+
Location.find(details['hub'])
|
12
|
+
elsif details['warehouse']
|
13
|
+
Location.find(details['warehouse']).parent
|
14
|
+
else
|
15
|
+
Store.find(details['stores'][0]).warehouse.parent
|
16
|
+
end
|
17
|
+
|
18
|
+
allocation_items =
|
19
|
+
DispatchPlanItem
|
20
|
+
.joins(:dispatch_plan)
|
21
|
+
.where(destination: hub, dispatch_plan: { status: DispatchPlan::APPROVED })
|
34
22
|
|
35
23
|
allocation_items.map do |item|
|
36
24
|
{
|
37
|
-
reference_no: item.
|
38
|
-
source: item.
|
25
|
+
reference_no: item.dispatch_plan.reference_no,
|
26
|
+
source: item.source.name,
|
39
27
|
destination: item.destination.name,
|
40
28
|
quantity: item.quantity,
|
41
|
-
batch_no: item.
|
42
|
-
commodity_id: item.
|
43
|
-
commodity_name: item.
|
44
|
-
unit: item.
|
29
|
+
batch_no: item.commodity.batch_no,
|
30
|
+
commodity_id: item.commodity_id,
|
31
|
+
commodity_name: item.commodity.name,
|
32
|
+
unit: item.commodity.unit_abbreviation
|
45
33
|
}
|
46
34
|
end
|
47
35
|
end
|
@@ -51,7 +39,7 @@ module Cats
|
|
51
39
|
warehouses = location.children
|
52
40
|
stores = Store.where(warehouse: warehouses)
|
53
41
|
|
54
|
-
commodity = receipt.dispatch.dispatch_plan_item.
|
42
|
+
commodity = receipt.dispatch.dispatch_plan_item.commodity
|
55
43
|
Stack.where(commodity: commodity, store: stores)
|
56
44
|
end
|
57
45
|
|
@@ -60,7 +48,7 @@ module Cats
|
|
60
48
|
warehouses = location.children
|
61
49
|
stores = Store.where(warehouse: warehouses)
|
62
50
|
|
63
|
-
commodity = dispatch.dispatch_plan_item.
|
51
|
+
commodity = dispatch.dispatch_plan_item.commodity
|
64
52
|
Stack.where(commodity: commodity, store: stores)
|
65
53
|
end
|
66
54
|
end
|
data/config/routes.rb
CHANGED
@@ -60,6 +60,7 @@ Cats::Core::Engine.routes.draw do
|
|
60
60
|
defaults: { level: Cats::Core::SpaceService::STORE }
|
61
61
|
|
62
62
|
get '/commodity_categories/roots', to: 'commodity_categories#root', as: :commodity_category_roots
|
63
|
+
get '/commodity_categories/all', to: 'commodity_categories#all', as: :commodity_category_all
|
63
64
|
resources :commodity_categories, except: %i[destroy] do
|
64
65
|
member do
|
65
66
|
get 'children'
|
@@ -73,6 +74,7 @@ Cats::Core::Engine.routes.draw do
|
|
73
74
|
end
|
74
75
|
resources :currencies, except: %i[destroy]
|
75
76
|
resources :unit_of_measures, except: %i[destroy]
|
77
|
+
resources :unit_conversions, except: %i[destroy]
|
76
78
|
|
77
79
|
post '/transporters/filter', controller: :transporters, action: :filter
|
78
80
|
resources :transporters, except: %i[destroy]
|
@@ -135,7 +137,7 @@ Cats::Core::Engine.routes.draw do
|
|
135
137
|
|
136
138
|
get '/stores/:id/stacks', controller: :stacks, action: :index, as: :stacks_store
|
137
139
|
post '/stores/:id/stacks', controller: :stacks, action: :filter
|
138
|
-
get '/stacks/
|
140
|
+
get '/stacks/items_for_location', controller: :stacks, action: :items_for_location, as: :items_for_location
|
139
141
|
get '/receipts/:id/stacks', controller: :stacks, action: :receipt_stacks, as: :receipt_stacks
|
140
142
|
get '/dispatches/:id/stacks', controller: :stacks, action: :dispatch_stacks, as: :dispatch_stacks
|
141
143
|
resources :stacks, only: %i[show index create update]
|
@@ -30,9 +30,14 @@ class CreateCatsCoreGiftCertificates < ActiveRecord::Migration[6.1]
|
|
30
30
|
foreign_key: { to_table: :cats_core_locations }
|
31
31
|
t.float :estimated_price
|
32
32
|
t.float :estimated_tax
|
33
|
+
t.references :currency,
|
34
|
+
null: false,
|
35
|
+
index: { name: 'currency_on_gc_indx' },
|
36
|
+
foreign_key: { to_table: :cats_core_currencies }
|
33
37
|
t.string :registration_no
|
34
38
|
t.string :requested_by, null: false
|
35
|
-
t.string :request_reference
|
39
|
+
t.string :request_reference
|
40
|
+
t.string :customs_office, null: false
|
36
41
|
|
37
42
|
t.timestamps
|
38
43
|
end
|
@@ -13,6 +13,7 @@ class CreateCatsCoreCommodities < ActiveRecord::Migration[6.1]
|
|
13
13
|
t.float :volume_per_metric_ton
|
14
14
|
t.string :arrival_status, null: false, default: 'At Source'
|
15
15
|
t.boolean :approved, null: false, default: false
|
16
|
+
t.string :shipping_reference
|
16
17
|
|
17
18
|
t.timestamps
|
18
19
|
end
|
@@ -6,11 +6,6 @@ class CreateCatsCoreDispatchPlans < ActiveRecord::Migration[6.1]
|
|
6
6
|
t.string :status, null: false, default: 'Draft'
|
7
7
|
t.references :dispatchable, polymorphic: true
|
8
8
|
t.boolean :upstream, null: false, default: false
|
9
|
-
t.references :commodity,
|
10
|
-
null: false,
|
11
|
-
index: { name: 'commodity_on_dp_indx' },
|
12
|
-
foreign_key: { to_table: :cats_core_commodities }
|
13
|
-
|
14
9
|
t.references :prepared_by,
|
15
10
|
null: false,
|
16
11
|
index: { name: 'pb_on_dp_indx' },
|
@@ -13,6 +13,10 @@ class CreateCatsCoreDispatchPlanItems < ActiveRecord::Migration[6.1]
|
|
13
13
|
null: false,
|
14
14
|
index: { name: 'dpi_on_destination_indx'},
|
15
15
|
foreign_key: { to_table: :cats_core_locations }
|
16
|
+
t.references :commodity,
|
17
|
+
null: false,
|
18
|
+
index: { name: 'commodity_on_dpi_indx' },
|
19
|
+
foreign_key: { to_table: :cats_core_commodities }
|
16
20
|
t.float :quantity, null: false
|
17
21
|
t.string :commodity_status, null: false, default: 'Good'
|
18
22
|
t.string :status, null: false, default: 'Unauthorized'
|
@@ -3,8 +3,9 @@ class CreateCatsCoreTransportBids < ActiveRecord::Migration[6.1]
|
|
3
3
|
create_table :cats_core_transport_bids do |t|
|
4
4
|
t.string :reference_no, unique: true
|
5
5
|
t.string :description
|
6
|
-
t.
|
7
|
-
t.
|
6
|
+
t.datetime :start_date, null: false
|
7
|
+
t.datetime :end_date, null: false
|
8
|
+
t.datetime :opening_date, null: false
|
8
9
|
t.string :status, null: false, default: 'New'
|
9
10
|
t.float :bid_bond_amount, null: false, default: 0
|
10
11
|
t.references :transport_plan,
|
@@ -10,6 +10,10 @@ class CreateCatsCoreTransportBidItems < ActiveRecord::Migration[6.1]
|
|
10
10
|
index: { name: 'tpi_on_tbi_indx' },
|
11
11
|
foreign_key: { to_table: :cats_core_transport_plan_items }
|
12
12
|
t.float :quantity, null: false
|
13
|
+
t.references :unit,
|
14
|
+
null: false,
|
15
|
+
index: { name: 'unit_on_tbi_indx' },
|
16
|
+
foreign_key: { to_table: :cats_core_unit_of_measures }
|
13
17
|
|
14
18
|
t.timestamps
|
15
19
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateCatsCoreUnitConversions < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :cats_core_unit_conversions do |t|
|
4
|
+
t.references :from,
|
5
|
+
null: false,
|
6
|
+
index: { name: 'from_on_uc_indx' },
|
7
|
+
foreign_key: { to_table: :cats_core_unit_of_measures }
|
8
|
+
t.references :to,
|
9
|
+
null: false,
|
10
|
+
index: { name: 'to_on_uc_indx' },
|
11
|
+
foreign_key: { to_table: :cats_core_unit_of_measures }
|
12
|
+
t.float :factor, null: false
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index(:cats_core_unit_conversions, [:from_id, :to_id], unique: true)
|
18
|
+
end
|
19
|
+
end
|
data/lib/cats/core/version.rb
CHANGED
@@ -4,12 +4,24 @@ FactoryBot.define do
|
|
4
4
|
status { Cats::Core::DispatchPlan::DRAFT }
|
5
5
|
dispatchable { nil }
|
6
6
|
upstream { false }
|
7
|
-
commodity
|
8
7
|
prepared_by factory: :user
|
9
8
|
approved_by { nil }
|
10
9
|
|
11
10
|
trait :with_rhn do
|
12
|
-
dispatchable
|
11
|
+
dispatchable do
|
12
|
+
disp = create(:rhn_request)
|
13
|
+
disp.approve
|
14
|
+
disp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
trait :with_monthly_plan do
|
19
|
+
dispatchable do
|
20
|
+
disp = create(:monthly_plan)
|
21
|
+
3.times { create(:monthly_plan_item, monthly_plan: disp) }
|
22
|
+
disp.approve
|
23
|
+
disp
|
24
|
+
end
|
13
25
|
end
|
14
26
|
end
|
15
27
|
end
|
@@ -15,8 +15,10 @@ FactoryBot.define do
|
|
15
15
|
quantity { 1.5 }
|
16
16
|
estimated_price { 1.5 }
|
17
17
|
estimated_tax { 1.5 }
|
18
|
+
currency
|
18
19
|
registration_no { FFaker::Name.name }
|
19
20
|
requested_by { FFaker::Name.name }
|
20
21
|
request_reference { FFaker::Name.name }
|
22
|
+
customs_office { FFaker::Name.name }
|
21
23
|
end
|
22
24
|
end
|
@@ -3,9 +3,9 @@ FactoryBot.define do
|
|
3
3
|
space_between_stack { 1 }
|
4
4
|
distance_from_gangway { 1.5 }
|
5
5
|
distance_from_ceiling { 1 }
|
6
|
-
maximum_height {
|
7
|
-
maximum_length {
|
8
|
-
maximum_width {
|
6
|
+
maximum_height { 7 }
|
7
|
+
maximum_length { 12 }
|
8
|
+
maximum_width { 12 }
|
9
9
|
distance_from_wall { 1 }
|
10
10
|
end
|
11
11
|
end
|
@@ -2,8 +2,9 @@ FactoryBot.define do
|
|
2
2
|
factory :transport_bid, class: 'Cats::Core::TransportBid' do
|
3
3
|
reference_no { FFaker::Name.name }
|
4
4
|
description { FFaker::Name.name }
|
5
|
-
start_date {
|
6
|
-
end_date {
|
5
|
+
start_date { DateTime.now - 1.week }
|
6
|
+
end_date { DateTime.now }
|
7
|
+
opening_date { DateTime.now + 1.week }
|
7
8
|
bid_bond_amount { 100 }
|
8
9
|
transport_plan
|
9
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cats_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henock L.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_model_serializers
|
@@ -251,12 +251,11 @@ files:
|
|
251
251
|
- app/controllers/cats/core/spaces_controller.rb
|
252
252
|
- app/controllers/cats/core/stacks_controller.rb
|
253
253
|
- app/controllers/cats/core/transporters_controller.rb
|
254
|
+
- app/controllers/cats/core/unit_conversions_controller.rb
|
254
255
|
- app/controllers/cats/core/unit_of_measures_controller.rb
|
255
256
|
- app/controllers/cats/core/users_controller.rb
|
256
257
|
- app/controllers/concerns/cats/core/common.rb
|
257
258
|
- app/jobs/cats/core/application_job.rb
|
258
|
-
- app/models/cats/core/allocation.rb
|
259
|
-
- app/models/cats/core/allocation_item.rb
|
260
259
|
- app/models/cats/core/application_module.rb
|
261
260
|
- app/models/cats/core/application_record.rb
|
262
261
|
- app/models/cats/core/commodity.rb
|
@@ -311,6 +310,7 @@ files:
|
|
311
310
|
- app/models/cats/core/transport_plan.rb
|
312
311
|
- app/models/cats/core/transport_plan_item.rb
|
313
312
|
- app/models/cats/core/transporter.rb
|
313
|
+
- app/models/cats/core/unit_conversion.rb
|
314
314
|
- app/models/cats/core/unit_of_measure.rb
|
315
315
|
- app/models/cats/core/user.rb
|
316
316
|
- app/models/concerns/cats/core/dispatchable.rb
|
@@ -334,6 +334,7 @@ files:
|
|
334
334
|
- app/serializers/cats/core/route_serializer.rb
|
335
335
|
- app/serializers/cats/core/stack_serializer.rb
|
336
336
|
- app/serializers/cats/core/transporter_serializer.rb
|
337
|
+
- app/serializers/cats/core/unit_conversion_serializer.rb
|
337
338
|
- app/serializers/cats/core/unit_of_measure_serializer.rb
|
338
339
|
- app/serializers/cats/core/user_serializer.rb
|
339
340
|
- app/services/cats/core/dispatch_plan_service.rb
|
@@ -374,8 +375,6 @@ files:
|
|
374
375
|
- db/migrate/20210718040129_create_cats_core_routes.rb
|
375
376
|
- db/migrate/20210718042749_create_cats_core_transporters.rb
|
376
377
|
- db/migrate/20210718042755_create_cats_core_rhn_requests.rb
|
377
|
-
- db/migrate/20210718042823_create_cats_core_allocations.rb
|
378
|
-
- db/migrate/20210718043204_create_cats_core_allocation_items.rb
|
379
378
|
- db/migrate/20210718043328_create_cats_core_dispatch_plans.rb
|
380
379
|
- db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb
|
381
380
|
- db/migrate/20210718045516_create_cats_core_dispatches.rb
|
@@ -404,13 +403,12 @@ files:
|
|
404
403
|
- db/migrate/20220107125025_create_cats_core_monthly_plan_items.rb
|
405
404
|
- db/migrate/20220107132433_create_cats_core_monthly_plan_item_details.rb
|
406
405
|
- db/migrate/20220209083928_create_cats_core_hub_authorizations.rb
|
406
|
+
- db/migrate/20220416143416_create_cats_core_unit_conversions.rb
|
407
407
|
- lib/cats/core.rb
|
408
408
|
- lib/cats/core/engine.rb
|
409
409
|
- lib/cats/core/version.rb
|
410
410
|
- lib/cats_core.rb
|
411
411
|
- lib/tasks/cats_core_tasks.rake
|
412
|
-
- spec/factories/cats/core/allocation_items.rb
|
413
|
-
- spec/factories/cats/core/allocations.rb
|
414
412
|
- spec/factories/cats/core/application_modules.rb
|
415
413
|
- spec/factories/cats/core/commodities.rb
|
416
414
|
- spec/factories/cats/core/commodity_categories.rb
|
@@ -463,6 +461,7 @@ files:
|
|
463
461
|
- spec/factories/cats/core/transport_plan_items.rb
|
464
462
|
- spec/factories/cats/core/transport_plans.rb
|
465
463
|
- spec/factories/cats/core/transporters.rb
|
464
|
+
- spec/factories/cats/core/unit_conversions.rb
|
466
465
|
- spec/factories/cats/core/unit_of_measures.rb
|
467
466
|
- spec/factories/cats/core/users.rb
|
468
467
|
homepage: http://cats.ndrmcapps.org
|
@@ -488,7 +487,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
488
487
|
- !ruby/object:Gem::Version
|
489
488
|
version: '0'
|
490
489
|
requirements: []
|
491
|
-
rubygems_version: 3.3.
|
490
|
+
rubygems_version: 3.3.7
|
492
491
|
signing_key:
|
493
492
|
specification_version: 4
|
494
493
|
summary: Core module for CATS applications
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module Cats
|
2
|
-
module Core
|
3
|
-
class Allocation < ApplicationRecord
|
4
|
-
DRAFT = 'Draft'.freeze
|
5
|
-
APPROVED = 'Approved'.freeze
|
6
|
-
ALLOCATION_STATUSES = [DRAFT, APPROVED].freeze
|
7
|
-
|
8
|
-
belongs_to :rhn_request, optional: true
|
9
|
-
belongs_to :commodity
|
10
|
-
belongs_to :source, class_name: 'Cats::Core::Location'
|
11
|
-
has_many :allocation_items
|
12
|
-
|
13
|
-
validates :commodity_status, :allocation_status, presence: true
|
14
|
-
validates :reference_no, presence: true, uniqueness: true
|
15
|
-
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
16
|
-
validates :commodity_status, inclusion: { in: Commodity::COMMODITY_STATUSES }
|
17
|
-
validates :allocation_status, inclusion: { in: ALLOCATION_STATUSES }
|
18
|
-
validate :validate_quantity_against_items, :validate_quantity_against_commodity,
|
19
|
-
:validate_quantity_against_request, :validate_request_status, :validate_commodity_status
|
20
|
-
|
21
|
-
delegate(:reference_no, to: :rhn_request, prefix: :rhn, allow_nil: true)
|
22
|
-
delegate(:batch_no, to: :commodity, prefix: true)
|
23
|
-
delegate(:name, to: :source, prefix: true)
|
24
|
-
delegate(:location_type, to: :source, prefix: true)
|
25
|
-
|
26
|
-
def validate_quantity_against_items
|
27
|
-
return unless quantity
|
28
|
-
|
29
|
-
return unless quantity_changed?
|
30
|
-
|
31
|
-
allocated = allocation_items.sum(:quantity)
|
32
|
-
errors.add(:quantity, "is below items quantity. Minimum allowed is #{allocated}") if quantity < allocated
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_quantity_against_commodity
|
36
|
-
return unless quantity && commodity
|
37
|
-
|
38
|
-
allocated = Allocation.where(commodity: commodity).sum(:quantity)
|
39
|
-
remaining = commodity.quantity - allocated
|
40
|
-
|
41
|
-
remaining += quantity_was if quantity_was
|
42
|
-
errors.add(:quantity, "exceeds commodity quantity. Maximum allowed is #{remaining}") if quantity > remaining
|
43
|
-
end
|
44
|
-
|
45
|
-
def validate_quantity_against_request
|
46
|
-
return unless quantity && rhn_request
|
47
|
-
|
48
|
-
errors.add(:quantity, 'is not equal to requested quantity.') if quantity != rhn_request.quantity
|
49
|
-
end
|
50
|
-
|
51
|
-
def validate_request_status
|
52
|
-
return unless rhn_request
|
53
|
-
|
54
|
-
errors.add(:rhn_request, 'should be approved first.') if rhn_request.status != RhnRequest::APPROVED
|
55
|
-
end
|
56
|
-
|
57
|
-
def validate_commodity_status
|
58
|
-
return unless commodity
|
59
|
-
|
60
|
-
errors.add(:commodity, 'should be approved first.') unless commodity.status == Commodity::APPROVED
|
61
|
-
end
|
62
|
-
|
63
|
-
def approve
|
64
|
-
raise(StandardError, 'Allocation already approved.') if allocation_status == Allocation::APPROVED
|
65
|
-
|
66
|
-
item_quantity = allocation_items.sum(:quantity)
|
67
|
-
raise(StandardError, 'Allocation quantity and items quantity do not match.') if quantity != item_quantity
|
68
|
-
|
69
|
-
self.allocation_status = Allocation::APPROVED
|
70
|
-
save!
|
71
|
-
|
72
|
-
# If the commodity is all allocated, then we should
|
73
|
-
# set its status to allocated.
|
74
|
-
commodity.allocate
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Cats
|
2
|
-
module Core
|
3
|
-
class AllocationItem < ApplicationRecord
|
4
|
-
belongs_to :allocation
|
5
|
-
belongs_to :destination, class_name: 'Cats::Core::Location'
|
6
|
-
|
7
|
-
validates :from, :to, presence: true
|
8
|
-
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
9
|
-
validate :validate_source_and_destination, :validate_quantity
|
10
|
-
validate :validate_allocation_status, on: %i[create update]
|
11
|
-
|
12
|
-
def validate_source_and_destination
|
13
|
-
return unless allocation.present? && destination.present?
|
14
|
-
|
15
|
-
errors.add(:base, 'source and destination cannot be the same') if allocation.source == destination
|
16
|
-
end
|
17
|
-
|
18
|
-
def validate_quantity
|
19
|
-
return unless quantity && allocation
|
20
|
-
|
21
|
-
return unless quantity_changed?
|
22
|
-
|
23
|
-
allocated = AllocationItem.where(allocation: allocation).sum(:quantity)
|
24
|
-
remaining = allocation.quantity - allocated
|
25
|
-
remaining += quantity_was if quantity_was
|
26
|
-
errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
|
27
|
-
end
|
28
|
-
|
29
|
-
def validate_allocation_status
|
30
|
-
return unless allocation
|
31
|
-
|
32
|
-
return unless allocation.allocation_status == Cats::Core::Allocation::APPROVED
|
33
|
-
|
34
|
-
errors.add(:allocation, 'is alreay approved. Changes are not allowed at this point.')
|
35
|
-
end
|
36
|
-
|
37
|
-
delegate(:name, to: :destination, prefix: true)
|
38
|
-
delegate(:reference_no, to: :allocation, prefix: true)
|
39
|
-
delegate(:location_type, to: :destination, prefix: true)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class CreateCatsCoreAllocations < ActiveRecord::Migration[6.1]
|
2
|
-
def change
|
3
|
-
create_table :cats_core_allocations do |t|
|
4
|
-
t.string :reference_no, unique: true
|
5
|
-
t.references :rhn_request,
|
6
|
-
null: true,
|
7
|
-
index: { name: 'rr_on_allocation_indx' },
|
8
|
-
foreign_key: { to_table: :cats_core_rhn_requests }
|
9
|
-
t.references :commodity,
|
10
|
-
null: false,
|
11
|
-
index: { name: 'ca_on_commodity_indx' },
|
12
|
-
foreign_key: { to_table: :cats_core_commodities }
|
13
|
-
t.references :source,
|
14
|
-
null: false,
|
15
|
-
index: { name: 'ca_on_source_indx' },
|
16
|
-
foreign_key: { to_table: :cats_core_locations }
|
17
|
-
t.float :quantity, null: false
|
18
|
-
t.string :commodity_status, null: false, default: 'Good'
|
19
|
-
t.string :allocation_status, null: false, default: 'Draft'
|
20
|
-
t.string :remark
|
21
|
-
|
22
|
-
t.timestamps
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class CreateCatsCoreAllocationItems < ActiveRecord::Migration[6.1]
|
2
|
-
def change
|
3
|
-
create_table :cats_core_allocation_items do |t|
|
4
|
-
t.references :allocation,
|
5
|
-
null: false,
|
6
|
-
index: { name: 'allocation_on_ai_indx' },
|
7
|
-
foreign_key: { to_table: :cats_core_allocations }
|
8
|
-
t.references :destination,
|
9
|
-
null: false,
|
10
|
-
index: { name: 'destination_on_ai_indx'},
|
11
|
-
foreign_key: { to_table: :cats_core_locations }
|
12
|
-
t.float :quantity, null: false
|
13
|
-
t.date :from, null: false
|
14
|
-
t.date :to, null: false
|
15
|
-
|
16
|
-
t.timestamps
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
factory :allocation, class: 'Cats::Core::Allocation' do
|
3
|
-
reference_no { FFaker::Name.name }
|
4
|
-
rhn_request { nil }
|
5
|
-
commodity do
|
6
|
-
c = create(:commodity)
|
7
|
-
c.approve
|
8
|
-
c
|
9
|
-
end
|
10
|
-
source factory: :location
|
11
|
-
quantity { 50 }
|
12
|
-
commodity_status { Cats::Core::Commodity::GOOD }
|
13
|
-
allocation_status { Cats::Core::Allocation::DRAFT }
|
14
|
-
remark { FFaker::Name.name }
|
15
|
-
end
|
16
|
-
end
|