cats_core 1.3.38 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef9922d4ff8da58afc9045f7390132b817ce7610941fda378ed3adc061dcb68b
4
- data.tar.gz: 2a2005f25ab47f22fd012ab301b5317d41b97ff159f8421826bacf7a4dcab5b4
3
+ metadata.gz: b1563c8d3250c1cda415de5081c46f445a82f593c727be676c3f9a7041f28fa7
4
+ data.tar.gz: b614991a9f6a2a4046c7c4e54af584d59a33478c62b5a0c6dee77ddbbdad2e6b
5
5
  SHA512:
6
- metadata.gz: b32b1b7c224845b8c48281da4815d5f4125c87cf954b427ba06ead6c3dbc3c01afbc112552950ef016693d05a7daa565086d54000dd8d496c6526ce7f307b4a5
7
- data.tar.gz: cfb9210cd040ca426977ed23c74a3f039ad01fd0d8b36b1e2e9f58c751ffd2b9df2695ac63755ffb7016e44d5c2cdbfc5c5c7939ba136930f2a7734618974ef3
6
+ metadata.gz: ff00ffac606dfa2136aaaed05a6825238b5ae38f737f4a3790db2b94193f0108b6d394097c0828339af8aab226acf871d65ddefa68c54ad929a47e7069d9d49b
7
+ data.tar.gz: fd1b163787f8fc21ba49f79929f027143f1a45d74425518536d9adc4369eb33ea6ab9b96a30fb34b7cba6e9f8ba11e2f9f191acd83200debf91589cc9be490e3
@@ -8,10 +8,16 @@ module Cats
8
8
  render json: { success: true, data: serialize(items) }
9
9
  end
10
10
 
11
+ def filter
12
+ query = Cats::Core::DispatchPlanItem.ransack(params[:q])
13
+ render json: { success: true, data: serialize(query.result) }
14
+ end
15
+
11
16
  private
12
17
 
13
18
  def model_params
14
- params.require(:payload).permit(:dispatch_plan_id, :source_id, :destination_id, :quantity, :commodity_status)
19
+ params.require(:payload).permit(:dispatch_plan_id, :source_id, :destination_id, :quantity, :commodity_status,
20
+ :status)
15
21
  end
16
22
  end
17
23
  end
@@ -22,8 +22,9 @@ module Cats
22
22
  end
23
23
 
24
24
  def approve
25
+ service = DispatchPlanService.new
25
26
  plan = Cats::Core::DispatchPlan.find(params[:id])
26
- plan.approve
27
+ plan = service.approve(plan)
27
28
  render json: { success: true, data: serialize(plan) }
28
29
  rescue StandardError => e
29
30
  render json: { success: false, error: e.message }
@@ -8,6 +8,26 @@ module Cats
8
8
  render json: { success: true, data: serialize(transactions) }
9
9
  end
10
10
 
11
+ # This end-point is used to create upstream dispatch transactions.
12
+ # We need a specific method like this because for upstream the source
13
+ # stack is a dummy one and we need to use that without waiting for the
14
+ # user to give us a source.
15
+ def create_allocation
16
+ dispatch = Dispatch.find(model_params[:dispatch_id])
17
+ commodity = dispatch.dispatch_plan_item.dispatch_plan.commodity
18
+ transaction = DispatchTransaction.new(model_params)
19
+
20
+ # Fetch supplier stack by commodity
21
+ stack = Stack.joins(:store).find_by(commodity: commodity, store: { code: 'SUP-STORE' })
22
+ transaction.source = stack
23
+
24
+ if transaction.save
25
+ render json: { success: true, data: serialize(transaction) }, status: :created
26
+ else
27
+ render json: { success: false, error: transaction.errors.full_messages[0] }, status: :unprocessable_entity
28
+ end
29
+ end
30
+
11
31
  private
12
32
 
13
33
  def model_params
@@ -9,26 +9,16 @@ module Cats
9
9
  end
10
10
 
11
11
  def create
12
- p = model_params
13
- receipt = Cats::Core::Receipt.find_by(
14
- dispatch_id: p[:dispatch_id],
15
- commodity_status: p[:commodity_status]
16
- )
17
- if receipt
18
- receipt.quantity += p[:quantity]
19
- if receipt.save
20
- render json: { success: true, data: serialize(receipt) }
21
- else
22
- render json: { success: false, error: receipt.errors.full_messages[0] }, status: :unprocessable_entity
23
- end
12
+ service = ReceiptService.new
13
+ receipt = service.init(model_params)
14
+
15
+ if receipt.save
16
+ render json: { success: true, data: serialize(receipt) }
24
17
  else
