cats_core 1.4.1 → 1.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/monthly_plans_controller.rb +3 -5
- data/app/models/cats/core/commodity.rb +0 -21
- data/app/models/cats/core/gift_certificate.rb +5 -2
- 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 +1 -1
- data/app/models/cats/core/transport_offer.rb +1 -0
- data/app/models/concerns/cats/core/dispatchable.rb +2 -2
- data/app/serializers/cats/core/commodity_serializer.rb +1 -1
- data/app/services/cats/core/stack_service.rb +18 -30
- data/config/routes.rb +1 -0
- 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/20211215121151_create_cats_core_transport_bids.rb +3 -2
- data/db/migrate/20211229160125_create_cats_core_transport_offers.rb +2 -0
- data/lib/cats/core/version.rb +1 -1
- data/spec/factories/cats/core/commodities.rb +1 -0
- data/spec/factories/cats/core/dispatch_plans.rb +4 -0
- 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_bids.rb +3 -2
- metadata +2 -8
- 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: 16cbad0f2d1788e23d39a4b904aac57711bc3d6432b36ea4a96105ee9fccfd94
|
4
|
+
data.tar.gz: d3ff309544e77e52620b48c66f19be7488c7629bcd6a2e7cf45cd084f48ce835
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c38aaf1efefb124e3e2e1d2122d420f5fe152363580931ac0c49065a19392b092cd280e503ce84d674c87709f251d1f780c50674808b83c47c2f7cd3bcf48a89
|
7
|
+
data.tar.gz: d7c641de65a5a30397eecabd9af62c792e50e5540aeafbb1f795a720ce49a4d0747611a01af39ab086b72c6c8cd759deb1561940d1c31f09b2cda51c8c2b6a1d
|
@@ -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) }
|
@@ -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
|
@@ -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 }
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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')
|
@@ -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
|
@@ -3,7 +3,7 @@ module Cats
|
|
3
3
|
class CommoditySerializer < ActiveModel::Serializer
|
4
4
|
attributes :id, :name, :batch_no, :description, :unit_of_measure_id, :unit_of_measure_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
|
@@ -7,41 +7,29 @@ module Cats
|
|
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: :commodity)
|
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.dispatch_plan.commodity.batch_no,
|
30
|
+
commodity_id: item.dispatch_plan.commodity_id,
|
31
|
+
commodity_name: item.dispatch_plan.commodity.name,
|
32
|
+
unit: item.dispatch_plan.commodity.unit_of_measure.abbreviation
|
45
33
|
}
|
46
34
|
end
|
47
35
|
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'
|
@@ -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
|
@@ -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,
|
data/lib/cats/core/version.rb
CHANGED
@@ -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.2
|
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-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_model_serializers
|
@@ -255,8 +255,6 @@ files:
|
|
255
255
|
- app/controllers/cats/core/users_controller.rb
|
256
256
|
- app/controllers/concerns/cats/core/common.rb
|
257
257
|
- app/jobs/cats/core/application_job.rb
|
258
|
-
- app/models/cats/core/allocation.rb
|
259
|
-
- app/models/cats/core/allocation_item.rb
|
260
258
|
- app/models/cats/core/application_module.rb
|
261
259
|
- app/models/cats/core/application_record.rb
|
262
260
|
- app/models/cats/core/commodity.rb
|
@@ -374,8 +372,6 @@ files:
|
|
374
372
|
- db/migrate/20210718040129_create_cats_core_routes.rb
|
375
373
|
- db/migrate/20210718042749_create_cats_core_transporters.rb
|
376
374
|
- 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
375
|
- db/migrate/20210718043328_create_cats_core_dispatch_plans.rb
|
380
376
|
- db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb
|
381
377
|
- db/migrate/20210718045516_create_cats_core_dispatches.rb
|
@@ -409,8 +405,6 @@ files:
|
|
409
405
|
- lib/cats/core/version.rb
|
410
406
|
- lib/cats_core.rb
|
411
407
|
- lib/tasks/cats_core_tasks.rake
|
412
|
-
- spec/factories/cats/core/allocation_items.rb
|
413
|
-
- spec/factories/cats/core/allocations.rb
|
414
408
|
- spec/factories/cats/core/application_modules.rb
|
415
409
|
- spec/factories/cats/core/commodities.rb
|
416
410
|
- spec/factories/cats/core/commodity_categories.rb
|
@@ -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
|