cats_core 1.4.20 → 1.4.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/cats/core/dispatch_authorizations_controller.rb +35 -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 +7 -2
- data/app/controllers/cats/core/lost_commodities_controller.rb +2 -2
- data/app/controllers/cats/core/receipt_authorizations_controller.rb +27 -0
- data/app/controllers/cats/core/receipt_transactions_controller.rb +2 -20
- data/app/controllers/cats/core/receipts_controller.rb +2 -28
- data/app/models/cats/core/authorization.rb +77 -0
- data/app/models/cats/core/dispatch.rb +30 -47
- 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/lost_commodity.rb +2 -3
- data/app/models/cats/core/receipt.rb +3 -37
- data/app/models/cats/core/receipt_authorization.rb +22 -0
- data/app/models/cats/core/receipt_transaction.rb +17 -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/lost_commodity_serializer.rb +1 -1
- data/app/serializers/cats/core/receipt_authorization_serializer.rb +8 -0
- data/app/serializers/cats/core/receipt_serializer.rb +1 -2
- data/app/serializers/cats/core/receipt_transaction_serializer.rb +1 -5
- data/app/services/cats/core/authorization_service.rb +25 -0
- data/config/routes.rb +26 -9
- 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/20210727105834_create_cats_core_receipts.rb +15 -0
- data/db/migrate/20210728041505_create_cats_core_lost_commodities.rb +3 -4
- 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 +38 -3
- data/spec/factories/cats/core/lost_commodities.rb +1 -2
- data/spec/factories/cats/core/receipt_authorizations.rb +25 -0
- data/spec/factories/cats/core/receipt_transactions.rb +2 -22
- data/spec/factories/cats/core/receipts.rb +2 -9
- data/spec/factories/cats/core/stacks.rb +1 -1
- metadata +15 -4
- data/app/services/cats/core/receipt_service.rb +0 -48
- data/db/migrate/20210727074646_create_cats_core_receipts.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c58aa13420d9d6df2e5954237e8d8fbfef4db3d620636a49bba9ba2c6d30eb2
|
4
|
+
data.tar.gz: 6ff8e9bc22538cef900ed1e4ef1d80620699f5b94df2bbf8771f37cf4b0367b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: caf7a1b4209a0405e22dbf86736424ce82f577ded281348911faed27a1cbc9e232c35eea14cdb768d2655aaa8dcce9fda5362ac3c60ec088b13522a191eeabbc
|
7
|
+
data.tar.gz: 2992ab176cd20d2e82a56ac9fc178d5aa06cc8870aa67c5c545f42804c9d31dc082203ef5cdebae968b69aee147689056d06401cffe35f4d566d0c5026bf470c
|
@@ -0,0 +1,35 @@
|
|
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
|
+
service = AuthorizationService.new
|
14
|
+
authorization = service.confirm(params[:id])
|
15
|
+
render json: { success: true, data: serialize(authorization) }
|
16
|
+
rescue StandardError => e
|
17
|
+
render json: { success: false, error: e.message }
|
18
|
+
end
|
19
|
+
|
20
|
+
def storekeeper_authorizations
|
21
|
+
storekeeper = User.find(params[:id])
|
22
|
+
stores = storekeeper.stores
|
23
|
+
authorizations = DispatchAuthorization.joins(:dispatch)
|
24
|
+
.where(store: stores, dispatch: { dispatch_status: Dispatch::APPROVED })
|
25
|
+
render json: { success: true, data: serialize(authorizations) }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def model_params
|
31
|
+
params.require(:payload).permit(:dispatch_id, :store_id, :quantity, :status, :authorized_by_id)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
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
|
@@ -43,6 +43,11 @@ module Cats
|
|
43
43
|
render json: { success: false, error: e.message }
|
44
44
|
end
|
45
45
|
|
46
|
+
def filter
|
47
|
+
query = Dispatch.ransack(params[:q])
|
48
|
+
render json: { success: true, data: serialize(query.result) }
|
49
|
+
end
|
50
|
+
|
46
51
|
def search
|
47
52
|
data = @service.search(current_user, params[:status])
|
48
53
|
render json: { success: true, data: serialize(data) }
|
@@ -60,8 +65,8 @@ module Cats
|
|
60
65
|
end
|
61
66
|
|
62
67
|
def model_params
|
63
|
-
params.require(:payload).permit(:reference_no, :dispatch_plan_item_id, :transporter_id, :plate_no,
|
64
|
-
:driver_name, :driver_phone, :
|
68
|
+
params.require(:payload).permit(:reference_no, :dispatch_plan_item_id, :transporter_id, :plate_no, :unit_id,
|
69
|
+
:driver_name, :driver_phone, :remark)
|
65
70
|
end
|
66
71
|
end
|
67
72
|
end
|
@@ -5,12 +5,12 @@ module Cats
|
|
5
5
|
|
6
6
|
def index
|
7
7
|
super do
|
8
|
-
LostCommodity.where(
|
8
|
+
LostCommodity.where(receipt_authorization_id: params[:id])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def model_params
|
13
|
-
params.require(:payload).permit(:
|
13
|
+
params.require(:payload).permit(:receipt_authorization_id, :quantity, :remark)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -0,0 +1,27 @@
|
|
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, :remark, :status, :authorized_by_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
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
|
@@ -5,40 +5,14 @@ module Cats
|
|
5
5
|
|
6
6
|
def index
|
7
7
|
super do
|
8
|
-
Receipt.where(
|
8
|
+
Receipt.where(receipt_authorization_id: params[:id])
|
9
9
|
end
|
10
10
|
end
|
11
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
12
|
private
|
39
13
|
|
40
14
|
def model_params
|
41
|
-
params.require(:payload).permit(:
|
15
|
+
params.require(:payload).permit(:receipt_authorization_id, :commodity_status, :quantity, :remark)
|
42
16
|
end
|
43
17
|
end
|
44
18
|
end
|
@@ -0,0 +1,77 @@
|
|
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
|
+
delegate(:dispatch_status, to: :dispatch)
|
24
|
+
delegate(:plate_no, to: :dispatch)
|
25
|
+
delegate(:driver_name, to: :dispatch)
|
26
|
+
|
27
|
+
def validate_dispatch_status
|
28
|
+
return unless dispatch
|
29
|
+
|
30
|
+
if instance_of?(DispatchAuthorization)
|
31
|
+
errors.add(:dispatch, 'is not in draft state.') unless dispatch.dispatch_status == Dispatch::DRAFT
|
32
|
+
else
|
33
|
+
return if dispatch.dispatch_status == Cats::Core::Dispatch::STARTED
|
34
|
+
|
35
|
+
errors.add(:dispatch, 'should be in "Started" state.')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# A convenience method to return dispatch or receipt transactions based on the
|
40
|
+
# authorization type.
|
41
|
+
def transactions
|
42
|
+
return dispatch_transactions if instance_of?(DispatchAuthorization)
|
43
|
+
|
44
|
+
return receipt_transactions if instance_of?(ReceiptAuthorization)
|
45
|
+
end
|
46
|
+
|
47
|
+
def confirm
|
48
|
+
if instance_of?(DispatchAuthorization)
|
49
|
+
raise(StandardError, 'Authorization does not have transactions.') if transactions.blank?
|
50
|
+
|
51
|
+
transactions.each(&:commit)
|
52
|
+
# count = transactions.where(status: Transaction::DRAFT).count
|
53
|
+
# raise(StandardError, 'There are uncommitted transactions.') if count.positive?
|
54
|
+
elsif instance_of?(ReceiptAuthorization)
|
55
|
+
raise(StandardError, 'Authorization does not have receipts.') unless receipts.count.positive?
|
56
|
+
|
57
|
+
total_received = receipts.sum(:quantity)
|
58
|
+
total_lost = lost_commodities.sum(:quantity)
|
59
|
+
diff = quantity - (total_received + total_lost)
|
60
|
+
raise(StandardError, "A quantity of #{diff} is unaccounted for.") unless diff.zero?
|
61
|
+
|
62
|
+
self.received_quantity = total_received
|
63
|
+
end
|
64
|
+
self.status = CONFIRMED
|
65
|
+
save!
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def set_status
|
71
|
+
return unless new_record?
|
72
|
+
|
73
|
+
self.status = AUTHORIZED
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -3,43 +3,36 @@ module Cats
|
|
3
3
|
class Dispatch < ApplicationRecord
|
4
4
|
DRAFT = 'Draft'.freeze
|
5
5
|
APPROVED = 'Approved'.freeze
|
6
|
+
READY_TO_START = 'Ready to Start'.freeze
|
6
7
|
STARTED = 'Started'.freeze
|
7
8
|
ARRIVED = 'Arrived'.freeze
|
8
9
|
UNLOADED = 'Unloaded'.freeze
|
9
10
|
RECEIVED = 'Received'.freeze
|
10
11
|
|
11
|
-
DISPATCH_STATUSES = [DRAFT, APPROVED, STARTED, ARRIVED, UNLOADED, RECEIVED].freeze
|
12
|
+
DISPATCH_STATUSES = [DRAFT, APPROVED, READY_TO_START, STARTED, ARRIVED, UNLOADED, RECEIVED].freeze
|
12
13
|
|
13
14
|
belongs_to :prepared_by, class_name: 'Cats::Core::User'
|
14
15
|
belongs_to :transporter
|
15
16
|
belongs_to :dispatch_plan_item
|
16
|
-
|
17
|
-
|
18
|
-
has_many :
|
17
|
+
belongs_to :unit, class_name: 'Cats::Core::UnitOfMeasure'
|
18
|
+
|
19
|
+
has_many :dispatch_authorizations
|
20
|
+
has_many :receipt_authorizations
|
21
|
+
has_many :dispatch_transactions, through: :dispatch_authorizations
|
22
|
+
has_many :receipt_transactions, through: :receipt_authorizations
|
19
23
|
|
20
24
|
validates :reference_no, :plate_no, :driver_name, :driver_phone, :quantity, :commodity_status, presence: true
|
21
25
|
validates :dispatch_status, presence: true, inclusion: { in: DISPATCH_STATUSES }
|
22
26
|
validates :reference_no, uniqueness: true
|
23
27
|
validates :quantity, numericality: { greater_than_or_equal_to: 0 }
|
24
28
|
validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
|
25
|
-
validate :
|
29
|
+
validate :validate_dispatch_plan_status
|
26
30
|
|
27
31
|
delegate(:name, to: :transporter, prefix: true)
|
28
32
|
delegate(:email, to: :prepared_by, prefix: true)
|
29
33
|
|
30
|
-
def
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
def validate_quantity
|
35
|
-
return unless quantity && dispatch_plan_item
|
36
|
-
|
37
|
-
return unless quantity_changed?
|
38
|
-
|
39
|
-
dispatched = dispatch_plan_item.dispatches.sum(:quantity)
|
40
|
-
remaining = dispatch_plan_item.quantity - dispatched
|
41
|
-
remaining += quantity_was if quantity_was
|
42
|
-
errors.add(:quantity, "exceeds allocated quantity. Maximum allowed is #{remaining}") if quantity > remaining
|
34
|
+
def authorized_quantity
|
35
|
+
dispatch_authorizations.sum(:quantity)
|
43
36
|
end
|
44
37
|
|
45
38
|
def validate_dispatch_plan_status
|
@@ -52,42 +45,32 @@ module Cats
|
|
52
45
|
def approve
|
53
46
|
raise(StandardError, 'Dispatch has to be in draft state.') unless dispatch_status == Dispatch::DRAFT
|
54
47
|
|
55
|
-
# Check if dispatch has
|
56
|
-
raise(StandardError, 'Dispatch has no
|
48
|
+
# Check if dispatch has authorizations
|
49
|
+
raise(StandardError, 'Dispatch has no authorizations.') unless dispatch_authorizations.count.positive?
|
57
50
|
|
58
|
-
Dispatch.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
self.dispatch_status = APPROVED
|
63
|
-
save!
|
51
|
+
dispatches = Dispatch.where(dispatch_plan_item: dispatch_plan_item)
|
52
|
+
authorized = dispatches.inject(0) do |result, dispatch|
|
53
|
+
result += dispatch.authorized_quantity
|
54
|
+
result
|
64
55
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
raise(StandardError, 'Dispatch has to be approved first.') unless dispatch_status == Dispatch::APPROVED
|
56
|
+
diff = authorized - dispatch_plan_item.quantity
|
57
|
+
error = "Total authorized quantity exceeds allocated quantity (Extra = #{diff})."
|
58
|
+
raise(StandardError, error) if diff.positive?
|
69
59
|
|
70
|
-
self.dispatch_status =
|
60
|
+
self.dispatch_status = APPROVED
|
71
61
|
save!
|
72
62
|
end
|
73
63
|
|
74
|
-
def
|
75
|
-
|
64
|
+
def all_authorizations_confirmed?
|
65
|
+
statuses = dispatch_authorizations.map(&:status).uniq
|
66
|
+
return true if statuses.length == 1 && statuses[0] == Authorization::CONFIRMED
|
76
67
|
|
77
|
-
|
78
|
-
|
79
|
-
raise(
|
80
|
-
StandardError,
|
81
|
-
"There is an amount of #{diff} in the dispatch which is unaccounted for."
|
82
|
-
)
|
83
|
-
end
|
68
|
+
false
|
69
|
+
end
|
84
70
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
save!
|
89
|
-
receipts.each(&:save!)
|
90
|
-
end
|
71
|
+
def start
|
72
|
+
self.dispatch_status = STARTED
|
73
|
+
save!
|
91
74
|
end
|
92
75
|
|
93
76
|
def self.search_commodity(batch_no)
|
@@ -101,7 +84,7 @@ module Cats
|
|
101
84
|
{
|
102
85
|
batch_no: batch_no,
|
103
86
|
commodity_name: commodity.name,
|
104
|
-
quantity: dispatch.
|
87
|
+
quantity: dispatch.quantity,
|
105
88
|
unit: commodity.unit_abbreviation,
|
106
89
|
location: dispatch.transporter.name,
|
107
90
|
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
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module Cats
|
2
2
|
module Core
|
3
3
|
class LostCommodity < ApplicationRecord
|
4
|
-
belongs_to :
|
4
|
+
belongs_to :receipt_authorization
|
5
5
|
|
6
|
-
validates :quantity, presence: true
|
7
|
-
validates :commodity_status, presence: true, inclusion: { in: Commodity::COMMODITY_STATUSES }
|
6
|
+
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
8
7
|
end
|
9
8
|
end
|
10
9
|
end
|
@@ -1,44 +1,10 @@
|
|
1
1
|
module Cats
|
2
2
|
module Core
|
3
3
|
class Receipt < ApplicationRecord
|
4
|
-
|
5
|
-
DRAFT = 'Draft'.freeze
|
6
|
-
CONFIRMED = 'Confirmed'.freeze
|
7
|
-
STACKING = 'Stacking'.freeze
|
8
|
-
STACKED = 'Stacked'.freeze
|
9
|
-
RECEIPT_STATUSES = [DRAFT, CONFIRMED, STACKING, STACKED].freeze
|
4
|
+
belongs_to :receipt_authorization
|
10
5
|
|
11
|
-
|
12
|
-
|
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
|
6
|
+
validates :commodity_status, presence: true, inclusion: { in: Commodity::COMMODITY_STATUSES }
|
7
|
+
validates :quantity, presence: true, numericality: { greater_than: 0 }
|
42
8
|
end
|
43
9
|
end
|
44
10
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Cats
|
2
|
+
module Core
|
3
|
+
class ReceiptAuthorization < Authorization
|
4
|
+
has_many :receipts
|
5
|
+
has_many :lost_commodities
|
6
|
+
has_many :receipt_transactions
|
7
|
+
|
8
|
+
validates :received_quantity, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
9
|
+
validate :validate_total_quantity
|
10
|
+
|
11
|
+
def validate_total_quantity
|
12
|
+
return unless dispatch && quantity
|
13
|
+
|
14
|
+
received = dispatch.receipt_authorizations.sum(:quantity)
|
15
|
+
diff = dispatch.quantity - received
|
16
|
+
diff += quantity_was if quantity_was
|
17
|
+
|
18
|
+
errors.add(:quantity, "authorized is higher than dispatch quantity (Max = #{diff}).") if quantity > diff
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,27 +1,30 @@
|
|
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
|
-
|
11
|
+
delegate(:code, to: :destination, prefix: true)
|
12
|
+
delegate(:dispatch_reference_no, to: :receipt_authorization)
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
).sum(:quantity)
|
15
|
-
received = self.class.joins(:destination).where(
|
16
|
-
destination: { store_id: destination.store_id }
|
17
|
-
).sum(:quantity)
|
14
|
+
def validate_receipt
|
15
|
+
return unless receipt_authorization
|
18
16
|
|
19
|
-
|
17
|
+
status = receipt_authorization.status
|
18
|
+
errors.add(:receipt_authorization, 'must be confirmed.') if status == ReceiptAuthorization::AUTHORIZED
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
def validate_quantity
|
22
|
+
return unless quantity && destination && receipt_authorization
|
23
23
|
|
24
|
-
|
24
|
+
total = ReceiptTransaction.where(receipt_authorization: receipt_authorization).sum(:quantity)
|
25
|
+
diff = receipt_authorization.quantity - total
|
26
|
+
diff += quantity_was if quantity_was
|
27
|
+
errors.add(:quantity, "exceeds authorized quantity (Max. = #{diff}).") if quantity > diff
|
25
28
|
end
|
26
29
|
|
27
30
|
def commit
|