cats_core 1.4.0 → 1.4.3

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 (49) 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/controllers/cats/core/stacks_controller.rb +7 -0
  6. data/app/controllers/cats/core/unit_conversions_controller.rb +13 -0
  7. data/app/models/cats/core/commodity.rb +0 -21
  8. data/app/models/cats/core/dispatch_plan.rb +27 -0
  9. data/app/models/cats/core/gift_certificate.rb +5 -2
  10. data/app/models/cats/core/location.rb +3 -1
  11. data/app/models/cats/core/monthly_plan.rb +24 -2
  12. data/app/models/cats/core/plan.rb +1 -0
  13. data/app/models/cats/core/rhn_request.rb +13 -1
  14. data/app/models/cats/core/route.rb +9 -1
  15. data/app/models/cats/core/stack.rb +31 -4
  16. data/app/models/cats/core/transport_bid.rb +5 -1
  17. data/app/models/cats/core/transport_bid_item.rb +1 -0
  18. data/app/models/cats/core/transport_offer.rb +1 -0
  19. data/app/models/cats/core/unit_conversion.rb +25 -0
  20. data/app/models/concerns/cats/core/dispatchable.rb +2 -2
  21. data/app/serializers/cats/core/commodity_serializer.rb +1 -1
  22. data/app/serializers/cats/core/unit_conversion_serializer.rb +7 -0
  23. data/app/services/cats/core/dispatch_plan_service.rb +1 -1
  24. data/app/services/cats/core/dispatch_service.rb +16 -9
  25. data/app/services/cats/core/stack_service.rb +29 -32
  26. data/config/routes.rb +3 -0
  27. data/db/migrate/20210717031810_create_cats_core_plans.rb +3 -0
  28. data/db/migrate/20210717032602_create_cats_core_gift_certificates.rb +6 -1
  29. data/db/migrate/20210717033223_create_cats_core_commodities.rb +1 -0
  30. data/db/migrate/20211215121151_create_cats_core_transport_bids.rb +3 -2
  31. data/db/migrate/20211215124452_create_cats_core_transport_bid_items.rb +4 -0
  32. data/db/migrate/20211229160125_create_cats_core_transport_offers.rb +2 -0
  33. data/db/migrate/20220416143416_create_cats_core_unit_conversions.rb +19 -0
  34. data/lib/cats/core/version.rb +1 -1
  35. data/spec/factories/cats/core/commodities.rb +1 -0
  36. data/spec/factories/cats/core/dispatch_plans.rb +14 -1
  37. data/spec/factories/cats/core/gift_certificates.rb +2 -0
  38. data/spec/factories/cats/core/plans.rb +2 -0
  39. data/spec/factories/cats/core/stacking_rules.rb +3 -3
  40. data/spec/factories/cats/core/transport_bid_items.rb +1 -0
  41. data/spec/factories/cats/core/transport_bids.rb +3 -2
  42. data/spec/factories/cats/core/unit_conversions.rb +7 -0
  43. metadata +8 -9
  44. data/app/models/cats/core/allocation.rb +0 -78
  45. data/app/models/cats/core/allocation_item.rb +0 -42
  46. data/db/migrate/20210718042823_create_cats_core_allocations.rb +0 -25
  47. data/db/migrate/20210718043204_create_cats_core_allocation_items.rb +0 -19
  48. data/spec/factories/cats/core/allocation_items.rb +0 -9
  49. data/spec/factories/cats/core/allocations.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1563c8d3250c1cda415de5081c46f445a82f593c727be676c3f9a7041f28fa7
4
- data.tar.gz: b614991a9f6a2a4046c7c4e54af584d59a33478c62b5a0c6dee77ddbbdad2e6b
3
+ metadata.gz: e2624794cc9a3787caefb212037b9f33f8964e9d5512fcc40a7dbb31fa129009
4
+ data.tar.gz: 0f2d9b94ca4dc8794fe89928449b6c26cac67a78e2ffffadfa5be8d49baef52c
5
5
  SHA512:
