cats_core 1.4.21 → 1.4.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/cats/core/dispatch_authorizations_controller.rb +27 -0
  3. data/app/controllers/cats/core/dispatch_plan_items_controller.rb +2 -2
  4. data/app/controllers/cats/core/dispatch_transactions_controller.rb +4 -4
  5. data/app/controllers/cats/core/dispatches_controller.rb +2 -2
  6. data/app/controllers/cats/core/receipt_authorizations_controller.rb +28 -0
  7. data/app/controllers/cats/core/receipt_transactions_controller.rb +2 -20
  8. data/app/models/cats/core/authorization.rb +65 -0
  9. data/app/models/cats/core/dispatch.rb +25 -46
  10. data/app/models/cats/core/dispatch_authorization.rb +13 -0
  11. data/app/models/cats/core/dispatch_plan_item.rb +1 -0
  12. data/app/models/cats/core/dispatch_transaction.rb +39 -2
  13. data/app/models/cats/core/receipt_authorization.rb +26 -0
  14. data/app/models/cats/core/receipt_transaction.rb +16 -14
  15. data/app/models/cats/core/transaction.rb +0 -30
  16. data/app/serializers/cats/core/dispatch_authorization_serializer.rb +8 -0
  17. data/app/serializers/cats/core/dispatch_plan_item_serializer.rb +1 -1
  18. data/app/serializers/cats/core/dispatch_transaction_serializer.rb +1 -2
  19. data/app/serializers/cats/core/receipt_authorization_serializer.rb +8 -0
  20. data/app/serializers/cats/core/receipt_transaction_serializer.rb +2 -2
  21. data/config/routes.rb +16 -8
  22. data/db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb +1 -0
  23. data/db/migrate/20210718045516_create_cats_core_dispatches.rb +4 -0
  24. data/db/migrate/20210718055414_create_cats_core_dispatch_authorizations.rb +22 -0
  25. data/db/migrate/20210718202957_create_cats_core_dispatch_transactions.rb +9 -3
  26. data/db/migrate/20210727074646_create_cats_core_receipt_authorizations.rb +24 -0
  27. data/db/migrate/20210814160628_create_cats_core_receipt_transactions.rb +3 -3
  28. data/lib/cats/core/version.rb +1 -1
  29. data/spec/factories/cats/core/dispatch_authorizations.rb +26 -0
  30. data/spec/factories/cats/core/dispatch_plan_items.rb +1 -0
  31. data/spec/factories/cats/core/dispatch_transactions.rb +2 -7
  32. data/spec/factories/cats/core/dispatches.rb +22 -3
  33. data/spec/factories/cats/core/receipt_authorizations.rb +19 -0
  34. data/spec/factories/cats/core/receipt_transactions.rb +2 -22
  35. data/spec/factories/cats/core/stacks.rb +1 -1
  36. metadata +13 -7
  37. data/app/controllers/cats/core/receipts_controller.rb +0 -45
  38. data/app/models/cats/core/receipt.rb +0 -44
  39. data/app/services/cats/core/receipt_service.rb +0 -48
  40. data/db/migrate/20210727074646_create_cats_core_receipts.rb +0 -20
  41. data/spec/factories/cats/core/receipts.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88b37ea0943ecb3db77fd873889665d4a58f990cb712a75ca258897cc448bc6c
4
- data.tar.gz: c4f897f6a36c0a5ce076d5ed144d342b82ef57ac8f3e226df6de84efa4f71daa
3
+ metadata.gz: a3a896be87ee316cd08b40a298effac694bfb59e1207699c50675b4242e0f630
4
+ data.tar.gz: 3b6d584ce3eacbf6a0f3ffda03c399d84db2c5bf3931666107cf9d7fd014e3ca
5
5
  SHA512:
6
- metadata.gz: 3c706230ac9911c572bdb611f18a65f7e61afaf01f94c4a901298391c7f54b7637be9b9b54b02a63e817e621916931fffe7eca14481ecca649fc21af0f1f553a
7
- data.tar.gz: c90b1ec96db1ccc7f20fae099366a4f1f5660905234a287ee7a6ccf7de16602e21c8dc653df35d1cfc5b1b722e8d2deace2374685a2c42b08263d3b113790c48
6
+ metadata.gz: 234470131214a8e68da2123957a811c55c41c38079c34ec9dde9b9313c0d85c7b88607da5b0a3d7a2dd98f1c2f39942f5790a858d21eb76595a9f0572578d3a5
7
+ data.tar.gz: 4f3e4040eff76a430bbcaf24ec3bae51dc54905831f744f23802905c4d6df80cc440184de47c9398be98051be81519010cf4ca9e3818817a3b1fc67b9cd3dda8
@@ -0,0 +1,27 @@
1
+ module Cats
2
+ module Core
3
+ class DispatchAuthorizationsController < ApplicationController
4
+ include Common
5
+
6
+ def index
7
+ super do
8
+ DispatchAuthorization.where(dispatch_id: params[:id])
9
+ end
10
+ end
11
+
12
+ def confirm
13
+ authorization = DispatchAuthorization.find(params[:id])
14
+ authorization.confirm
15
+ render json: { success: true, data: serialize(authorization) }
16
+ rescue StandardError => e
17
+ render json: { success: false, error: e.message }
18
+ end
19
+
20
+ private
21
+
22
+ def model_params
23
+ params.require(:payload).permit(:dispatch_id, :store_id, :quantity, :status, :authorized_by_id)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -17,8 +17,8 @@ module Cats
17
17
  private
18
18
 
19
19
  def model_params
20
- params.require(:payload).permit(:dispatch_plan_id, :source_id, :destination_id, :quantity, :commodity_status,
21
- :status, :commodity_id)
20
+ params.require(:payload).permit(:reference_no, :dispatch_plan_id, :source_id, :destination_id, :quantity,
21
+ :commodity_status, :status, :commodity_id)
22
22
  end
23
23
  end
24
24
  end
@@ -5,7 +5,7 @@ module Cats
5
5
 
6
6
  def index
7
7
  super do
8
- DispatchTransaction.where(dispatch_id: params[:id])
8
+ DispatchTransaction.where(dispatch_authorization_id: params[:id])
9
9
  end
10
10
  end
11
11
 
@@ -14,8 +14,8 @@ module Cats
14
14
  # stack is a dummy one and we need to use that without waiting for the
15
15
  # user to give us a source.
16
16
  def create_allocation
17
- dispatch = Dispatch.find(model_params[:dispatch_id])
18
- commodity = dispatch.dispatch_plan_item.commodity
17
+ authorization = DispatchAuthorization.find(model_params[:dispatch_authorization_id])
18
+ commodity = authorization.dispatch.dispatch_plan_item.commodity
19
19
  transaction = DispatchTransaction.new(model_params)
