cats_core 1.1.34 → 1.1.38

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04aa5725df06bf149cf057515dd11ef721dc9511b9aa9555cd2dd311ad9e96ff
4
- data.tar.gz: ec1393337a6276fec08d3897618bb2ed345f66dd027a8a07efc59544bcd326d6
3
+ metadata.gz: 05d36c2ff3f71d11f2d601ae469f69b4db03ae956e98e5ea6e7fc11e230ca918
4
+ data.tar.gz: feb9cd6e23c14759ab5c7a423af1669d7d017de9eefa8e8cf602ca36b94ff0e7
5
5
  SHA512:
6
- metadata.gz: d5b97bdff8990988dd0bebeba15e24fadc28328970e1343f36617c3ee93a149af2470320ad8b7adafca36dcfddcb927acbed34e67b325dbb3828e2941ab5f9cc
7
- data.tar.gz: ec0011655502fd35e6313bd4e5f079557cc58de783d093d640e122fbcd894bbcca459225ebafdc83f7c4c2770a116477dd4f09061ee33c5fadeee0e32790445d
6
+ metadata.gz: d52633ea04e36f159602d53ec10d8e6664921238328e80bd85b6587dbbc5ecc1aade3f64a0cb7d8ae0ced07b9b4657f27be83d66906be5c79b1f66fce51ce359
7
+ data.tar.gz: 833963237bc5fa5c84da07a7f2e691f47ac379df36ef0df434f4de308205109bc3dcc40b77a1da2433f260f3b6a104486eca9c01888364d7d73ff9a8d0afaa41
@@ -31,8 +31,8 @@ module Cats
31
31
  end
32
32
 
33
33
  def approve
34
- dispatch = @service.approve(@dispatch)
35
- render json: { success: true, data: serialize(dispatch) }
34
+ @dispatch.approve
35
+ render json: { success: true, data: serialize(@dispatch) }
36
36
  rescue StandardError => e
37
37
  render json: { success: false, error: e.message }
38
38
  end
@@ -45,8 +45,8 @@ module Cats
45
45
  end
46
46
 
47
47
  def confirm
48
- dispatch = @service.confirm(@dispatch)
49
- render json: { success: true, data: serialize(dispatch) }
48
+ @dispatch.confirm
49
+ render json: { success: true, data: serialize(@dispatch) }
50
50
  rescue StandardError => e
51
51
  render json: { success: false, error: e.message }
52
52
  end
@@ -13,13 +13,62 @@ module Cats
13
13
  validates :commodity_status, :allocation_status, presence: true
14
14
  validates :reference_no, presence: true, uniqueness: true
15
15
  validates :quantity, presence: true, numericality: { greater_than: 0 }
16
- validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
16
+ validates :commodity_status, inclusion: { in: Commodity::COMMODITY_STATUSES }
17
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
18
20
 
19
21
  delegate(:reference_no, to: :rhn_request, prefix: :rhn, allow_nil: true)
20
22
  delegate(:batch_no, to: :commodity, prefix: true)
21
23
  delegate(:name, to: :source, prefix: true)
22
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.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
+ end
23
72
  end
24
73
  end
25
74
  end
@@ -6,7 +6,8 @@ module Cats
6
6
 
7
7
  validates :from, :to, presence: true
8
8
  validates :quantity, presence: true, numericality: { greater_than: 0 }
9
- validate :validate_source_and_destination
9
+ validate :validate_source_and_destination, :validate_quantity
10
+ validate :validate_allocation_status, on: %i[create update]
10
11
 
11
12
  def validate_source_and_destination
12
13
  return unless allocation.present? && destination.present?
@@ -14,6 +15,25 @@ module Cats
14
15
  errors.add(:base, 'source and destination cannot be the same') if allocation.source == destination
15
16
  end
16
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
+
17
37
  delegate(:name, to: :destination, prefix: true)
18
38
  delegate(:reference_no, to: :allocation, prefix: true)
19
39
  delegate(:location_type, to: :destination, prefix: true)
@@ -20,7 +20,7 @@ module Cats
20
20
  validates :reference_no, uniqueness: true
21
21
  validates :quantity, numericality: { greater_than: 0 }
