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.
- checksums.yaml +4 -4
- data/app/controllers/cats/core/dispatch_authorizations_controller.rb +27 -0
- data/app/controllers/cats/core/dispatch_plan_items_controller.rb +2 -2
- data/app/controllers/cats/core/dispatch_transactions_controller.rb +4 -4
- data/app/controllers/cats/core/dispatches_controller.rb +2 -2
- data/app/controllers/cats/core/receipt_authorizations_controller.rb +28 -0
- data/app/controllers/cats/core/receipt_transactions_controller.rb +2 -20
- data/app/models/cats/core/authorization.rb +65 -0
- data/app/models/cats/core/dispatch.rb +25 -46
- data/app/models/cats/core/dispatch_authorization.rb +13 -0
- data/app/models/cats/core/dispatch_plan_item.rb +1 -0
- data/app/models/cats/core/dispatch_transaction.rb +39 -2
- data/app/models/cats/core/receipt_authorization.rb +26 -0
- data/app/models/cats/core/receipt_transaction.rb +16 -14
- data/app/models/cats/core/transaction.rb +0 -30
- data/app/serializers/cats/core/dispatch_authorization_serializer.rb +8 -0
- data/app/serializers/cats/core/dispatch_plan_item_serializer.rb +1 -1
- data/app/serializers/cats/core/dispatch_transaction_serializer.rb +1 -2
- data/app/serializers/cats/core/receipt_authorization_serializer.rb +8 -0
- data/app/serializers/cats/core/receipt_transaction_serializer.rb +2 -2
- data/config/routes.rb +16 -8
- data/db/migrate/20210718043401_create_cats_core_dispatch_plan_items.rb +1 -0
- data/db/migrate/20210718045516_create_cats_core_dispatches.rb +4 -0
- data/db/migrate/20210718055414_create_cats_core_dispatch_authorizations.rb +22 -0
- data/db/migrate/20210718202957_create_cats_core_dispatch_transactions.rb +9 -3
- data/db/migrate/20210727074646_create_cats_core_receipt_authorizations.rb +24 -0
- data/db/migrate/20210814160628_create_cats_core_receipt_transactions.rb +3 -3
- data/lib/cats/core/version.rb +1 -1
- data/spec/factories/cats/core/dispatch_authorizations.rb +26 -0
- data/spec/factories/cats/core/dispatch_plan_items.rb +1 -0
- data/spec/factories/cats/core/dispatch_transactions.rb +2 -7
- data/spec/factories/cats/core/dispatches.rb +22 -3
- data/spec/factories/cats/core/receipt_authorizations.rb +19 -0
- data/spec/factories/cats/core/receipt_transactions.rb +2 -22
- data/spec/factories/cats/core/stacks.rb +1 -1
- metadata +13 -7
- data/app/controllers/cats/core/receipts_controller.rb +0 -45
- data/app/models/cats/core/receipt.rb +0 -44
- data/app/services/cats/core/receipt_service.rb +0 -48
- data/db/migrate/20210727074646_create_cats_core_receipts.rb +0 -20
- data/spec/factories/cats/core/receipts.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3a896be87ee316cd08b40a298effac694bfb59e1207699c50675b4242e0f630
|
4
|
+
data.tar.gz: 3b6d584ce3eacbf6a0f3ffda03c399d84db2c5bf3931666107cf9d7fd014e3ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,
|
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(
|
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
|
-
|
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, :
|
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, :
|
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(
|
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(:
|
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
|
-
|
17
|
-
|
18
|
-
has_many :
|
19
|
-
has_many :
|
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 :
|
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
|
32
|
-
|
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
|
57
|
-
raise(StandardError, 'Dispatch has no
|
47
|
+
# Check if dispatch has authorizations
|
48
|
+
raise(StandardError, 'Dispatch has no authorizations.') unless dispatch_authorizations.count.positive?
|
58
49
|
|
59
|
-
Dispatch.
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
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 =
|
59
|
+
self.dispatch_status = APPROVED
|
72
60
|
save!
|
73
61
|
end
|
74
62
|
|
75
|
-
def
|
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
|
-
|
88
|
-
|
65
|
+
# Commit transactions
|
66
|
+
self.quantity = dispatch_transactions.sum(:quantity)
|
67
|
+
self.dispatch_status = STARTED
|
89
68
|
save!
|
90
|
-
|
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.
|
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 :
|
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 :
|
4
|
+
belongs_to :receipt_authorization
|
5
5
|
belongs_to :destination, class_name: 'Cats::Core::Stack'
|
6
6
|
|
7
|
-
|
7
|
+
validates :transaction_date, presence: true
|
8
|
+
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
9
|
+
validate :validate_receipt, :validate_quantity
|
8
10
|
|
9
|
-
|
10
|
-
return unless quantity.present? && destination.present? && receipt.present?
|
11
|
+
delegate(:code, to: :destination, prefix: true)
|
11
12
|
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
+
status = receipt_authorization.status
|
17
|
+
errors.add(:receipt_authorization, 'must be confirmed.') if status == ReceiptAuthorization::AUTHORIZED
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
20
|
+
def validate_quantity
|
21
|
+
return unless quantity && destination && receipt_authorization
|
23
22
|
|
24
|
-
|
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
|
|
@@ -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, :
|
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, :
|
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.
|
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 '
|
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 :
|
8
|
+
t.references :dispatch_authorization,
|
9
9
|
null: false,
|
10
|
-
index: { name: '
|
11
|
-
foreign_key: { to_table: :
|
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 :
|
4
|
+
t.references :receipt_authorization,
|
5
5
|
null: false,
|
6
|
-
index: { name: '
|
7
|
-
foreign_key: { to_table: :
|
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' },
|
data/lib/cats/core/version.rb
CHANGED
@@ -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
|
@@ -4,14 +4,9 @@ FactoryBot.define do
|
|
4
4
|
stack { create(:stack) }
|
5
5
|
end
|
6
6
|
source { stack }
|
7
|
-
|
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 {
|
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
|
-
|
23
|
-
|
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
|
-
|
4
|
-
|
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 }
|
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.
|
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-
|
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/
|
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/
|
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
|