6
- metadata.gz: ff00ffac606dfa2136aaaed05a6825238b5ae38f737f4a3790db2b94193f0108b6d394097c0828339af8aab226acf871d65ddefa68c54ad929a47e7069d9d49b
7
- data.tar.gz: fd1b163787f8fc21ba49f79929f027143f1a45d74425518536d9adc4369eb33ea6ab9b96a30fb34b7cba6e9f8ba11e2f9f191acd83200debf91589cc9be490e3
6
+ metadata.gz: c0f3fc9431f4b011ca5015f9bf288627b51b547d79323e48d1f0221baae4781766b63ab521c23652feda8cd2fefb7f17a2242166ace64875cf4418138dc37c54
7
+ data.tar.gz: c9b0ec89851d48c0fcc9338dd749364d4a1a66e0a4291085c59f70b73605f5b47b4831cbfd03d01683f0b1ed829309247069f0878b6bc199cf2791936e416978
@@ -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
@@ -19,6 +19,13 @@ module Cats
19
19
  render json: { success: true, data: serialize(commodities) }
20
20
  end
21
21
 
22
+ def dispatch_stacks
23
+ service = StackService.new
24
+ dispatch = Dispatch.find(params[:id])
25
+ stacks = service.dispatch_stacks(dispatch)
26
+ render json: { success: true, data: serialize(stacks) }
27
+ end
28
+
22
29
  def receipt_stacks
23
30
  service = StackService.new
24
31
  receipt = Receipt.find(params[:id])
@@ -0,0 +1,13 @@
1
+ module Cats
2
+ module Core
3
+ class UnitConversionsController < ApplicationController
4
+ include Common
5
+
6
+ private
7
+
8
+ def model_params
9
+ params.require(:payload).permit(:from_id, :to_id, :factor)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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
@@ -14,6 +14,7 @@ module Cats
14
14
 
15
15
  validates :reference_no, presence: true, uniqueness: true
16
16
  validates :status, inclusion: { in: STATUSES }
17
+ validate :validate_dispatchable, on: :create
17
18
 
18
19
  delegate(:batch_no, :name, :quantity, to: :commodity, prefix: true)
19
20
  delegate(:request_reference, to: :dispatchable, allow_nil: true)
@@ -23,14 +24,40 @@ module Cats
23
24
  plan.upstream = !plan.dispatchable.nil? && plan.dispatchable_type == RhnRequest.name
24
25
  end
25
26
 
27
+ after_save do |plan|
28
+ plan.dispatchable&.reserve if status == DRAFT
29
+ end
30
+
31
+ def validate_dispatchable
32
+ # Check if dispatchable is already reserved and raise error if so.
33
+ return unless dispatchable
34
+
35
+ return if dispatchable.status == RhnRequest::APPROVED
36
+
37
+ errors.add(:dispatchable, 'is already reserved.') if id.nil?
38
+ end
39
+
26
40
  def approve
27
41
  raise(StandardError, 'Dispatch plan already approved.') if status == APPROVED
28
42
 
29
43
  raise(StandardError, 'Dispatch plan is empty.') if dispatch_plan_items.count.zero?
30
44
 
45
+ # Raise error if the total dispatch plan quantity is not equal to the
46
+ # dispatchable quantity
47
+ if dispatchable.instance_of?(RhnRequest) && dispatchable.quantity != quantity
48
+ raise(StandardError, 'Requested quantity and plan quantity do not match.')
49
+ end
50
+
31
51
  self.status = APPROVED
52
+ dispatchable&.allocate if dispatchable.instance_of?(RhnRequest)
32
53
  save!
33
54
  end
55
+
56
+ # A method which returns the total quantity in the dispatch plan
57
+ # based on dispatch plan item quantities.
58
+ def quantity
59
+ dispatch_plan_items.sum(:quantity)
60
+ end
34
61
  end
35
62
  end
36
63
  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
@@ -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: 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
@@ -18,6 +18,7 @@ module Cats
18
18
  has_many :plan_item_details, through: :plan_items
19
19
 