22
22
  validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
23
- validate :validate_quantity
23
+ validate :validate_quantity, :validate_allocation_status
24
24
 
25
25
  delegate(:name, to: :transporter, prefix: true)
26
26
  delegate(:email, to: :prepared_by, prefix: true)
@@ -32,8 +32,57 @@ module Cats
32
32
 
33
33
  dispatched = Dispatch.where(allocation_item: allocation_item).sum(:quantity)
34
34
  remaining = allocation_item.quantity - dispatched
35
+ remaining += quantity_was if quantity_was
35
36
  errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
36
37
  end
38
+
39
+ def validate_allocation_status
40
+ return unless allocation_item
41
+
42
+ status = allocation_item.allocation.allocation_status
43
+ errors.add(:allocation_item, 'should be approved first.') unless status == Allocation::APPROVED
44
+ end
45
+
46
+ def approve
47
+ raise(StandardError, 'Dispatch has to be in draft state.') unless dispatch_status == Dispatch::DRAFT
48
+
49
+ count = DispatchTransaction.where(destination_id: id).count
50
+ raise(StandardError, 'Dispatch has no transactions.') unless count.positive?
51
+
52
+ quantity = DispatchTransaction.where(destination_id: id).sum(:quantity)
53
+ raise(StandardError, 'Transactions quantity is not equal to dispatch quantity.') if self.quantity != quantity
54
+
55
+ self.dispatch_status = Dispatch::APPROVED
56
+ save!
57
+ end
58
+
59
+ def start
60
+ raise(StandardError, 'Dispatch has to be approved first.') unless dispatch_status == Dispatch::APPROVED
61
+
62
+ self.dispatch_status = Dispatch::STARTED
63
+ save!
64
+ transactions = DispatchTransaction.where(destination_id: id)
65
+ transactions.each(&:commit)
66
+ end
67
+
68
+ def confirm
69
+ total = receipts.sum(:quantity)
70
+
71
+ unless total == quantity
72
+ diff = (quantity - total).abs
73
+ raise(
74
+ StandardError,
75
+ "There is an amount of #{diff} in the dispatch which is unaccounted for."
76
+ )
77
+ end
78
+
79
+ Dispatch.transaction do
80
+ self.dispatch_status = Dispatch::RECEIVED
81
+ receipts.each { |r| r.status = Receipt::CONFIRMED }
82
+ save!
83
+ receipts.each(&:save!)
84
+ end
85
+ end
37
86
  end
38
87
  end
39
88
  end
@@ -35,15 +35,9 @@ module Cats
35
35
 
36
36
  received = dispatch.receipts.sum(:quantity)
37
37
  diff = dispatch.quantity - received
38
- if new_record?
39
- return if quantity <= diff
38
+ diff += quantity_was if quantity_was
40
39
 
41
- errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff}).")
42
- else
43
- return unless diff.negative?
44
-
45
- errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff.abs}).")
46
- end
40
+ errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff}).") if quantity > diff
47
41
  end
48
42
  end
49
43
  end
@@ -1,13 +1,40 @@
1
1
  module Cats
2
2
  module Core
3
3
  class RhnRequest < ApplicationRecord
4
+ DRAFT = 'Draft'.freeze
5
+ APPROVED = 'Approved'.freeze
6
+ STATUSES = [DRAFT, APPROVED].freeze
7
+
4
8
  belongs_to :commodity
5
9
 
6
10
  validates :reference_no, :request_date, :quantity, presence: true
7
11
  validates :reference_no, uniqueness: true
8
12
  validates :quantity, numericality: { greater_than: 0 }
13
+ validates :status, presence: true, inclusion: { in: STATUSES }
14
+ validate :validate_commodity_status, :validate_quantity
9
15
 
10
16
  delegate(:batch_no, to: :commodity, prefix: true)
