cats_core 1.1.33 → 1.1.37

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc7dd4f19838153db58356a4d33eb5f0fcff634279643a00e221084b170bd840
4
- data.tar.gz: b423a14678d56634fb1b2d1f10ee7c9df20ef0129de0ac245b956a6943cf8029
3
+ metadata.gz: f07fe2e24b72c5cf2c4c7d7c9acd92332e6e7a80b4d9305fdffcbb94365fb67e
4
+ data.tar.gz: 6c343a483c11b17757966c650fa355a541a62483eafa9d6ad5b5428ebb1aef63
5
5
  SHA512:
6
- metadata.gz: 1ebaeba514c4ebba0f6f3288efbadd58546cf94e5f5b1028808a037767c8b36df516b357ea404e1d7046fb26729334eed0d90c11b31fe267cff1f05ccf20b98e
7
- data.tar.gz: 89514042663c0b651b09da15c7897e4c7f87b4a8df2648661181c692ea9b99b3c6575f4e592a595fe364e419ccc1175a1d08412a55d8d9a55231cbfe6de50943
6
+ metadata.gz: 5c7a27a3e6babd99f6e331c63d6d79ecfb6af34e5c6ae746ccd538d11e1ea62e48ea9c6b4b84eb5d1500da1466992f2acae40297127e5822c12b4f8ed418a728
7
+ data.tar.gz: 930ccb77011e1cabc7ce9851fe22584f50346d1494d4556df7df90159fb9f2d99b3340c0f9ff1f7f5cc0a7b334f5274e74b67191d48abecf709f04af27b553b5
@@ -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
@@ -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
@@ -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.33'.freeze
3
+ VERSION = '1.1.37'.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.33
4
+ version: 1.1.37
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-22 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