25
- obj = Cats::Core::Receipt.new(model_params)
26
- if obj.save
27
- render json: { success: true, data: serialize(obj) }, status: :created
28
- else
29
- render json: { success: false, error: obj.errors.full_messages[0] }, status: :unprocessable_entity
30
- end
18
+ render json: { success: false, error: receipt.errors.full_messages[0] }, status: :unprocessable_entity
31
19
  end
20
+ rescue StandardError => e
21
+ render json: { success: false, error: e.message }
32
22
  end
33
23
 
34
24
  def start_stacking
@@ -0,0 +1,37 @@
1
+ module Cats
2
+ module Core
3
+ class StacksController < ApplicationController
4
+ include Common
5
+
6
+ def index
7
+ stacks = Stack.where(store_id: params[:id])
8
+ render json: { success: true, data: serialize(stacks) }
9
+ end
10
+
11
+ def filter
12
+ query = Stack.where(store_id: params[:id]).ransack(params[:q])
13
+ render json: { success: true, data: serialize(query.result) }
14
+ end
15
+
16
+ def commodity_for_location
17
+ service = StackService.new
18
+ commodities = service.commodity_for_location(current_user)
19
+ render json: { success: true, data: serialize(commodities) }
20
+ end
21
+
22
+ def receipt_stacks
23
+ service = StackService.new
24
+ receipt = Receipt.find(params[:id])
25
+ stacks = service.receipt_stacks(receipt)
26
+ render json: { success: true, data: serialize(stacks) }
27
+ end
28
+
29
+ private
30
+
31
+ def model_params
32
+ params.require(:payload).permit(:code, :length, :width, :height, :start_x, :start_y, :commodity_id, :store_id,
33
+ :commodity_status, :stack_status, :quantity)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,6 +3,11 @@ module Cats
3
3
  class TransportersController < ApplicationController
4
4
  include Cats::Core::Common
5
5
 
6
+ def filter
7
+ query = Cats::Core::Transporter.ransack(params[:q])
8
+ render json: { success: true, data: serialize(query.result) }
9
+ end
10
+
6
11
  private
7
12
 
8
13
  def model_params
@@ -71,6 +71,7 @@ module Cats
71
71
  return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
72
72
 
73
73
  stacks = store.stacks.where(stack_status: [RESERVED, ALLOCATED]).where.not(id: id)
74
+
74
75
  stacks.each do |s|
75
76
  errors.add(:base, message: "#{code} overlaps with #{s.code}") if overlaps?(self, s)
76
77
  end
@@ -12,15 +12,17 @@ module Cats
12
12
 
13
13
  def message
14
14
  allocation_item = params[:allocation_item]
15
- commodity = allocation_item.allocation.commodity.name
15
+ commodity = allocation_item.dispatch_plan.commodity.name
16
+ source = allocation_item.source.name
17
+ destination = allocation_item.destination.name
16
18
  title = "Allocation Notification - #{commodity}"
17
19
  date = Date.today
18
20
  body = <<~BODY
19
21
  Commodity with the following specification has been allocated to you:
20
- Batch No. = #{allocation_item.allocation.commodity.batch_no}
22
+ Batch No. = #{allocation_item.dispatch_plan.commodity.batch_no}
21
23
  Commodity = #{commodity}
22
24
  Quantity = #{allocation_item.quantity}
23
- The commodity is expected to be delivered from #{allocation_item.from} to #{allocation_item.to}
25
+ The commodity is expected to be delivered from #{source} to #{destination}
24
26
  BODY
25
27
  { title: title, date: date, body: body }
26
28
  end
@@ -2,7 +2,8 @@ module Cats
2
2
  module Core
3
3
  class DispatchPlanItemSerializer < ActiveModel::Serializer
4
4
  attributes :id, :dispatch_plan_id, :plan_reference_no, :source_id, :source_name, :destination_id,
5
- :destination_name, :quantity, :source_location_type, :destination_location_type, :commodity_status
5
+ :destination_name, :quantity, :source_location_type, :destination_location_type, :commodity_status,
6
+ :status
6
7
  end
7
8
  end
8
9
  end
@@ -1,7 +1,8 @@
1
1
  module Cats
2
2
  module Core
3
3
  class MonthlyPlanSerializer < ActiveModel::Serializer
4
- attributes :id, :reference_no, :status, :plan_id, :plan_reference_no, :region_id, :region_name, :month, :no_of_days
4
+ attributes :id, :reference_no, :status, :plan_id, :plan_reference_no, :region_id, :region_name, :month,
5
+ :no_of_days
5
6
  end
6
7
  end