17
+
18
+ def validate_commodity_status
19
+ return unless commodity
20
+
21
+ errors.add(:commodity, 'should be approved first.') unless commodity.approved
22
+ end
23
+
24
+ def validate_quantity
25
+ return unless commodity && quantity
26
+
27
+ requested = RhnRequest.where(commodity: commodity).sum(:quantity)
28
+ remaining = commodity.quantity - requested
29
+
30
+ remaining += quantity_was if quantity_was
31
+ errors.add(:quantity, "exceeds commodity quantity. Maximum allowed is #{remaining}") if quantity > remaining
32
+ end
33
+
34
+ def approve
35
+ self.status = APPROVED
36
+ save!
37
+ end
11
38
  end
12
39
  end
13
40
  end
@@ -2,9 +2,6 @@ module Cats
2
2
  module Core
3
3
  class DispatchService
4
4
  def create_receipt_authorization(reference_no, allocation_item, quantity, remark, user)
5
- status = allocation_item.allocation.allocation_status
6
- raise(StandardError, 'Allocation not approved.') unless status == Cats::Core::Allocation::APPROVED
7
-
8
5
  transporter = Cats::Core::Transporter.find_by(code: 'SUP-TRANS')
9
6
  raise(StandardError, 'Supplier transporter does not exist.') unless transporter
10
7
 
@@ -16,27 +13,30 @@ module Cats
16
13
 
17
14
  raise(StandardError, 'Commodity not found in supplier store.') unless stack
18
15
 
19
- dispatch = Cats::Core::Dispatch.create!(
20
- reference_no: reference_no,
21
- allocation_item: allocation_item,
22
- transporter: transporter,
23
- plate_no: 'Supplier plate no',
24
- driver_name: 'Supplier driver',
25
- driver_phone: 'Supplier driver phone',
26
- quantity: quantity,
27
- remark: remark,
28
- prepared_by: user,
29
- dispatch_status: Cats::Core::Dispatch::DRAFT
30
- )
16
+ dispatch = nil
17
+ ApplicationRecord.transaction do
18
+ dispatch = Cats::Core::Dispatch.create!(
19
+ reference_no: reference_no,
20
+ allocation_item: allocation_item,
21
+ transporter: transporter,
22
+ plate_no: 'Supplier plate no',
23
+ driver_name: 'Supplier driver',
24
+ driver_phone: 'Supplier driver phone',
25
+ quantity: quantity,
26
+ remark: remark,
27
+ prepared_by: user,
28
+ dispatch_status: Cats::Core::Dispatch::DRAFT
29
+ )
31
30
 
32
- # Create a dispatch transaction
33
- Cats::Core::DispatchTransaction.create!(
34
- source: stack,
35
- destination: dispatch,
36
- transaction_date: Date.today,
37
- quantity: quantity,
38
- status: Cats::Core::Transaction::DRAFT
39
- )
31
+ # Create a dispatch transaction
32
+ Cats::Core::DispatchTransaction.create!(
33
+ source: stack,
34
+ destination: dispatch,
35
+ transaction_date: Date.today,
36
+ quantity: quantity,
37
+ status: Cats::Core::Transaction::DRAFT
38
+ )
39
+ end
40
40
  dispatch
41
41
  end
42
42
 
@@ -87,52 +87,12 @@ module Cats
87
87
  dispatches
88
88
  end
89
89
 
90
- def approve(dispatch)
91
- unless dispatch.dispatch_status == Cats::Core::Dispatch::DRAFT
92
- raise(StandardError, 'Dispatch has to be in draft state.')
93
- end
94
-
95
- transactions = Cats::Core::DispatchTransaction.where(destination: dispatch).count
96
- raise(StandardError, 'Dispatch has no transactions.') unless transactions.positive?
97
-
98
- dispatch.dispatch_status = Cats::Core::Dispatch::APPROVED
99
- dispatch.save
100
- dispatch
101
- end
102
-
103
90
  def start(dispatch)
104
- unless dispatch.dispatch_status == Cats::Core::Dispatch::APPROVED
105
- raise(StandardError, 'Dispatch has to be approved first.')
106
- end
107
-
108
- dispatch.dispatch_status = Cats::Core::Dispatch::STARTED
109
- dispatch.save
110
- transactions = Cats::Core::DispatchTransaction.where(destination: dispatch)
111
- transactions.each(&:commit)
91
+ dispatch.start
112
92
  send_notification(dispatch)
113
93
  dispatch
114
94
  end
115
95
 
