cats_core 1.1.0 → 1.1.4
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/dispatches_controller.rb +22 -6
- data/app/controllers/cats/core/locations_controller.rb +3 -33
- data/app/controllers/cats/core/receipt_transactions_controller.rb +13 -0
- data/app/controllers/cats/core/receipts_controller.rb +36 -0
- data/app/models/cats/core/dispatch.rb +1 -0
- data/app/models/cats/core/receipt.rb +34 -3
- data/app/models/cats/core/receipt_transaction.rb +2 -0
- data/app/models/cats/core/transaction.rb +18 -3
- data/app/serializers/cats/core/receipt_serializer.rb +4 -0
- data/app/serializers/cats/core/receipt_transaction_serializer.rb +8 -0
- data/app/services/cats/core/dispatch_service.rb +67 -0
- data/app/services/cats/core/receipt_service.rb +32 -0
- data/config/routes.rb +10 -0
- data/lib/cats/core/version.rb +1 -1
- data/spec/factories/cats/core/receipt_transactions.rb +1 -1
- data/spec/factories/cats/core/receipts.rb +2 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63d1bc4e2e97985bc79c49007a2d826b43caec3b8fc31eca51fa4f588d22e10f
|
4
|
+
data.tar.gz: d4d08836b88121d75bd29fb711975726285b9ab5f7b64285ed48349cff51e2e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bc9fdab7012e63bcda95512f54f0fe8586c225a8eec25c88dcc3ed6b0634aa21a6a62ba5e6091f21b718f10d9df93eeabdf0a88a62a78891f244dc2c14d3bac
|
7
|
+
data.tar.gz: 9ced66786a2d6303d5ea944366cf9357ff9d3a9ab8e4406d2a6c490d8969e0c6431b2265e321a965a2ab10c503bc51e4cbdd40766581f8af6ccf844405f58527
|
@@ -3,7 +3,8 @@ module Cats
|
|
3
3
|
class DispatchesController < ApplicationController
|
4
4
|
include Common
|
5
5
|
|
6
|
-
before_action :set_service, only: %i[create_receipt_authorization approve start]
|
6
|
+
before_action :set_service, only: %i[create_receipt_authorization approve start search confirm]
|
7
|
+
before_action :set_dispatch, only: %i[approve start confirm]
|
7
8
|
|
8
9
|
def index
|
9
10
|
dispatches = Cats::Core::Dispatch.where(allocation_item_id: params[:id])
|
@@ -12,6 +13,7 @@ module Cats
|
|
12
13
|
|
13
14
|
def create
|
14
15
|
dispatch = Cats::Core::Dispatch.new(model_params)
|
16
|
+
dispatch.dispatch_status = Cats::Core::Dispatch::DRAFT
|
15
17
|
dispatch.prepared_by = current_user
|
16
18
|
if dispatch.save
|
17
19
|
render json: { success: true, data: serialize(dispatch) }, status: :created
|
@@ -29,30 +31,44 @@ module Cats
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def approve
|
32
|
-
dispatch =
|
33
|
-
dispatch = @service.approve(dispatch)
|
34
|
+
dispatch = @service.approve(@dispatch)
|
34
35
|
render json: { success: true, data: serialize(dispatch) }
|
35
36
|
rescue StandardError => e
|
36
37
|
render json: { success: false, error: e.message }
|
37
38
|
end
|
38
39
|
|
39
40
|
def start
|
40
|
-
dispatch =
|
41
|
-
dispatch = @service.start(dispatch)
|
41
|
+
dispatch = @service.start(@dispatch)
|
42
42
|
render json: { success: true, data: serialize(dispatch) }
|
43
43
|
rescue StandardError => e
|
44
44
|
render json: { success: false, error: e.message }
|
45
45
|
end
|
46
46
|
|
47
|
+
def confirm
|
48
|
+
dispatch = @service.confirm(@dispatch)
|
49
|
+
render json: { success: true, data: serialize(dispatch) }
|
50
|
+
rescue StandardError => e
|
51
|
+
render json: { success: false, error: e.message }
|
52
|
+
end
|
53
|
+
|
54
|
+
def search
|
55
|
+
data = @service.search(current_user, params[:status])
|
56
|
+
render json: { success: true, data: serialize(data) }
|
57
|
+
end
|
58
|
+
|
47
59
|
private
|
48
60
|
|
49
61
|
def set_service
|
50
62
|
@service = DispatchService.new
|
51
63
|
end
|
52
64
|
|
65
|
+
def set_dispatch
|
66
|
+
@dispatch = Cats::Core::Dispatch.find(params[:id])
|
67
|
+
end
|
68
|
+
|
53
69
|
def model_params
|
54
70
|
params.require(:payload).permit(:reference_no, :allocation_item_id, :transporter_id, :plate_no, :driver_name,
|
55
|
-
:driver_phone, :quantity, :remark
|
71
|
+
:driver_phone, :quantity, :remark)
|
56
72
|
end
|
57
73
|
end
|
58
74
|
end
|
@@ -1,50 +1,20 @@
|
|
1
1
|
module Cats
|
2
2
|
module Core
|
3
3
|
class LocationsController < ApplicationController
|
4
|
-
|
4
|
+
include Common
|
5
5
|
|
6
6
|
def index
|
7
7
|
locations = Cats::Core::Location.where(location_type: params[:location_type])
|
8
|
-
data
|
9
|
-
render json: { success: true, data: data }
|
10
|
-
end
|
11
|
-
|
12
|
-
def show
|
13
|
-
data = ActiveModelSerializers::SerializableResource.new(@location)
|
14
|
-
render json: { success: true, data: data }
|
8
|
+
render json: { success: true, data: serialize(locations) }
|
15
9
|
end
|
16
10
|
|
17
11
|
def children
|
18
12
|
parent = Cats::Core::Location.find(params[:id])
|
19
|
-
data
|
20
|
-
render json: { success: true, data: data }
|
21
|
-
end
|
22
|
-
|
23
|
-
def create
|
24
|
-
obj = Cats::Core::Location.new(model_params)
|
25
|
-
if obj.save
|
26
|
-
data = ActiveModelSerializers::SerializableResource.new(obj)
|
27
|
-
render json: { success: true, data: data }, status: :created
|
28
|
-
else
|
29
|
-
render json: { success: false, error: obj.errors.full_messages[0] }, status: :unprocessable_entity
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def update
|
34
|
-
if @location.update(model_params)
|
35
|
-
data = ActiveModelSerializers::SerializableResource.new(@location)
|
36
|
-
render json: { success: true, data: data }
|
37
|
-
else
|
38
|
-
render json: { success: false, error: @location.errors.full_messages[0] }, status: :unprocessable_entity
|
39
|
-
end
|
13
|
+
render json: { success: true, data: serialize(parent.children) }
|
40
14
|
end
|
41
15
|
|
42
16
|
private
|
43
17
|
|
44
|
-
def set_location
|
45
|
-
@location = Cats::Core::Location.find(params[:id])
|
46
|
-
end
|
47
|
-
|
48
18
|
def model_params
|
49
19
|
params.require(:payload).permit(:code, :name, :location_type, :description, :parent_id)
|
50
20
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Cats
|
2
|
+
module Core
|
3
|
+
class ReceiptTransactionsController < ApplicationController
|
4
|
+
include Common
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def model_params
|
9
|
+
params.require(:payload).permit(:source_id, :destination_id, :transaction_date, :quantity)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Cats
|
2
|
+
module Core
|
3
|
+
class ReceiptsController < ApplicationController
|
4
|
+
include Common
|
5
|
+
|
6
|
+
def index
|
7
|
+
receipts = Cats::Core::Receipt.where(dispatch_id: params[:id])
|
8
|
+
render json: { success: true, data: serialize(receipts) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def start_stacking
|
12
|
+
receipt = Cats::Core::Receipt.find(params[:id])
|
13
|
+
service = ReceiptService.new
|
14
|
+
result = service.start_stacking(receipt)
|
15
|
+
render json: { success: true, data: serialize(result) }
|
16
|
+
rescue StandardError => e
|
17
|
+
render json: { success: false, error: e.message }
|
18
|
+
end
|
19
|
+
|
20
|
+
def stack
|
21
|
+
receipt = Cats::Core::Receipt.find(params[:id])
|
22
|
+
service = ReceiptService.new
|
23
|
+
result = service.stack(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
|
+
private
|
30
|
+
|
31
|
+
def model_params
|
32
|
+
params.require(:payload).permit(:dispatch_id, :quantity, :commodity_status, :status, :remark, :prepared_by_id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -13,6 +13,7 @@ module Cats
|
|
13
13
|
belongs_to :prepared_by, class_name: 'Cats::Core::User'
|
14
14
|
belongs_to :transporter
|
15
15
|
belongs_to :allocation_item
|
16
|
+
has_many :receipts
|
16
17
|
|
17
18
|
validates :reference_no, :plate_no, :driver_name, :driver_phone, :quantity, :commodity_status, presence: true
|
18
19
|
validates :dispatch_status, presence: true, inclusion: { in: DISPATCH_STATUSES }
|
@@ -3,17 +3,48 @@ module Cats
|
|
3
3
|
class Receipt < ApplicationRecord
|
4
4
|
# Receipt status
|
5
5
|
DRAFT = 'Draft'.freeze
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
CONFIRMED = 'Confirmed'.freeze
|
7
|
+
STACKING = 'Stacking'.freeze
|
8
|
+
STACKED = 'Stacked'.freeze
|
9
|
+
RECEIPT_STATUSES = [DRAFT, CONFIRMED, STACKING, STACKED].freeze
|
9
10
|
|
10
11
|
belongs_to :dispatch
|
11
12
|
belongs_to :prepared_by, class_name: 'Cats::Core::User'
|
13
|
+
has_many :receipt_transactions, foreign_key: :source_id
|
12
14
|
|
13
15
|
validates :quantity, :commodity_status, :status, presence: true
|
14
16
|
validates :quantity, numericality: { greater_than: 0 }
|
15
17
|
validates :status, inclusion: { in: RECEIPT_STATUSES }
|
16
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)
|
37
|
+
diff = dispatch.quantity - received
|
38
|
+
if new_record?
|
39
|
+
return if quantity <= diff
|
40
|
+
|
41
|
+
errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff}).")
|
42
|
+
else
|
43
|
+
return unless diff.negative?
|
44
|
+
|
45
|
+
errors.add(:quantity, "total is higher than dispatch quantity (Max = #{diff.abs}).")
|
46
|
+
end
|
47
|
+
end
|
17
48
|
end
|
18
49
|
end
|
19
50
|
end
|
@@ -12,12 +12,14 @@ 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
|
15
|
+
validate :validate_quantity, unless: :skip_quantity_validation
|
16
16
|
|
17
17
|
def validate_quantity
|
18
18
|
return unless quantity.present? && source.present?
|
19
19
|
|
20
|
-
|
20
|
+
total = self.class.where(source: source).sum(:quantity)
|
21
|
+
diff = source.quantity - total
|
22
|
+
errors.add(:quantity, "total is higher than source quantity (Max = #{diff}).") if quantity > diff
|
21
23
|
end
|
22
24
|
|
23
25
|
def commit
|
@@ -27,10 +29,23 @@ module Cats
|
|
27
29
|
source.save
|
28
30
|
destination.save
|
29
31
|
self.status = COMMITTED
|
30
|
-
save
|
32
|
+
save!
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
36
|
+
def skip_quantity_validation
|
37
|
+
# Quantity validation should be skipped if we are commiting transactions.
|
38
|
+
(
|
39
|
+
instance_of?(Cats::Core::DispatchTransaction) &&
|
40
|
+
destination &&
|
41
|
+
destination.dispatch_status == Cats::Core::Dispatch::STARTED
|
42
|
+
) || (
|
43
|
+
instance_of?(Cats::Core::ReceiptTransaction) &&
|
44
|
+
source &&
|
45
|
+
source.status == Cats::Core::Receipt::STACKING
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
34
49
|
def set_status
|
35
50
|
return unless new_record?
|
36
51
|
|
@@ -40,6 +40,53 @@ module Cats
|
|
40
40
|
dispatch
|
41
41
|
end
|
42
42
|
|
43
|
+
def search(user, status)
|
44
|
+
details = user.details
|
45
|
+
|
46
|
+
unless details['stores'] || details['warehouse'] || details['hub']
|
47
|
+
raise(StandardError, 'User does not have associated location.')
|
48
|
+
end
|
49
|
+
|
50
|
+
if details['stores']
|
51
|
+
warehouse = Cats::Core::Store.find(details['stores'][0]).warehouse
|
52
|
+
hub = warehouse.parent
|
53
|
+
|
54
|
+
dispatches = Cats::Core::Dispatch.joins(:allocation_item)
|
55
|
+
.where(
|
56
|
+
allocation_item: { destination: hub },
|
57
|
+
dispatch_status: status
|
58
|
+
).or(
|
59
|
+
Cats::Core::Dispatch.joins(:allocation_item)
|
60
|
+
.where(
|
61
|
+
allocation_item: { destination: warehouse },
|
62
|
+
dispatch_status: status
|
63
|
+
)
|
64
|
+
)
|
65
|
+
elsif details['warehouse']
|
66
|
+
warehouse = Cats::Core::Location.find(details['warehouse'])
|
67
|
+
hub = warehouse.parent
|
68
|
+
dispatches = Cats::Core::Dispatch.joins(:allocation_item)
|
69
|
+
.where(
|
70
|
+
allocation_item: { destination: hub },
|
71
|
+
dispatch_status: status
|
72
|
+
).or(
|
73
|
+
Cats::Core::Dispatch.joins(:allocation_item)
|
74
|
+
.where(
|
75
|
+
allocation_item: { destination: warehouse },
|
76
|
+
dispatch_status: status
|
77
|
+
)
|
78
|
+
)
|
79
|
+
elsif details['hub']
|
80
|
+
hub = Cats::Core::Location.find(details['hub'])
|
81
|
+
dispatches = Cats::Core::Dispatch.joins(:allocation_item)
|
82
|
+
.where(
|
83
|
+
allocation_item: { destination: hub },
|
84
|
+
dispatch_status: status
|
85
|
+
)
|
86
|
+
end
|
87
|
+
dispatches
|
88
|
+
end
|
89
|
+
|
43
90
|
def approve(dispatch)
|
44
91
|
unless dispatch.dispatch_status == Cats::Core::Dispatch::DRAFT
|
45
92
|
raise(StandardError, 'Dispatch has to be in draft state.')
|
@@ -64,6 +111,26 @@ module Cats
|
|
64
111
|
transactions.each(&:commit)
|
65
112
|
dispatch
|
66
113
|
end
|
114
|
+
|
115
|
+
def confirm(dispatch)
|
116
|
+
total = dispatch.receipts.sum(:quantity)
|
117
|
+
|
118
|
+
unless total == dispatch.quantity
|
119
|
+
raise(
|
120
|
+
StandardError,
|
121
|
+
"There is an amount of #{dispatch.quantity - total} in the dispatch which is unaccounted for."
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
Cats::Core::Dispatch.transaction do
|
126
|
+
dispatch.dispatch_status = Cats::Core::Dispatch::RECEIVED
|
127
|
+
dispatch.receipts.each { |r| r.status = Cats::Core::Receipt::CONFIRMED }
|
128
|
+
dispatch.save
|
129
|
+
dispatch.receipts.each(&:save!)
|
130
|
+
end
|
131
|
+
|
132
|
+
dispatch
|
133
|
+
end
|
67
134
|
end
|
68
135
|
end
|
69
136
|
end
|
@@ -0,0 +1,32 @@
|
|
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 stack(receipt)
|
15
|
+
unless receipt.status == Cats::Core::Receipt::STACKING
|
16
|
+
raise(StandardError, 'Receipt should be in stacking state.')
|
17
|
+
end
|
18
|
+
|
19
|
+
receipt.status = Cats::Core::Receipt::STACKED
|
20
|
+
stacks = receipt.receipt_transactions.map(&:destination)
|
21
|
+
stacks.each { |stack| stack.stack_status = Cats::Core::Stack::ALLOCATED }
|
22
|
+
|
23
|
+
Cats::Core::Receipt.transaction do
|
24
|
+
receipt.receipt_transactions.each(&:commit)
|
25
|
+
stacks.each(&:save!)
|
26
|
+
receipt.save!
|
27
|
+
end
|
28
|
+
receipt
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/config/routes.rb
CHANGED
@@ -56,11 +56,21 @@ Cats::Core::Engine.routes.draw do
|
|
56
56
|
action: :create_receipt_authorization,
|
57
57
|
as: :receipt_authorization_allocation_item
|
58
58
|
|
59
|
+
get '/dispatches/search', controller: :dispatches, action: :search, as: :search_dispatches
|
59
60
|
resources :dispatches, except: %i[index destroy] do
|
60
61
|
member do
|
62
|
+
get 'receipts', controller: :receipts, action: :index
|
61
63
|
post 'approve'
|
62
64
|
post 'start'
|
65
|
+
post 'confirm'
|
63
66
|
end
|
64
67
|
end
|
65
68
|
resources :dispatch_transactions, except: %i[new edit destroy]
|
69
|
+
resources :receipts, except: %i[index new edit destroy] do
|
70
|
+
member do
|
71
|
+
post 'start_stacking'
|
72
|
+
post 'stack'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
resources :receipt_transactions, except: %i[new edit destroy]
|
66
76
|
end
|
data/lib/cats/core/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
FactoryBot.define do
|
2
2
|
factory :receipt, class: 'Cats::Core::Receipt' do
|
3
|
-
dispatch
|
4
|
-
quantity {
|
3
|
+
dispatch factory: :dispatch, dispatch_status: Cats::Core::Dispatch::STARTED
|
4
|
+
quantity { 50 }
|
5
5
|
commodity_status { Cats::Core::Commodity::GOOD }
|
6
6
|
status { Cats::Core::Receipt::DRAFT }
|
7
7
|
remark { FFaker::Name.name }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cats_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henock L.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_model_serializers
|
@@ -225,6 +225,8 @@ files:
|
|
225
225
|
- app/controllers/cats/core/locations_controller.rb
|
226
226
|
- app/controllers/cats/core/menus_controller.rb
|
227
227
|
- app/controllers/cats/core/notifications_controller.rb
|
228
|
+
- app/controllers/cats/core/receipt_transactions_controller.rb
|
229
|
+
- app/controllers/cats/core/receipts_controller.rb
|
228
230
|
- app/controllers/cats/core/roles_controller.rb
|
229
231
|
- app/controllers/cats/core/spaces_controller.rb
|
230
232
|
- app/controllers/cats/core/unit_of_measures_controller.rb
|
@@ -275,11 +277,14 @@ files:
|
|
275
277
|
- app/serializers/cats/core/dispatch_serializer.rb
|
276
278
|
- app/serializers/cats/core/dispatch_transaction_serializer.rb
|
277
279
|
- app/serializers/cats/core/location_serializer.rb
|
280
|
+
- app/serializers/cats/core/receipt_serializer.rb
|
281
|
+
- app/serializers/cats/core/receipt_transaction_serializer.rb
|
278
282
|
- app/serializers/cats/core/role_menu_serializer.rb
|
279
283
|
- app/serializers/cats/core/unit_of_measure_serializer.rb
|
280
284
|
- app/services/cats/core/dispatch_service.rb
|
281
285
|
- app/services/cats/core/menu_service.rb
|
282
286
|
- app/services/cats/core/notification_service.rb
|
287
|
+
- app/services/cats/core/receipt_service.rb
|
283
288
|
- app/services/cats/core/space_service.rb
|
284
289
|
- app/services/cats/core/token_auth_service.rb
|
285
290
|
- config/routes.rb
|