cats_core 1.1.32 → 1.1.36

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: 38e415ba9c0ae6853fc377ab8cb33fd85c9d483cfda350f7f952f38593a794b6
4
- data.tar.gz: eb94d3adf63d313fba9956ae5d2e2ab22656dc3d49e6bc2a90944a4998d0ba39
3
+ metadata.gz: 9d66e9f780b4e36013c3eac6a0c319e61270199d621eea8cc1747451eb09e95b
4
+ data.tar.gz: 83c8aee6ba3e4a15d3aa6a0255f0c8a6aead3247fed994e5ced103c91cc1d314
5
5
  SHA512:
6
- metadata.gz: 994251d466ed5b143b5fd138c10d446804f4d0f49bf7156f261cf4a9881f9bd944f38bc7b6ebeb31c07760f969a4345b76ebb3247aa6dce5b6483ccf0a559b72
7
- data.tar.gz: 83d05eef310b8a97265144aab84e605b54d7164f2bccf110acf2f5ae52fe5d9b5806b4e7c243e0eda7fa2d5aee776ea299cabbb0ad5866df27adde5912c1b1b3
6
+ metadata.gz: b77f6a0923079b2e847b263602e42fb489245f15442b11ccd0509d4c6b3790b1f3950469557a686d0b4cbeb9f34c9c94dc14c82e853e0d2d064d42c5db3bd4e8
7
+ data.tar.gz: ac19f2ff28600eaa8d580bef4d6ad8fdec01ea0511f163d486d8bc3397e67d95eab82a79c32977b01e88952f789d53198a40c599fc977c14a623f4cf3eb4da12
@@ -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,24 @@ 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
+ errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
26
+ end
27
+
28
+ def validate_allocation_status
29
+ return unless allocation
30
+
31
+ return unless allocation.allocation_status == Cats::Core::Allocation::APPROVED
32
+
33
+ errors.add(:allocation, 'is alreay approved. Changes are not allowed at this point.')
34
+ end
35
+
17
36
  delegate(:name, to: :destination, prefix: true)
18
37
  delegate(:reference_no, to: :allocation, prefix: true)
19
38
  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)
@@ -34,6 +34,54 @@ module Cats
34
34
  remaining = allocation_item.quantity - dispatched
35
35
  errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
36
36
  end
37
+
38
+ def validate_allocation_status
39
+ return unless allocation_item
40
+
41
+ status = allocation_item.allocation.allocation_status
42
+ errors.add(:allocation_item, 'should be approved first.') unless status == Allocation::APPROVED
43
+ end
44
+
45
+ def approve
46
+ raise(StandardError, 'Dispatch has to be in draft state.') unless dispatch_status == Dispatch::DRAFT
47
+
48
+ count = DispatchTransaction.where(destination_id: id).count
49
+ raise(StandardError, 'Dispatch has no transactions.') unless count.positive?
50
+
51
+ quantity = DispatchTransaction.where(destination_id: id).sum(:quantity)
52
+ raise(StandardError, 'Transactions quantity is not equal to dispatch quantity.') if self.quantity != quantity
53
+
54
+ self.dispatch_status = Dispatch::APPROVED
55
+ save!
56
+ end
57
+
58
+ def start
59
+ raise(StandardError, 'Dispatch has to be approved first.') unless dispatch_status == Dispatch::APPROVED
60
+
61
+ self.dispatch_status = Dispatch::STARTED
62
+ save!
63
+ transactions = DispatchTransaction.where(destination_id: id)
64
+ transactions.each(&:commit)
65
+ end
66
+
67
+ def confirm
68
+ total = receipts.sum(:quantity)
69
+
70
+ unless total == quantity
71
+ diff = (quantity - total).abs
72
+ raise(
73
+ StandardError,
74
+ "There is an amount of #{diff} in the dispatch which is unaccounted for."
75
+ )
76
+ end
77
+
78
+ Dispatch.transaction do
79
+ self.dispatch_status = Dispatch::RECEIVED
80
+ receipts.each { |r| r.status = Receipt::CONFIRMED }
81
+ save!
82
+ receipts.each(&:save!)
83
+ end
84
+ end
37
85
  end
38
86
  end
39
87
  end
@@ -3,7 +3,9 @@ module Cats
3
3
  class Hrp < ApplicationRecord
4
4
  DRAFT = 'Draft'.freeze
5
5
  APPROVED = 'Approved'.freeze
6
- STATUSES = [DRAFT, APPROVED].freeze
6
+ NEEDS_APPROVED = 'Needs Approved'.freeze
7
+
8
+ STATUSES = [DRAFT, APPROVED, NEEDS_APPROVED].freeze
7
9
 
8
10
  BELG = 'Belg'.freeze
9
11
  MEHER = 'Meher'.freeze
@@ -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,35 @@
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
11
33
  end
12
34
  end
13
35
  end
@@ -12,12 +12,13 @@ module Cats
12
12
 
13
13
  def message
14
14
  allocation_item = params[:allocation_item]
15
- title = 'Allocation Notification'
15
+ commodity = allocation_item.allocation.commodity.name
16
+ title = "Allocation Notification - #{commodity}"
16
17
  date = Date.today
17
18
  body = <<~BODY
18
19
  Commodity with the following specification has been allocated to you:
19
20
  Batch No. = #{allocation_item.allocation.commodity.batch_no}
20
- Commodity = #{allocation_item.allocation.commodity.name}
21
+ Commodity = #{commodity}
21
22
  Quantity = #{allocation_item.quantity}
22
23
  The commodity is expected to be delivered from #{allocation_item.from} to #{allocation_item.to}
23
24
  BODY
@@ -7,13 +7,14 @@ module Cats
7
7
 
8
8
  def message
9
9
  dispatch = params[:dispatch]
10
- title = 'Dispatch Notification'
10
+ commodity = dispatch.allocation_item.allocation.commodity.name
11
+ title = "Dispatch Notification - #{commodity}"
11
12
  date = Date.today
12
13
  body = <<~BODY
13
14
  Commodity with the following details has been dispatched to you:
14
15
  Dispatch Ref. = #{dispatch.reference_no}
15
16
  Batch No. = #{dispatch.allocation_item.allocation.commodity.batch_no}
16
- Commodity = #{dispatch.allocation_item.allocation.commodity.name}
17
+ Commodity = #{commodity}
17
18
  Allocated Quantity = #{dispatch.allocation_item.quantity}
18
19
  Quantity = #{dispatch.quantity}
19
20
  Truck Plate No. = #{dispatch.plate_no}
@@ -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.32'.freeze
3
+ VERSION = '1.1.36'.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.32
4
+ version: 1.1.36
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-20 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