116
- def confirm(dispatch)
117
- total = dispatch.receipts.sum(:quantity)
118
-
119
- unless total == dispatch.quantity
120
- raise(
121
- StandardError,
122
- "There is an amount of #{dispatch.quantity - total} in the dispatch which is unaccounted for."
123
- )
124
- end
125
-
126
- Cats::Core::Dispatch.transaction do
127
- dispatch.dispatch_status = Cats::Core::Dispatch::RECEIVED
128
- dispatch.receipts.each { |r| r.status = Cats::Core::Receipt::CONFIRMED }
129
- dispatch.save
130
- dispatch.receipts.each(&:save!)
131
- end
132
-
133
- dispatch
134
- end
135
-
136
96
  def send_notification(dispatch)
137
97
  notification_rule = Cats::Core::NotificationRule.find_by(code: 'dispatch')
138
98
  raise(StandardError, 'Notification rule not found for dispatch notification.') unless notification_rule
@@ -0,0 +1,5 @@
1
+ class AddStatusToCatsCoreRhnRequests < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :cats_core_rhn_requests, :status, :string, null: false, default: 'Draft'
4
+ end
5
+ end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.1.34'.freeze
3
+ VERSION = '1.1.38'.freeze
4
4
  end
5
5
  end
@@ -2,7 +2,7 @@ FactoryBot.define do
2
2
  factory :allocation_item, class: 'Cats::Core::AllocationItem' do
3
3
  allocation
4
4
  destination factory: :location
5
- quantity { 100 }
5
+ quantity { 50 }
6
6
  from { Date.today }
7
7
  to { Date.today + 1.week }
8
8
  end
@@ -8,6 +8,6 @@ FactoryBot.define do
8
8
  best_use_before { Date.today + 2.month }
9
9
  volume_per_metric_ton { 10 }
10
10
  arrival_status { Cats::Core::Commodity::AT_SOURCE }
11
- approved { false }
11
+ approved { true }
12
12
  end
13
13
  end
@@ -1,7 +1,12 @@
1
1
  FactoryBot.define do
2
2
  factory :dispatch, class: 'Cats::Core::Dispatch' do
3
3
  reference_no { FFaker::Name.name }
4
- allocation_item
4
+ allocation_item do
5
+ allocation = create(:allocation, quantity: 100)
6
+ allocation_item = create(:allocation_item, allocation: allocation, quantity: 100)
7
+ allocation.approve
8
+ allocation_item
9
+ end
5
10
  transporter
6
11
  plate_no { FFaker::Name.name }
7
12
  driver_name { FFaker::Name.name }
@@ -1,6 +1,12 @@
1
1
  FactoryBot.define do
2
2
  factory :receipt, class: 'Cats::Core::Receipt' do
3
- dispatch factory: :dispatch, dispatch_status: Cats::Core::Dispatch::STARTED
3
+ dispatch do
4
+ dispatch = create(:dispatch)
5
+ create(:dispatch_transaction, destination: dispatch, quantity: 50)
6
+ dispatch.approve
7
+ dispatch.start
8
+ dispatch
9
+ end
4
10
  quantity { 50 }
5
11
  commodity_status { Cats::Core::Commodity::GOOD }
6
12
  status { Cats::Core::Receipt::DRAFT }
@@ -5,5 +5,6 @@ FactoryBot.define do
5
5
  quantity { 100 }
6
6
  request_date { Date.today }
7
7
  requested_by { FFaker::Name.name }
8
+ status { Cats::Core::RhnRequest::DRAFT }
8
9
  end
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.1.34
4
+ version: 1.1.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henock L.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-23 00:00:00.000000000 Z
11
+ date: 2021-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -345,6 +345,7 @@ files:
345
345
  - db/migrate/20210814160628_create_cats_core_receipt_transactions.rb
346
346
  - db/migrate/20210814175406_create_cats_core_stack_transactions.rb
347
347
  - db/migrate/20211002050739_create_cats_core_notification_rules.rb
348
+ - db/migrate/20211024063240_add_status_to_cats_core_rhn_requests.rb
348
349
  - lib/cats/core.rb
349
350
  - lib/cats/core/engine.rb
350
351
  - lib/cats/core/version.rb