20
20
 
21
21
  # Fetch supplier stack by commodity
@@ -32,7 +32,7 @@ module Cats
32
32
  private
33
33
 
34
34
  def model_params
35
- params.require(:payload).permit(:source_id, :dispatch_id, :transaction_date, :quantity)
35
+ params.require(:payload).permit(:source_id, :dispatch_authorization_id, :transaction_date, :quantity)
36
36
  end
37
37
  end
38
38
  end
@@ -60,8 +60,8 @@ module Cats
60
60
  end
61
61
 
62
62
  def model_params
63
- params.require(:payload).permit(:reference_no, :dispatch_plan_item_id, :transporter_id, :plate_no,
64
- :driver_name, :driver_phone, :quantity, :remark)
63
+ params.require(:payload).permit(:reference_no, :dispatch_plan_item_id, :transporter_id, :plate_no, :unit_id,
64
+ :driver_name, :driver_phone, :remark)
65
65
  end
66
66
  end
67
67
  end
@@ -0,0 +1,28 @@
1
+ module Cats
2
+ module Core
3
+ class ReceiptAuthorizationsController < ApplicationController
4
+ include Common
5
+
6
+ def index
7
+ super do
8
+ ReceiptAuthorization.where(dispatch_id: params[:id])
9
+ end
10
+ end
11
+
12
+ def confirm
13
+ authorization = ReceiptAuthorization.find(params[:id])
14
+ authorization.confirm
15
+ render json: { success: true, data: serialize(authorization) }
16
+ rescue StandardError => e
17
+ render json: { success: false, error: e.message }
18
+ end
19
+
20
+ private
21
+
22
+ def model_params
23
+ params.require(:payload).permit(:dispatch_id, :store_id, :quantity, :lost_quantity, :remark, :status,
24
+ :authorized_by_id)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -5,32 +5,14 @@ module Cats
5
5
 
6
6
  def index
7
7
  super do
8
- ReceiptTransaction.where(receipt_id: params[:id])
9
- end
10
- end
11
-
12
- def create
13
- super do
14
- p = model_params
15
-
16
- # Look for a transaction with the same destination as incoming
17
- transaction = ReceiptTransaction.find_by(
18
- receipt_id: p[:receipt_id],
19
- destination_id: p[:destination_id]
20
- )
21
- if transaction
22
- transaction.quantity += p[:quantity]
23
- else
24
- transaction = ReceiptTransaction.new(p)
25
- end
26
- transaction
8
+ ReceiptTransaction.joins(receipt_authorization: :dispatch).where(receipt_authorization_id: params[:id])
27
9
  end
28
10
  end
29
11
 
30
12
  private
31
13
 
32
14
  def model_params
33
- params.require(:payload).permit(:receipt_id, :destination_id, :transaction_date, :quantity)
15
+ params.require(:payload).permit(:receipt_authorization_id, :destination_id, :transaction_date, :quantity)
34
16
  end
35
17
  end
36
18
  end
@@ -0,0 +1,65 @@
1
+ module Cats
2
+ module Core
3
+ class Authorization < ApplicationRecord
4
+ self.abstract_class = true
5
+ after_initialize :set_status
6
+
7
+ # Authorization statuses
8
+ AUTHORIZED = 'Authorized'.freeze
9
+ CONFIRMED = 'Confirmed'.freeze
10
+ STATUSES = [AUTHORIZED, CONFIRMED].freeze
11
+
12
+ belongs_to :dispatch
13
+ belongs_to :store
14
+ belongs_to :authorized_by, class_name: 'Cats::Core::User'
15
+
16
+ validates :quantity, presence: true, numericality: { greater_than: 0 }
17
+ validates :status, presence: true, inclusion: { in: STATUSES }
18
+ validate :validate_dispatch_status, if: -> { status == AUTHORIZED }
19
+
20
+ delegate(:full_name, to: :authorized_by, prefix: :authorizer)
21
+ delegate(:name, to: :store, prefix: true)
22
+ delegate(:reference_no, to: :dispatch, prefix: true)
23
+
24
+ def validate_dispatch_status
25
+ return unless dispatch
26
+
27
+ if instance_of?(DispatchAuthorization)
28
+ errors.add(:dispatch, 'is not in draft state.') unless dispatch.dispatch_status == Dispatch::DRAFT
29
+ else
30
+ return if dispatch.dispatch_status == Cats::Core::Dispatch::STARTED
31
+
32
+ errors.add(:dispatch, 'should be in "Started" state.')
33
+ end
34
+ end
35
+
36
+ # A convenience method to return dispatch or receipt transactions based on the
37
+ # authorization type.
38
+ def transactions
39
+ return dispatch_transactions if instance_of?(DispatchAuthorization)
40
+
41
+ return receipt_transactions if instance_of?(ReceiptAuthorization)
42
+ end
43
+
44
+ def confirm
45
+ # Check if all transactions are committed first.
46
+ if instance_of?(DispatchAuthorization)
47
+ raise(StandardError, 'Authorization does not have transactions.') if transactions.blank?
48
+
49
+ count = transactions.where(status: Transaction::DRAFT).count
50
+ raise(StandardError, 'There are uncommitted transactions.') if count.positive?
51
+ end
52
+ self.status = CONFIRMED
53
+ save!
54
+ end
55
+
56
+ private
57
+
58
+ def set_status
59
+ return unless new_record?
60
+
61
+ self.status = AUTHORIZED
62
+ end
63
+ end
64
+ end
65
+ end
@@ -13,34 +13,25 @@ module Cats
13
13
  belongs_to :prepared_by, class_name: 'Cats::Core::User'
14
14
  belongs_to :transporter
15
15
  belongs_to :dispatch_plan_item
16
- has_many :receipts
17
- has_many :dispatch_transactions
18
- has_many :receipt_transactions, through: :receipts
19
- has_many :lost_commodities
16
+ belongs_to :unit, class_name: 'Cats::Core::UnitOfMeasure'
17
+
18
+ has_many :dispatch_authorizations
19
+ has_many :receipt_authorizations
20
+ has_many :dispatch_transactions, through: :dispatch_authorizations
21
+ has_many :receipt_transactions, through: :receipt_authorizations
20
22
 
21
23
  validates :reference_no, :plate_no, :driver_name, :driver_phone, :quantity, :commodity_status, presence: true
22
24
  validates :dispatch_status, presence: true, inclusion: { in: DISPATCH_STATUSES }