20
20
  validates :reference_no, :year, :status, presence: true
21
+ validates :total_days, :rounds, presence: true, numericality: { greater_than: 0 }
21
22
  validates :season, presence: true, inclusion: { in: SEASONS }
22
23
  validates :reference_no, uniqueness: true
23
24
  validates :status, inclusion: { in: STATUSES }
@@ -5,8 +5,9 @@ module Cats
5
5
 
6
6
  DRAFT = 'Draft'.freeze
7
7
  APPROVED = 'Approved'.freeze
8
+ RESERVED = 'Reserved'.freeze
8
9
  ALLOCATED = 'Allocated'.freeze
9
- STATUSES = [DRAFT, APPROVED, ALLOCATED].freeze
10
+ STATUSES = [DRAFT, APPROVED, RESERVED, ALLOCATED].freeze
10
11
 
11
12
  belongs_to :commodity
12
13
 
@@ -43,11 +44,22 @@ module Cats
43
44
  end
44
45
 
45
46
  def approve
47
+ raise(StandardError, 'Request is not in draft state.') unless status == DRAFT
48
+
46
49
  self.status = APPROVED
47
50
  save!
48
51
  end
49
52
 
53
+ def reserve
54
+ raise(StandardError, 'Request is not approved.') unless status == APPROVED
55
+
56
+ self.status = RESERVED
57
+ save!
58
+ end
59
+
50
60
  def allocate
61
+ raise(StandardError, 'Request is not reserved.') unless status == RESERVED
62
+
51
63
  self.status = ALLOCATED
52
64
  save!
53
65
  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
@@ -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
 
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ module Cats
2
+ module Core
3
+ class UnitConversionSerializer < ActiveModel::Serializer
4
+ attributes :id, :from_id, :from_abbreviation, :to_id, :to_abbreviation, :factor
5
+ end
6
+ end
7
+ end
@@ -23,7 +23,6 @@ module Cats
23
23
  end
24
24
  HubAuthorization.insert_all(authorizations)
25
25
  plan.dispatch_plan_items.update_all(status: DispatchPlanItem::SOURCE_AUTHORIZED)
26
- plan.dispatchable.allocate
27
26
  end
28
27
  send_notification(plan)
29
28
  plan
@@ -33,6 +32,7 @@ module Cats
33
32
  plan = Cats::Core::DispatchPlan.new(params)
34
33
  plan.prepared_by = user
35
34
  plan.save!
35
+
36
36
  plan
37
37
  rescue ActiveRecord::RecordInvalid
38
38
  raise(StandardError, plan.errors.full_messages[0])
@@ -1,7 +1,7 @@
1
1
  module Cats
2
2
  module Core
3
3
  class DispatchService
4
- def search(user, status)
4
+ def search(user, status, authorized: false)
5
5
  details = user.details
6
6
 
7
7
  unless details['stores'] || details['warehouse'] || details['hub']
@@ -10,18 +10,25 @@ module Cats
10
10
 
11
11
  # Get user's hub
12
12
  hub = if details['stores']
13
- Cats::Core::Store.find(details['stores'][0]).warehouse.parent
13
+ Store.find(details['stores'][0]).warehouse.parent
14
14
  elsif details['warehouse']
15
- Cats::Core::Location.find(details['warehouse']).parent
15
+ Location.find(details['warehouse']).parent
16
16
  else
17
- Cats::Core::Location.find(details['hub'])
17
+ Location.find(details['hub'])
18
18
  end
19
19
 
20
- Cats::Core::Dispatch.joins(:dispatch_plan_item)
21
- .where(
22
- dispatch_plan_item: { destination: hub },
23
- dispatch_status: status
24
- )
20
+ if authorized
21
+ return Dispatch.joins(:dispatch_plan_item)
22
+ .where(
23
+ dispatch_plan_item: { destination: hub, status: DispatchPlanItem::AUTHORIZED },
24
+ dispatch_status: status
25
+ )
26
+ end
27
+ Dispatch.joins(:dispatch_plan_item)
28
+ .where(
29
+ dispatch_plan_item: { destination: hub },
30
+ dispatch_status: status
31
+ )
25
32
  end