7
8
  end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class StackSerializer < ActiveModel::Serializer
4
+ attributes :id, :code, :length, :width, :height, :start_x, :start_y, :commodity_id, :store_id, :commodity_status,
5
+ :stack_status, :quantity, :commodity_batch_no
6
+ end
7
+ end
8
+ end
@@ -4,8 +4,28 @@ module Cats
4
4
  def approve(plan)
5
5
  plan.approve
6
6
 
7
- plan.dispatchable.allocate if plan.dispatchable_type == RhnRequest.name
8
- # send_notification(plan)
7
+ if plan.upstream
8
+ # Create source hub authorizations for each item and
9
+ # put them in a `Source Authorized` state
10
+ store = Store.find_by(code: 'SUP-STORE')
11
+ keeper = User.find_by(first_name: 'SUP-Storekeeper')
12
+ authorizations = []
13
+ plan.dispatch_plan_items.each do |item|
14
+ authorizations << {
15
+ dispatch_plan_item_id: item.id,
16
+ store_id: store.id,
17
+ quantity: item.quantity,
18
+ authorization_type: HubAuthorization::SOURCE,
19
+ authorized_by_id: keeper.id,
20
+ created_at: Date.today,
21
+ updated_at: Date.today
22
+ }
23
+ end
24
+ HubAuthorization.insert_all(authorizations)
25
+ plan.dispatch_plan_items.update_all(status: DispatchPlanItem::SOURCE_AUTHORIZED)
26
+ plan.dispatchable.allocate
27
+ end
28
+ send_notification(plan)
9
29
  plan
10
30
  end
11
31
 
@@ -17,6 +37,28 @@ module Cats
17
37
  rescue ActiveRecord::RecordInvalid
18
38
  raise(StandardError, plan.errors.full_messages[0])
19
39
  end
40
+
41
+ def send_notification(allocation)
42
+ notification_rule = Cats::Core::NotificationRule.find_by(code: 'allocation')
43
+ raise(StandardError, 'Notification rule not found for allocation notification.') unless notification_rule
44
+
45
+ users = Cats::Core::User.joins(:roles).where(cats_core_roles: { name: notification_rule.roles })
46
+ allocation.dispatch_plan_items.each do |item|
47
+ location_id = item.destination_id
48
+
49
+ recipients = users.map do |user|
50
+ details = user.details
51
+ if (details.key?('warehouse') && details['warehouse'] == location_id) ||
52
+ (details.key?('hub') && details['hub'] == location_id)
53
+ user
54
+ end
55
+ end.compact
56
+ unless recipients.empty?
57
+ notification = Cats::Core::AllocationNotification.with(allocation_item: item)
58
+ notification.deliver(recipients)
59
+ end
60
+ end
61
+ end
20
62
  end
21
63
  end
22
64
  end
@@ -21,6 +21,28 @@ module Cats
21
21
  receipt.save!
22
22
  receipt
23
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
24
46
  end
25
47
  end
26
48
  end
