cats_core 1.4.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/cats/core/commodities_controller.rb +1 -1
  3. data/app/controllers/cats/core/commodity_categories_controller.rb +5 -0
  4. data/app/controllers/cats/core/monthly_plans_controller.rb +3 -5
  5. data/app/models/cats/core/commodity.rb +0 -21
  6. data/app/models/cats/core/gift_certificate.rb +5 -2
  7. data/app/models/cats/core/monthly_plan.rb +24 -2
  8. data/app/models/cats/core/route.rb +9 -1
  9. data/app/models/cats/core/stack.rb +31 -4
  10. data/app/models/cats/core/transport_bid.rb +1 -1
  11. data/app/models/cats/core/transport_offer.rb +1 -0
  12. data/app/models/concerns/cats/core/dispatchable.rb +2 -2
  13. data/app/serializers/cats/core/commodity_serializer.rb +1 -1
  14. data/app/services/cats/core/stack_service.rb +18 -30
  15. data/config/routes.rb +1 -0
  16. data/db/migrate/20210717032602_create_cats_core_gift_certificates.rb +6 -1
  17. data/db/migrate/20210717033223_create_cats_core_commodities.rb +1 -0
  18. data/db/migrate/20211215121151_create_cats_core_transport_bids.rb +3 -2
  19. data/db/migrate/20211229160125_create_cats_core_transport_offers.rb +2 -0
  20. data/lib/cats/core/version.rb +1 -1
  21. data/spec/factories/cats/core/commodities.rb +1 -0
  22. data/spec/factories/cats/core/dispatch_plans.rb +4 -0
  23. data/spec/factories/cats/core/gift_certificates.rb +2 -0
  24. data/spec/factories/cats/core/stacking_rules.rb +3 -3
  25. data/spec/factories/cats/core/transport_bids.rb +3 -2
  26. metadata +2 -8
  27. data/app/models/cats/core/allocation.rb +0 -78
  28. data/app/models/cats/core/allocation_item.rb +0 -42
  29. data/db/migrate/20210718042823_create_cats_core_allocations.rb +0 -25
  30. data/db/migrate/20210718043204_create_cats_core_allocation_items.rb +0 -19
  31. data/spec/factories/cats/core/allocation_items.rb +0 -9
  32. data/spec/factories/cats/core/allocations.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: affaa1b4a210fc6234d49f105efd3a0e197b8d9e6c2ad7e00ae2dbefd23cfe31
4
- data.tar.gz: 608f4585d6c34f68a62a7bcfc187d495ac21a0fa528f905bcda7044801ab4c1f
3
+ metadata.gz: 16cbad0f2d1788e23d39a4b904aac57711bc3d6432b36ea4a96105ee9fccfd94
4
+ data.tar.gz: d3ff309544e77e52620b48c66f19be7488c7629bcd6a2e7cf45cd084f48ce835
5
5
  SHA512:
6
- metadata.gz: 68b8a081e2ee0e3ad7edb1876b76a1cb2d2c0b8836de2af209acb01de699d004c0fd2f74c0357a27857fd287f249f3338950debe88c15ee2b742cfe72f4d62cd
7
- data.tar.gz: 4b5c89c2de473ec47255835b1862ddaa42f44b4a99d5410bd4c63515b73bef77d1ef92328a75358a00dd29992afa2bcf2c582cbde84a5d63de2833d10944aada
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
- if plan.monthly_plan_items.count.zero?
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, :request_reference, presence: true
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
- donation = self.donation
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: Cats::Core::Plan::STATUSES }
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 == Cats::Core::Location::REGION
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, unless: -> { store && store.code == 'SUP-STORE' }
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: 5,
52
- maximum_length: 5,
53
- maximum_width: 5,
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
- hub = Cats::Core::Location.find(details['hub'])
12
- allocation_items =
13
- Cats::Core::AllocationItem
14
- .joins(allocation: :commodity)
15
- .where(destination: hub, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
16
- else
17
- if details['stores']
18
- warehouse = Cats::Core::Store.find(details['stores'][0]).warehouse
19
- hub = warehouse.parent
20
- elsif details['warehouse']
21
- warehouse = Cats::Core::Location.find(details['warehouse'])
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.allocation.reference_no,
38
- source: item.allocation.source.name,
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.allocation.commodity.batch_no,
42
- commodity_id: item.allocation.commodity_id,
43
- commodity_name: item.allocation.commodity.name,
44
- unit: item.allocation.commodity.unit_of_measure.abbreviation
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, null: false
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.date :start_date, null: false
7
- t.date :end_date, null: false
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,
@@ -13,6 +13,8 @@ class CreateCatsCoreTransportOffers < ActiveRecord::Migration[6.1]
13
13
  t.float :bid_bond_amount, null: false, default: 0
14
14
 
15
15
  t.timestamps
16
+
17
+ t.index [:transport_bid_id, :transporter_id], unique: true, name: 'tb_and_t_on_to_indx'
16
18
  end
17
19
  end
18
20
  end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.4.1'.freeze
3
+ VERSION = '1.4.2'.freeze
4
4
  end
5
5
  end
@@ -9,5 +9,6 @@ FactoryBot.define do
9
9
  volume_per_metric_ton { 10 }
10
10
  arrival_status { Cats::Core::Commodity::AT_SOURCE }
11
11
  status { Cats::Core::Commodity::DRAFT }
12
+ shipping_reference { FFaker::Name.name }
12
13
  end
13
14
  end
@@ -11,5 +11,9 @@ FactoryBot.define do
11
11
  trait :with_rhn do
12
12
  dispatchable { create(:rhn_request) }
13
13
  end
14
+
15
+ trait :with_monthly_plan do
16
+ dispatchable { create(:monthly_plan) }
17
+ end
14
18
  end
15
19
  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 { 2.5 }
7
- maximum_length { 6 }
8
- maximum_width { 6 }
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 { Date.today - 1.week }
6
- end_date { Date.today }
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.1
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-03-27 00:00:00.000000000 Z
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,9 +0,0 @@
1
- FactoryBot.define do
2
- factory :allocation_item, class: 'Cats::Core::AllocationItem' do
3
- allocation
4
- destination factory: :location
5
- quantity { 50 }
6
- from { Date.today }
7
- to { Date.today + 1.week }
8
- end
9
- 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