26
33
 
27
34
  def start(dispatch)
@@ -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
@@ -49,10 +37,19 @@ module Cats
49
37
  def receipt_stacks(receipt)
50
38
  location = receipt.dispatch.dispatch_plan_item.destination
51
39
  warehouses = location.children
52
- stores = Cats::Core::Store.where(warehouse: warehouses)
40
+ stores = Store.where(warehouse: warehouses)
53
41
 
54
42
  commodity = receipt.dispatch.dispatch_plan_item.dispatch_plan.commodity
55
- Cats::Core::Stack.where(commodity: commodity, store: stores)
43
+ Stack.where(commodity: commodity, store: stores)
44
+ end
45
+
46
+ def dispatch_stacks(dispatch)
47
+ location = dispatch.dispatch_plan_item.source
48
+ warehouses = location.children
49
+ stores = Store.where(warehouse: warehouses)
50
+
51
+ commodity = dispatch.dispatch_plan_item.dispatch_plan.commodity
52
+ Stack.where(commodity: commodity, store: stores)
56
53
  end
57
54
  end
58
55
  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]
@@ -137,5 +139,6 @@ Cats::Core::Engine.routes.draw do
137
139
  post '/stores/:id/stacks', controller: :stacks, action: :filter
138
140
  get '/stacks/commodity_for_location', controller: :stacks, action: :commodity_for_location, as: :commodity_for_location
139
141
  get '/receipts/:id/stacks', controller: :stacks, action: :receipt_stacks, as: :receipt_stacks
142
+ get '/dispatches/:id/stacks', controller: :stacks, action: :dispatch_stacks, as: :dispatch_stacks
140
143
  resources :stacks, only: %i[show index create update]
141
144
  end
@@ -5,6 +5,9 @@ class CreateCatsCorePlans < ActiveRecord::Migration[6.1]
5
5
  t.integer :year, null: false
6
6
  t.string :season, null: false
7
7
  t.string :status, null: false, default: 'Draft'
8
+ t.date :start_date
9
+ t.integer :total_days, null: false, default: 180
10
+ t.integer :rounds, null: false
8
11
 
9
12
  t.references :program,
10
13
  null: false,
@@ -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,
@@ -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
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.4.0'.freeze
3
+ VERSION = '1.4.3'.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
@@ -9,7 +9,20 @@ FactoryBot.define do
9
9
  approved_by { nil }
10
10
 
11
11
  trait :with_rhn do
12
- dispatchable { create(:rhn_request) }
12
+ dispatchable do
13
+ disp = create(:rhn_request)
14
+ disp.approve
15
+ disp
16
+ end
17
+ end
18
+
19
+ trait :with_monthly_plan do
20
+ dispatchable do
21
+ disp = create(:monthly_plan)
22
+ 3.times { create(:monthly_plan_item, monthly_plan: disp) }
23
+ disp.approve
24
+ disp
25
+ end
13
26
  end
14
27
  end
15
28
  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,6 +3,8 @@ FactoryBot.define do
3
3
  reference_no { FFaker::Name.name }
4
4
  year { 1 }
5
5
  season { Cats::Core::Plan::BELG }
6
+ total_days { 180 }
7
+ rounds { 6 }
6
8
  status { Cats::Core::Plan::DRAFT }
7
9
  program
8
10
  ration
@@ -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
@@ -3,5 +3,6 @@ FactoryBot.define do
3
3
  transport_bid
4
4
  transport_plan_item
5
5
  quantity { 100 }
6
+ unit factory: :unit_of_measure
6
7
  end
7
8
  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
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :unit_conversion, class: 'Cats::Core::UnitConversion' do
3
+ from factory: :unit_of_measure
4
+ to factory: :unit_of_measure
5
+ factor { 1 }
6
+ end
7
+ 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.0
4
+ version: 1.4.3
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-24 00:00:00.000000000 Z
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.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,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