23
25
  validates :reference_no, uniqueness: true
24
26
  validates :quantity, numericality: { greater_than_or_equal_to: 0 }
25
27
  validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
26
- validate :validate_quantity, :validate_dispatch_plan_status
28
+ validate :validate_dispatch_plan_status
27
29
 
28
30
  delegate(:name, to: :transporter, prefix: true)
29
31
  delegate(:email, to: :prepared_by, prefix: true)
30
32
 
31
- def total_quantity
32
- dispatch_transactions.sum(:quantity)
33
- end
34
-
35
- def validate_quantity
36
- return unless quantity && dispatch_plan_item
37
-
38
- return unless quantity_changed?
39
-
40
- dispatched = dispatch_plan_item.dispatches.sum(:quantity)
41
- remaining = dispatch_plan_item.quantity - dispatched
42
- remaining += quantity_was if quantity_was
43
- errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
33
+ def authorized_quantity
34
+ dispatch_authorizations.sum(:quantity)
44
35
  end
45
36
 
46
37
  def validate_dispatch_plan_status
@@ -53,41 +44,29 @@ module Cats
53
44
  def approve
54
45
  raise(StandardError, 'Dispatch has to be in draft state.') unless dispatch_status == Dispatch::DRAFT
55
46
 
56
- # Check if dispatch has transactions
57
- raise(StandardError, 'Dispatch has no transactions.') unless dispatch_transactions.count.positive?
47
+ # Check if dispatch has authorizations
48
+ raise(StandardError, 'Dispatch has no authorizations.') unless dispatch_authorizations.count.positive?
58
49
 
59
- Dispatch.transaction do
60
- # Commit transactions
61
- dispatch_transactions.each(&:commit)
62
- self.quantity = total_quantity
63
- self.dispatch_status = APPROVED
64
- save!
50
+ dispatches = Dispatch.where(dispatch_plan_item: dispatch_plan_item)
51
+ authorized = dispatches.inject(0) do |result, dispatch|
52
+ result += dispatch.authorized_quantity
53
+ result
65
54
  end
66
- end
67
-
68
- def start
69
- raise(StandardError, 'Dispatch has to be approved first.') unless dispatch_status == Dispatch::APPROVED
55
+ diff = authorized - dispatch_plan_item.quantity
56
+ error = "Total authorized quantity exceeds allocated quantity (Extra = #{diff})."
57
+ raise(StandardError, error) if diff.positive?
70
58
 
71
- self.dispatch_status = STARTED
59
+ self.dispatch_status = APPROVED
72
60
  save!
73
61
  end
74
62
 
75
- def confirm
76
- total = receipts.sum(:quantity)
77
-
78
- unless total == quantity
79
- diff = (quantity - total).abs
80
- raise(
81
- StandardError,
82
- "There is an amount of #{diff} in the dispatch which is unaccounted for."
83
- )
84
- end
85
-
63
+ def start
86
64
  Dispatch.transaction do
87
- self.dispatch_status = RECEIVED
88
- receipts.each { |r| r.status = Receipt::CONFIRMED }
65
+ # Commit transactions
66
+ self.quantity = dispatch_transactions.sum(:quantity)
67
+ self.dispatch_status = STARTED
89
68
  save!
90
- receipts.each(&:save!)
69
+ dispatch_transactions.each(&:commit)
91
70
  end
92
71
  end
93
72
 