@@ -0,0 +1,59 @@
1
+ module Cats
2
+ module Core
3
+ class StackService
4
+ def commodity_for_location(user)
5
+ details = user.details
6
+
7
+ key_available = details.keys.any? { |key| %w[stores warehouse hub].include?(key) }
8
+ raise(StandardError, 'User does not have associated location.') unless key_available
9
+
10
+ if details['hub']
11
+ hub = Cats::Core::Location.find(details['hub'])
12
+ allocation_items =
13
+ Cats::Core::AllocationItem
14
+ .joins(allocation: :commodity)
15
+ .where(destination: hub, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
16
+ else
17
+ if details['stores']
18
+ warehouse = Cats::Core::Store.find(details['stores'][0]).warehouse
19
+ hub = warehouse.parent
20
+ elsif details['warehouse']
21
+ warehouse = Cats::Core::Location.find(details['warehouse'])
22
+ hub = warehouse.parent
23
+ end
24
+ allocation_items =
25
+ Cats::Core::AllocationItem
26
+ .joins(allocation: :commodity)
27
+ .where(destination: hub, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
28
+ .or(
29
+ Cats::Core::AllocationItem
30
+ .joins(allocation: :commodity)
31
+ .where(destination: warehouse, allocation: { allocation_status: Cats::Core::Allocation::APPROVED })
32
+ )
33
+ end
34
+
35
+ allocation_items.map do |item|
36
+ {
37
+ reference_no: item.allocation.reference_no,
38
+ source: item.allocation.source.name,
39
+ destination: item.destination.name,
40
+ quantity: item.quantity,
41
+ batch_no: item.allocation.commodity.batch_no,
42
+ commodity_id: item.allocation.commodity_id,
43
+ commodity_name: item.allocation.commodity.name,
44
+ unit: item.allocation.commodity.unit_of_measure.abbreviation
45
+ }
46
+ end
47
+ end
48
+
49
+ def receipt_stacks(receipt)
50
+ location = receipt.dispatch.dispatch_plan_item.destination
51
+ warehouses = location.children
52
+ stores = Cats::Core::Store.where(warehouse: warehouses)
53
+
54
+ commodity = receipt.dispatch.dispatch_plan_item.dispatch_plan.commodity
55
+ Cats::Core::Stack.where(commodity: commodity, store: stores)
56
+ end
57
+ end
58
+ end
59
+ end
data/config/routes.rb CHANGED
@@ -73,6 +73,8 @@ Cats::Core::Engine.routes.draw do
73
73
  end
74
74
  resources :currencies, except: %i[destroy]
75
75
  resources :unit_of_measures, except: %i[destroy]
76
+
77
+ post '/transporters/filter', controller: :transporters, action: :filter
76
78
  resources :transporters, except: %i[destroy]
77
79
 
78
80
  post '/routes/filter', controller: :routes, action: :filter
@@ -88,6 +90,7 @@ Cats::Core::Engine.routes.draw do
88
90
 
89
91
  resources :dispatch_plan_items, except: %i[index destroy]
90
92
 
93
+ post '/dispatch_plan_items/filter', controller: :dispatch_plan_items, action: :filter
91
94
  get '/dispatch_plan_items/:id/dispatches', controller: :dispatches, action: :index, as: :dispatches_plan_item
92
95
 
93
96
  get '/dispatches/search', controller: :dispatches, action: :search, as: :search_dispatches
@@ -102,6 +105,13 @@ Cats::Core::Engine.routes.draw do
102
105
  post 'confirm'
103
106
  end
104
107
  end
108
+
109
+ post(
110
+ 'dispatch_transactions/allocation',
111
+ controller: :dispatch_transactions,
112
+ action: :create_allocation,
113
+ as: :allocation_transaction
114
+ )
105
115
  resources :dispatch_transactions, except: %i[index new edit destroy]
106
116
  resources :receipts, except: %i[index new edit destroy] do
107
117
  member do
@@ -122,4 +132,10 @@ Cats::Core::Engine.routes.draw do
122
132
  post 'approve'
123
133
  end
124
134
  end
135
+
136
+ get '/stores/:id/stacks', controller: :stacks, action: :index, as: :stacks_store
137
+ post '/stores/:id/stacks', controller: :stacks, action: :filter
138
+ get '/stacks/commodity_for_location', controller: :stacks, action: :commodity_for_location, as: :commodity_for_location
139
+ get '/receipts/:id/stacks', controller: :stacks, action: :receipt_stacks, as: :receipt_stacks
140
+ resources :stacks, only: %i[show index create update]
125
141
  end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.3.38'.freeze
3
+ VERSION = '1.4.0'.freeze
4
4
  end
5
5
  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.3.38
4
+ version: 1.4.0
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-03-07 00:00:00.000000000 Z
11
+ date: 2022-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -249,6 +249,7 @@ files:
249
249
  - app/controllers/cats/core/roles_controller.rb
250
250
  - app/controllers/cats/core/routes_controller.rb
251
251
  - app/controllers/cats/core/spaces_controller.rb
252
+ - app/controllers/cats/core/stacks_controller.rb
252
253
  - app/controllers/cats/core/transporters_controller.rb
253
254
  - app/controllers/cats/core/unit_of_measures_controller.rb
254
255
  - app/controllers/cats/core/users_controller.rb
@@ -331,6 +332,7 @@ files:
331
332
  - app/serializers/cats/core/role_menu_serializer.rb
332
333
  - app/serializers/cats/core/role_serializer.rb
333
334
  - app/serializers/cats/core/route_serializer.rb
335
+ - app/serializers/cats/core/stack_serializer.rb
334
336
  - app/serializers/cats/core/transporter_serializer.rb
335
337
  - app/serializers/cats/core/unit_of_measure_serializer.rb
336
338
  - app/serializers/cats/core/user_serializer.rb
@@ -341,6 +343,7 @@ files:
341
343
  - app/services/cats/core/notification_service.rb
342
344
  - app/services/cats/core/receipt_service.rb
343
345
  - app/services/cats/core/space_service.rb
346
+ - app/services/cats/core/stack_service.rb
344
347
  - app/services/cats/core/token_auth_service.rb
345
348
  - config/routes.rb
346
349
  - db/migrate/20210715114238_create_cats_core_application_modules.rb