@@ -102,7 +81,7 @@ module Cats
102
81
  {
103
82
  batch_no: batch_no,
104
83
  commodity_name: commodity.name,
105
- quantity: dispatch.total_quantity,
84
+ quantity: dispatch.quantity,
106
85
  unit: commodity.unit_abbreviation,
107
86
  location: dispatch.transporter.name,
108
87
  location_detail: "Plate No.: #{dispatch.plate_no}, Driver: #{dispatch.driver_name}",
@@ -0,0 +1,13 @@
1
+ module Cats
2
+ module Core
3
+ class DispatchAuthorization < Authorization
4
+ has_many :dispatch_transactions
5
+
6
+ def validate_dispatch_status
7
+ return unless dispatch
8
+
9
+ errors.add(:dispatch, 'is not in draft state.') unless dispatch.dispatch_status == Dispatch::DRAFT
10
+ end
11
+ end
12
+ end
13
+ end
@@ -15,6 +15,7 @@ module Cats
15
15
  has_many :dispatches
16
16
  has_many :hub_authorizations
17
17
 
18
+ validates :reference_no, presence: true, uniqueness: true
18
19
  validates :commodity_status, presence: true, inclusion: { in: Commodity::COMMODITY_STATUSES }
19
20
  validates :quantity, presence: true, numericality: { greater_than: 0 }
20
21
  validates :status, presence: true, inclusion: { in: STATUSES }
@@ -2,10 +2,13 @@ module Cats
2
2
  module Core
3
3
  class DispatchTransaction < Transaction
4
4
  belongs_to :source, class_name: 'Cats::Core::Stack'
5
- belongs_to :dispatch
5
+ belongs_to :dispatch_authorization
6
+
7
+ validates :source_id, uniqueness: { scope: :dispatch_authorization_id }
8
+ validate :validate_dispatch
9
+ validate :validate_source_quantity, :validate_authorized_quantity, unless: :skip_quantity_validation
6
10
 
7
11
  delegate(:code, to: :source, prefix: true)
8
- delegate(:reference_no, to: :dispatch, prefix: true)
9
12
 
10
13
  def commit
11
14
  Transaction.transaction do
@@ -16,6 +19,40 @@ module Cats
16
19
  save!
17
20
  end
18
21
  end
22
+
23
+ def validate_dispatch
24
+ return unless dispatch_authorization
25
+
26
+ status = dispatch_authorization.dispatch.dispatch_status
27
+ errors.add(:base, 'Dispatch must be approved first.') if status == Dispatch::DRAFT
28
+ end
29
+
30
+ def validate_source_quantity
31
+ return unless quantity && source
32
+
33
+ total = DispatchTransaction.where(status: DRAFT, source: source).sum(:quantity)
34
+ diff = quantity - (source.quantity - total)
35
+ diff -= quantity_was if quantity_was
36
+ errors.add(:quantity, "exceeds source quantity by #{diff}") if diff.positive?
37
+ end
38
+
39
+ def validate_authorized_quantity
40
+ return unless quantity && dispatch_authorization
41
+
42
+ total = DispatchTransaction.where(dispatch_authorization: dispatch_authorization).sum(:quantity)
43
+ diff = dispatch_authorization.quantity - total
44
+ diff += quantity_was if quantity_was
45
+ errors.add(:quantity, "exceeds authorized quantity (Max. = #{diff}).") if quantity > diff
46
+ end
47
+
48
+ def skip_quantity_validation
49
+ # Quantity validation should be skipped if dispatch is already started.
50
+ return true unless dispatch_authorization
51
+
52
+ return true if status == COMMITTED
53
+
54
+ ![Dispatch::DRAFT, Dispatch::APPROVED].include?(dispatch_authorization.dispatch.dispatch_status)
55
+ end
19
56
  end
20
57
  end
21
58
  end
@@ -0,0 +1,26 @@
1
+ module Cats
2
+ module Core
3
+ class ReceiptAuthorization < Authorization
4
+ has_many :receipt_transactions
5
+
6
+ validates :lost_quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
7
+ validate :validate_total_quantity
8
+
9
+ def validate_total_quantity
10
+ return unless dispatch && quantity
11
+
12
+ received = dispatch.receipt_authorizations.sum(:quantity) + dispatch.receipt_authorizations.sum(:lost_quantity)
13
+ diff = dispatch.quantity - received
14
+ diff += quantity_was if quantity_was
15
+ diff += lost_quantity_was if lost_quantity_was
16
+
17
+ errors.add(:quantity, "authorized is higher than dispatch quantity (Max = #{diff}).") if quantity > diff
18
+ end
19
+
20
+ def confirm
21
+ self.status = CONFIRMED
22
+ save!
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,27 +1,29 @@
1
1
  module Cats
2
2
  module Core
3
3
  class ReceiptTransaction < Transaction
4
- belongs_to :receipt
4
+ belongs_to :receipt_authorization
5
5
  belongs_to :destination, class_name: 'Cats::Core::Stack'
6
6
 
7
- delegate(:code, to: :destination, prefix: true)
7
+ validates :transaction_date, presence: true
8
+ validates :quantity, presence: true, numericality: { greater_than: 0 }
9
+ validate :validate_receipt, :validate_quantity
8
10
 
9
- def validate_quantity
10
- return unless quantity.present? && destination.present? && receipt.present?
11
+ delegate(:code, to: :destination, prefix: true)
11
12
 
12
- authorized = receipt.dispatch.dispatch_plan_item.hub_authorizations.where(
13
- store: destination.store
14
- ).sum(:quantity)
15
- received = self.class.joins(:destination).where(
16
- destination: { store_id: destination.store_id }
17
- ).sum(:quantity)
13
+ def validate_receipt
14
+ return unless receipt_authorization
18
15
 
19
- received -= quantity_was if quantity_was
16
+ status = receipt_authorization.status
17
+ errors.add(:receipt_authorization, 'must be confirmed.') if status == ReceiptAuthorization::AUTHORIZED
18
+ end
20
19
 
21
- # Get quantity in hub authorization for source
22
- available = authorized - received
20
+ def validate_quantity
21
+ return unless quantity && destination && receipt_authorization
23
22
 
24
- errors.add(:quantity, "exceeds authorized quantity (Max = #{available}).") if quantity > available
23
+ total = ReceiptTransaction.where(receipt_authorization: receipt_authorization).sum(:quantity)
24
+ diff = receipt_authorization.quantity - total
25
+ diff += quantity_was if quantity_was
26
+ errors.add(:quantity, "exceeds authorized quantity (Max. = #{diff}).") if quantity > diff
25
27
  end
26
28
 
27
29
  def commit
@@ -12,41 +12,11 @@ module Cats
12
12
  validates :transaction_date, :quantity, :status, presence: true
13
13
  validates :quantity, numericality: { greater_than: 0 }
14
14
  validates :status, inclusion: { in: STATUSES }
15
- validate :validate_quantity, unless: :skip_quantity_validation
16
-
17
- def validate_quantity
18
- return unless quantity.present? && source.present? && dispatch.present?
19
-
20
- dispatched = self.class.joins(:source, :dispatch).where(
21
- source: { store_id: source.store_id },
22
- dispatch: { dispatch_plan_item_id: dispatch.dispatch_plan_item_id }
23
- ).sum(:quantity)
24
- dispatched -= quantity_was if quantity_was
25
-
26
- # Get quantity in hub authorization for source
27
- authorized = dispatch.dispatch_plan_item.hub_authorizations.where(store_id: source.store_id).sum(:quantity)
28
- available = authorized - dispatched
29
-
30
- errors.add(:quantity, "exceeds authorized quantity (Max = #{available}).") if quantity > available
31
- end
32
15
 
33
16
  def commit
34
17
  raise(NotImplementedError, 'Method should be implemented in child classes.')
35
18
  end
36
19
 
37
- def skip_quantity_validation
38
- # Quantity validation should be skipped if we are commiting transactions.
39
- (
40
- instance_of?(Cats::Core::DispatchTransaction) &&
41
- dispatch &&
42
- status == COMMITTED
43
- ) || (
44
- instance_of?(Cats::Core::ReceiptTransaction) &&
45
- receipt &&
46
- receipt.status == Cats::Core::Receipt::STACKING
47
- )
48
- end
49
-
50
20
  def set_status
51
21
  return unless new_record?
52
22
 
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class DispatchAuthorizationSerializer < ActiveModel::Serializer
4
+ attributes :id, :dispatch_id, :dispatch_reference_no, :store_id, :store_name, :quantity, :authorized_by_id,
5
+ :authorizer_full_name
6
+ end
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
1
  module Cats
2
2
  module Core
3
3
  class DispatchPlanItemSerializer < ActiveModel::Serializer
4
- attributes :id, :dispatch_plan_id, :plan_reference_no, :source_id, :source_name, :destination_id,
4
+ attributes :id, :reference_no, :dispatch_plan_id, :plan_reference_no, :source_id, :source_name, :destination_id,
5
5
  :destination_name, :quantity, :source_location_type, :destination_location_type, :commodity_status,
6
6
  :status, :commodity_id, :commodity_name, :commodity_batch_no
7
7
  end
@@ -1,8 +1,7 @@
1
1
  module Cats
2
2
  module Core
3
3
  class DispatchTransactionSerializer < ActiveModel::Serializer
4
- attributes :id, :source_id, :source_code, :dispatch_id, :dispatch_reference_no, :quantity,
5
- :transaction_date, :status
4
+ attributes :id, :source_id, :source_code, :dispatch_authorization_id, :quantity, :transaction_date, :status
6
5
  end
7
6
  end
8
7
  end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class ReceiptAuthorizationSerializer < ActiveModel::Serializer
4
+ attributes :id, :dispatch_id, :dispatch_reference_no, :store_id, :store_name, :quantity, :lost_quantity, :remark,
5
+ :status, :authorized_by_id, :authorizer_full_name
6
+ end
7
+ end
8
+ end
@@ -1,11 +1,11 @@
1
1
  module Cats
2
2
  module Core
3
3
  class ReceiptTransactionSerializer < ActiveModel::Serializer
4
- attributes :id, :receipt_id, :dispatch_reference, :destination_id, :destination_code, :quantity,
4
+ attributes :id, :receipt_authorization_id, :dispatch_reference, :destination_id, :destination_code, :quantity,
5
5
  :transaction_date, :status
6
6
 
7
7
  def dispatch_reference
8
- object.receipt.dispatch.reference_no
8
+ object.receipt_authorization.dispatch.reference_no
9
9
  end
10
10
  end
11
11
  end
data/config/routes.rb CHANGED
@@ -99,7 +99,8 @@ Cats::Core::Engine.routes.draw do
99
99
  get '/dispatches/search', controller: :dispatches, action: :search, as: :search_dispatches
100
100
  resources :dispatches, except: %i[index destroy] do
101
101
  member do
102
- get 'transactions', controller: :dispatch_transactions, action: :index
102
+ get 'dispatch_authorizations', controller: :dispatch_authorizations, action: :index
103
+ get 'receipt_authorizations', controller: :receipt_authorizations, action: :index
103
104
  get 'receipts', controller: :receipts, action: :index
104
105
  get 'lost', controller: :lost_commodities, action: :index
105
106
  get 'commodity'
@@ -109,6 +110,20 @@ Cats::Core::Engine.routes.draw do
109
110
  end
110
111
  end
111
112
 
113
+ resources :dispatch_authorizations, except: %i[index destory] do
114
+ member do
115
+ get 'transactions', controller: :dispatch_transactions, action: :index
116
+ post 'confirm', controller: :dispatch_authorizations, action: :confirm
117
+ end
118
+ end
119
+
120
+ resources :receipt_authorizations, except: %i[index destroy] do
121
+ member do
122
+ get 'transactions', controller: :receipt_transactions, action: :index
123
+ post 'confirm', controller: :receipt_authorizations, action: :confirm
124
+ end
125
+ end
126
+
112
127
  post(
113
128
  'dispatch_transactions/allocation',
114
129
  controller: :dispatch_transactions,
@@ -116,13 +131,6 @@ Cats::Core::Engine.routes.draw do
116
131
  as: :allocation_transaction
117
132
  )
118
133
  resources :dispatch_transactions, except: %i[index new edit destroy]
119
- resources :receipts, except: %i[index new edit destroy] do
120
- member do
121
- get 'transactions', controller: :receipt_transactions, action: :index
122
- post 'start_stacking'
123
- post 'finish_stacking'
124
- end
125
- end
126
134
  resources :receipt_transactions, except: %i[index new edit destroy]
127
135
  resources :lost_commodities, except: %i[index destroy]
128
136
  get '/plans/:id/round_plans', controller: :round_plans, action: :index, as: :round_plans_plan
@@ -1,6 +1,7 @@
1
1
  class CreateCatsCoreDispatchPlanItems < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  create_table :cats_core_dispatch_plan_items do |t|
4
+ t.string :reference_no, null: false, unique: true
4
5
  t.references :dispatch_plan,
5
6
  null: false,
6
7
  index: { name: 'dpi_on_dp_indx' },
@@ -14,6 +14,10 @@ class CreateCatsCoreDispatches < ActiveRecord::Migration[6.1]
14
14
  t.string :driver_name, null: false
15
15
  t.string :driver_phone, null: false
16
16
  t.float :quantity, null: false, default: 0
17
+ t.references :unit,
18
+ null: false,
19
+ index: { name: 'unit_on_dispatches_indx' },
20
+ foreign_key: { to_table: :cats_core_unit_of_measures }
17
21
  t.string :commodity_status, null: false, default: 'Good'
18
22
  t.string :remark
19
23
  t.references :prepared_by,
@@ -0,0 +1,22 @@
1
+ class CreateCatsCoreDispatchAuthorizations < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :cats_core_dispatch_authorizations do |t|
4
+ t.references :dispatch,
5
+ null: false,
6
+ index: { name: 'dispatch_on_da_indx' },
7
+ foreign_key: { to_table: :cats_core_dispatches }
8
+ t.references :store,
9
+ null: false,
10
+ index: { name: 'store_on_da_indx' },
11
+ foreign_key: { to_table: :cats_core_stores }
12
+ t.float :quantity, null: false
13
+ t.string :status, null: false, default: 'Authorized'
14
+ t.references :authorized_by,
15
+ null: false,
16
+ index: { name: 'ab_on_da_indx' },
17
+ foreign_key: { to_table: :cats_core_users }
18
+
19
+ t.timestamps
20
+ end
21
+ end
22
+ end
@@ -5,15 +5,21 @@ class CreateCatsCoreDispatchTransactions < ActiveRecord::Migration[6.1]
5
5
  null: false,
6
6
  index: { name: 'stack_on_dt_indx' },
7
7
  foreign_key: { to_table: :cats_core_stacks }
8
- t.references :dispatch,
8
+ t.references :dispatch_authorization,
9
9
  null: false,
10
- index: { name: 'dispatch_on_dt_indx' },
11
- foreign_key: { to_table: :cats_core_dispatches }
10
+ index: { name: 'da_on_dt_indx' },
11
+ foreign_key: { to_table: :cats_core_dispatch_authorizations }
12
12
  t.date :transaction_date, null: false
13
13
  t.float :quantity, null: false
14
14
  t.string :status, null: false, default: 'Draft'
15
15
 
16
16
  t.timestamps
17
17
  end
18
+ add_index(
19
+ :cats_core_dispatch_transactions,
20
+ [:source_id, :dispatch_authorization_id],
21
+ unique: true,
22
+ name: 'sda_on_dt_uniq_indx'
23
+ )
18
24
  end
19
25
  end
@@ -0,0 +1,24 @@
1
+ class CreateCatsCoreReceiptAuthorizations < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :cats_core_receipt_authorizations do |t|
4
+ t.references :dispatch,
5
+ null: false,
6
+ index: { name: 'dispatch_on_receipt_authorizations_indx' },
7
+ foreign_key: { to_table: :cats_core_dispatches }
8
+ t.references :store,
9
+ null: false,
10
+ index: { name: 'store_on_ra_indx' },
11
+ foreign_key: { to_table: :cats_core_stores }
12
+ t.float :quantity, null: false
13
+ t.float :lost_quantity, null: false, default: 0
14
+ t.string :status, null: false, default: 'Authorized'
15
+ t.string :remark
16
+ t.references :authorized_by,
17
+ null: false,
18
+ index: { name: 'ab_on_receipt_authorizations_indx' },
19
+ foreign_key: { to_table: :cats_core_users }
20
+
21
+ t.timestamps
22
+ end
23
+ end
24
+ end
@@ -1,10 +1,10 @@
1
1
  class CreateCatsCoreReceiptTransactions < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  create_table :cats_core_receipt_transactions do |t|
4
- t.references :receipt,
4
+ t.references :receipt_authorization,
5
5
  null: false,
6
- index: { name: 'receipt_on_rt_indx' },
7
- foreign_key: { to_table: :cats_core_receipts }
6
+ index: { name: 'receipt_authorization_on_rt_indx' },
7
+ foreign_key: { to_table: :cats_core_receipt_authorizations }
8
8
  t.references :destination,
9
9
  null: false,
10
10
  index: { name: 'stack_on_rt_indx' },
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.4.21'.freeze
3
+ VERSION = '1.4.22'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,26 @@
1
+ FactoryBot.define do
2
+ factory :dispatch_authorization, class: 'Cats::Core::DispatchAuthorization' do
3
+ transient do
4
+ s { create(:store) }
5
+ stack { create(:stack, quantity: 100, store: s) }
6
+ end
7
+ dispatch
8
+ store { s }
9
+ quantity { 100 }
10
+ status { Cats::Core::ReceiptAuthorization::AUTHORIZED }
11
+ authorized_by factory: :user
12
+
13
+ trait :approved do
14
+ after(:create) do |obj|
15
+ obj.dispatch.approve
16
+ end
17
+ end
18
+
19
+ trait :with_transaction do
20
+ after(:create) do |obj, options|
21
+ obj.dispatch.approve
22
+ create(:dispatch_transaction, dispatch_authorization: obj, source: options.stack, quantity: 100)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :dispatch_plan_item, class: 'Cats::Core::DispatchPlanItem' do
3
+ reference_no { FFaker::Name.name }
3
4
  source factory: :location
4
5
  destination factory: :location
5
6
  dispatch_plan
@@ -4,14 +4,9 @@ FactoryBot.define do
4
4
  stack { create(:stack) }
5
5
  end
6
6
  source { stack }
7
- dispatch do
8
- plan_item = create(:dispatch_plan_item, quantity: 100)
9
- plan_item.dispatch_plan.approve
10
- create(:hub_authorization, dispatch_plan_item: plan_item, quantity: 100, store: stack.store)
11
- create(:dispatch, dispatch_plan_item: plan_item, transaction?: false)
12
- end
7
+ association :dispatch_authorization, :approved
13
8
  transaction_date { Date.today }
14
- quantity { 10 }
9
+ quantity { 100 }
15
10
  status { Cats::Core::Transaction::DRAFT }
16
11
  end
17
12
  end
@@ -2,7 +2,6 @@ FactoryBot.define do
2
2
  factory :dispatch, class: 'Cats::Core::Dispatch' do
3
3
  transient do
4
4
  stack { create(:stack, quantity: 100) }
5
- transaction? { true }
6
5
  end
7
6
  reference_no { FFaker::Name.name }
8
7
  dispatch_plan_item do
@@ -11,6 +10,7 @@ FactoryBot.define do
11
10
  create(:hub_authorization, dispatch_plan_item: plan_item, quantity: 100, store: stack.store)
12
11
  plan_item
13
12
  end
13
+ unit factory: :unit_of_measure
14
14
  transporter
15
15
  plate_no { FFaker::Name.name }
16
16
  driver_name { FFaker::Name.name }
@@ -19,8 +19,27 @@ FactoryBot.define do
19
19
  prepared_by factory: :user
20
20
  dispatch_status { Cats::Core::Dispatch::DRAFT }
21
21
 
22
- after :create do |dispatch, options|
23
- create(:dispatch_transaction, dispatch: dispatch, source: options.stack, quantity: 100) if options.transaction?
22
+ trait :with_authorization do
23
+ after(:create) do |dispatch, options|
24
+ create(:dispatch_authorization, dispatch: dispatch, store: options.stack.store)
25
+ end
26
+ end
27
+
28
+ trait :with_transaction do
29
+ after(:create) do |dispatch, options|
30
+ authorization = create(:dispatch_authorization, dispatch: dispatch, store: options.stack.store)
31
+ dispatch.approve
32
+ create(:dispatch_transaction, dispatch_authorization: authorization, source: options.stack, quantity: 100)
33
+ end
34
+ end
35
+
36
+ trait :started do
37
+ after(:create) do |dispatch, options|
38
+ authorization = create(:dispatch_authorization, dispatch: dispatch, store: options.stack.store)
39
+ dispatch.approve
40
+ create(:dispatch_transaction, dispatch_authorization: authorization, source: options.stack, quantity: 100)
41
+ dispatch.start
42
+ end
24
43
  end
25
44
  end
26
45
  end
@@ -0,0 +1,19 @@
1
+ FactoryBot.define do
2
+ factory :receipt_authorization, class: 'Cats::Core::ReceiptAuthorization' do
3
+ dispatch do
4
+ dispatch = create(:dispatch, :with_transaction)
5
+ dispatch.start
6
+ dispatch
7
+ end
8
+ store
9
+ quantity { 100 }
10
+ lost_quantity { 0 }
11
+ remark { FFaker::Name.name }
12
+ status { Cats::Core::ReceiptAuthorization::AUTHORIZED }
13
+ authorized_by factory: :user
14
+
15
+ trait :confirmed do
16
+ status { Cats::Core::ReceiptAuthorization::CONFIRMED }
17
+ end
18
+ end
19
+ end
@@ -1,27 +1,7 @@
1
1
  FactoryBot.define do
2
2
  factory :receipt_transaction, class: 'Cats::Core::ReceiptTransaction' do
3
- transient do
4
- dispatch { create(:dispatch) }
5
- end
6
- transient do
7
- stack { create(:stack) }
8
- end
9
-
10
- destination { stack }
11
- receipt do
12
- dispatch.approve
13
- dispatch.start
14
- receipt = create(:receipt, dispatch: dispatch)
15
- dispatch.confirm
16
- create(
17
- :hub_authorization,
18
- authorization_type: Cats::Core::HubAuthorization::DESTINATION,
19
- dispatch_plan_item: dispatch.dispatch_plan_item,
20
- store: stack.store,
21
- quantity: 100
22
- )
23
- receipt
24
- end
3
+ association :receipt_authorization, :confirmed
4
+ destination factory: :stack
25
5
  transaction_date { Date.today }
26
6
  quantity { 100 }
27
7
  status { Cats::Core::Transaction::DRAFT }
@@ -10,6 +10,6 @@ FactoryBot.define do
10
10
  store
11
11
  commodity_status { Cats::Core::Commodity::GOOD }
12
12
  stack_status { Cats::Core::Stack::RESERVED }
13
- quantity { 50 }
13
+ quantity { 100 }
14
14
  end
15
15
  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.21
4
+ version: 1.4.22
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-05-19 00:00:00.000000000 Z
11
+ date: 2022-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -235,6 +235,7 @@ files:
235
235
  - app/controllers/cats/core/commodities_controller.rb
236
236
  - app/controllers/cats/core/commodity_categories_controller.rb
237
237
  - app/controllers/cats/core/currencies_controller.rb
238
+ - app/controllers/cats/core/dispatch_authorizations_controller.rb
238
239
  - app/controllers/cats/core/dispatch_plan_items_controller.rb
239
240
  - app/controllers/cats/core/dispatch_plans_controller.rb
240
241
  - app/controllers/cats/core/dispatch_transactions_controller.rb
@@ -243,8 +244,8 @@ files:
243
244
  - app/controllers/cats/core/lost_commodities_controller.rb
244
245
  - app/controllers/cats/core/menus_controller.rb
245
246
  - app/controllers/cats/core/notifications_controller.rb
247
+ - app/controllers/cats/core/receipt_authorizations_controller.rb
246
248
  - app/controllers/cats/core/receipt_transactions_controller.rb
247
- - app/controllers/cats/core/receipts_controller.rb
248
249
  - app/controllers/cats/core/roles_controller.rb
249
250
  - app/controllers/cats/core/round_plans_controller.rb
250
251
  - app/controllers/cats/core/routes_controller.rb
@@ -258,6 +259,7 @@ files:
258
259
  - app/jobs/cats/core/application_job.rb
259
260
  - app/models/cats/core/application_module.rb
260
261
  - app/models/cats/core/application_record.rb
262
+ - app/models/cats/core/authorization.rb
261
263
  - app/models/cats/core/beneficiary.rb
262
264
  - app/models/cats/core/beneficiary_category.rb
263
265
  - app/models/cats/core/beneficiary_plan_item.rb
@@ -268,6 +270,7 @@ files:
268
270
  - app/models/cats/core/contract_item.rb
269
271
  - app/models/cats/core/currency.rb
270
272
  - app/models/cats/core/dispatch.rb
273
+ - app/models/cats/core/dispatch_authorization.rb
271
274
  - app/models/cats/core/dispatch_plan.rb
272
275
  - app/models/cats/core/dispatch_plan_item.rb
273
276
  - app/models/cats/core/dispatch_transaction.rb
@@ -289,7 +292,7 @@ files:
289
292
  - app/models/cats/core/program.rb
290
293
  - app/models/cats/core/purchase_order.rb
291
294
  - app/models/cats/core/ration.rb
292
- - app/models/cats/core/receipt.rb
295
+ - app/models/cats/core/receipt_authorization.rb
293
296
  - app/models/cats/core/receipt_transaction.rb
294
297
  - app/models/cats/core/rhn_request.rb
295
298
  - app/models/cats/core/role.rb
@@ -328,12 +331,14 @@ files:
328
331
  - app/serializers/cats/core/commodity_category_serializer.rb
329
332
  - app/serializers/cats/core/commodity_serializer.rb
330
333
  - app/serializers/cats/core/currency_serializer.rb
334
+ - app/serializers/cats/core/dispatch_authorization_serializer.rb
331
335
  - app/serializers/cats/core/dispatch_plan_item_serializer.rb
332
336
  - app/serializers/cats/core/dispatch_plan_serializer.rb
333
337
  - app/serializers/cats/core/dispatch_serializer.rb
334
338
  - app/serializers/cats/core/dispatch_transaction_serializer.rb
335
339
  - app/serializers/cats/core/location_serializer.rb
336
340
  - app/serializers/cats/core/lost_commodity_serializer.rb
341
+ - app/serializers/cats/core/receipt_authorization_serializer.rb
337
342
  - app/serializers/cats/core/receipt_serializer.rb
338
343
  - app/serializers/cats/core/receipt_transaction_serializer.rb
339
344
  - app/serializers/cats/core/role_menu_serializer.rb
@@ -349,7 +354,6 @@ files:
349
354
  - app/services/cats/core/dispatch_service.rb
350
355
  - app/services/cats/core/menu_service.rb
351
356
  - app/services/cats/core/notification_service.rb
352
- - app/services/cats/core/receipt_service.rb
353
357
  - app/services/cats/core/round_plan_service.rb
354
358
  - app/services/cats/core/space_service.rb
355
359
  - app/services/cats/core/stack_service.rb
@@ -387,10 +391,11 @@ files:
387
391
  - db/migrate/20210718043328_create_cats_core_dispatch_plans.rb
388
392
  - db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb
389
393
  - db/migrate/20210718045516_create_cats_core_dispatches.rb
394
+ - db/migrate/20210718055414_create_cats_core_dispatch_authorizations.rb
390
395
  - db/migrate/20210718202957_create_cats_core_dispatch_transactions.rb
391
396
  - db/migrate/20210719133710_create_cats_core_stacking_rules.rb
392
397
  - db/migrate/20210724074657_create_cats_core_notifications.rb
393
- - db/migrate/20210727074646_create_cats_core_receipts.rb
398
+ - db/migrate/20210727074646_create_cats_core_receipt_authorizations.rb
394
399
  - db/migrate/20210728041505_create_cats_core_lost_commodities.rb
395
400
  - db/migrate/20210814160628_create_cats_core_receipt_transactions.rb
396
401
  - db/migrate/20210814175406_create_cats_core_stack_transactions.rb
@@ -435,6 +440,7 @@ files:
435
440
  - spec/factories/cats/core/commodity_substitutions.rb
436
441
  - spec/factories/cats/core/contract_items.rb
437
442
  - spec/factories/cats/core/currencies.rb
443
+ - spec/factories/cats/core/dispatch_authorizations.rb
438
444
  - spec/factories/cats/core/dispatch_plan_items.rb
439
445
  - spec/factories/cats/core/dispatch_plans.rb
440
446
  - spec/factories/cats/core/dispatch_transactions.rb
@@ -457,8 +463,8 @@ files:
457
463
  - spec/factories/cats/core/programs.rb
458
464
  - spec/factories/cats/core/purchase_orders.rb
459
465
  - spec/factories/cats/core/rations.rb
466
+ - spec/factories/cats/core/receipt_authorizations.rb
460
467
  - spec/factories/cats/core/receipt_transactions.rb
461
- - spec/factories/cats/core/receipts.rb
462
468
  - spec/factories/cats/core/rhn_requests.rb
463
469
  - spec/factories/cats/core/role_menus.rb
464
470
  - spec/factories/cats/core/roles.rb
@@ -1,45 +0,0 @@
1
- module Cats
2
- module Core
3
- class ReceiptsController < ApplicationController
4
- include Common
5
-
6
- def index
7
- super do
8
- Receipt.where(dispatch_id: params[:id])
9
- end
10
- end
11
-
12
- def create
13
- super do
14
- service = ReceiptService.new
15
- receipt = service.init(model_params)
16
- receipt
17
- end
18
- end
19
-
20
- def start_stacking
21
- receipt = Receipt.find(params[:id])
22
- service = ReceiptService.new
23
- result = service.start_stacking(receipt)
24
- render json: { success: true, data: serialize(result) }
25
- rescue StandardError => e
26
- render json: { success: false, error: e.message }
27
- end
28
-
29
- def finish_stacking
30
- receipt = Receipt.find(params[:id])
31
- service = ReceiptService.new
32
- result = service.finish_stacking(receipt)
33
- render json: { success: true, data: serialize(result) }
34
- rescue StandardError => e
35
- render json: { success: false, error: e.message }
36
- end
37
-
38
- private
39
-
40
- def model_params
41
- params.require(:payload).permit(:dispatch_id, :quantity, :commodity_status, :status, :remark, :prepared_by_id)
42
- end
43
- end
44
- end
45
- end
@@ -1,44 +0,0 @@
1
- module Cats
2
- module Core
3
- class Receipt < ApplicationRecord
4
- # Receipt status
5
- DRAFT = 'Draft'.freeze
6
- CONFIRMED = 'Confirmed'.freeze
7
- STACKING = 'Stacking'.freeze
8
- STACKED = 'Stacked'.freeze
9
- RECEIPT_STATUSES = [DRAFT, CONFIRMED, STACKING, STACKED].freeze
10
-
11
- belongs_to :dispatch
12
- belongs_to :prepared_by, class_name: 'Cats::Core::User'
13
- has_many :receipt_transactions
14
-
15
- validates :quantity, :commodity_status, :status, presence: true
16
- validates :quantity, numericality: { greater_than: 0 }
17
- validates :status, inclusion: { in: RECEIPT_STATUSES }
18
- validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
19
- validate :validate_dispatch_status, :validate_total_quantity
20
-
21
- delegate(:reference_no, to: :dispatch, prefix: true)
22
- delegate(:email, to: :prepared_by, prefix: true)
23
-
24
- def validate_dispatch_status
25
- return unless dispatch
26
-
27
- statuses = [Cats::Core::Dispatch::STARTED, Cats::Core::Dispatch::RECEIVED]
28
- return if statuses.include?(dispatch.dispatch_status)
29
-
30
- errors.add(:dispatch, 'should be in "Started" state.')
31
- end
32
-
33
- def validate_total_quantity
34
- return unless dispatch && quantity
35
-
36
- received = dispatch.receipts.sum(:quantity) + dispatch.lost_commodities.sum(:quantity)
37
- diff = dispatch.quantity - received
38
- diff += quantity_was if quantity_was
39
-
40
- errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff}).") if quantity > diff
41
- end
42
- end
43
- end
44
- end
@@ -1,48 +0,0 @@
1
- module Cats
2
- module Core
3
- class ReceiptService
4
- def start_stacking(receipt)
5
- raise(StandardError, 'Receipt should be confirmed.') unless receipt.status == Cats::Core::Receipt::CONFIRMED
6
-
7
- raise(StandardError, 'There are no stack assignments in receipt.') if receipt.receipt_transactions.count.zero?
8
-
9
- receipt.status = Cats::Core::Receipt::STACKING
10
- receipt.save!
11
- receipt
12
- end
13
-
14
- def finish_stacking(receipt)
15
- unless receipt.status == Cats::Core::Receipt::STACKING
16
- raise(StandardError, 'Receipt should be in stacking state.')
17
- end
18
-
19
- receipt.receipt_transactions.each(&:commit)
20
- receipt.status = Cats::Core::Receipt::STACKED
21
- receipt.save!
22
- receipt
23
- end
24
-
25
- def init(params)
26
- receipt = Cats::Core::Receipt.find_by(
27
- dispatch_id: params[:dispatch_id],
28
- commodity_status: params[:commodity_status]
29
- )
30
-
31
- if receipt
32
- # We can assume that the plan item is destination authorized.
33
- # Therefore no need for checking destination authorization.
34
- receipt.quantity += params[:quantity]
35
- return receipt
36
- end
37
-
38
- # Check if plan item is destination authorized
39
- dispatch = Dispatch.find(params[:dispatch_id])
40
- status = dispatch.dispatch_plan_item.status
41
- statuses = [DispatchPlanItem::DESTINATION_AUTHORIZED, DispatchPlanItem::AUTHORIZED]
42
- raise(StandardError, 'Plan item is not destination authorized.') unless statuses.include?(status)
43
-
44
- Receipt.new(params)
45
- end
46
- end
47
- end
48
- end
@@ -1,20 +0,0 @@
1
- class CreateCatsCoreReceipts < ActiveRecord::Migration[6.1]
2
- def change
3
- create_table :cats_core_receipts do |t|
4
- t.references :dispatch,
5
- null: false,
6
- index: { name: 'dispatch_on_receipts_indx' },
7
- foreign_key: { to_table: :cats_core_dispatches }
8
- t.float :quantity, null: false
9
- t.string :commodity_status, null: false, default: 'Good'
10
- t.string :status, null: false, default: 'Draft'
11
- t.string :remark
12
- t.references :prepared_by,
13
- null: false,
14
- index: { name: 'pb_on_receipts_indx' },
15
- foreign_key: { to_table: :cats_core_users }
16
-
17
- t.timestamps
18
- end
19
- end
20
- end
@@ -1,15 +0,0 @@
1
- FactoryBot.define do
2
- factory :receipt, class: 'Cats::Core::Receipt' do
3
- dispatch do
4
- dispatch = create(:dispatch)
5
- dispatch.approve
6
- dispatch.start
7
- dispatch
8
- end
9
- quantity { 100 }
10
- commodity_status { Cats::Core::Commodity::GOOD }
11
- status { Cats::Core::Receipt::DRAFT }
12
- remark { FFaker::Name.name }
13
- prepared_by factory: :user
14
- end
15
- end