cats_core 1.3.39 → 1.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16a8d6fe8ce3bada8611add7e2b8669608072f40609445223966652619c16844
4
- data.tar.gz: 291b4d451c1027375e203245717680ae5419306ef01707c40abdb66d3ec880c0
3
+ metadata.gz: affaa1b4a210fc6234d49f105efd3a0e197b8d9e6c2ad7e00ae2dbefd23cfe31
4
+ data.tar.gz: 608f4585d6c34f68a62a7bcfc187d495ac21a0fa528f905bcda7044801ab4c1f
5
5
  SHA512:
6
- metadata.gz: eab2450cce0646b1914dc800938af63f96eea3439c8377a35c2eaef56574d970dcaded1c250b9bf1d59be929b7a428fce9a790f3956adeab6461f0ec94074ffd
7
- data.tar.gz: 663adc2701e5fc8a374eb037b66fba8116049f2c49b5d7a7d09640de12b90d55150387db85113f5a6a047792f24a098a83918ab48a0898e32f6a782cb314e1ba
6
+ metadata.gz: 68b8a081e2ee0e3ad7edb1876b76a1cb2d2c0b8836de2af209acb01de699d004c0fd2f74c0357a27857fd287f249f3338950debe88c15ee2b742cfe72f4d62cd
7
+ data.tar.gz: 4b5c89c2de473ec47255835b1862ddaa42f44b4a99d5410bd4c63515b73bef77d1ef92328a75358a00dd29992afa2bcf2c582cbde84a5d63de2833d10944aada
@@ -16,7 +16,8 @@ module Cats
16
16
  private
17
17
 
18
18
  def model_params
19
- 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)
20
21
  end
21
22
  end
22
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 }
@@ -19,6 +19,13 @@ module Cats
19
19
  render json: { success: true, data: serialize(commodities) }
20
20
  end
21
21
 
22
+ def dispatch_stacks
23
+ service = StackService.new
24
+ dispatch = Dispatch.find(params[:id])
25
+ stacks = service.dispatch_stacks(dispatch)
26
+ render json: { success: true, data: serialize(stacks) }
27
+ end
28
+
22
29
  def receipt_stacks
23
30
  service = StackService.new
24
31
  receipt = Receipt.find(params[:id])
@@ -14,6 +14,7 @@ module Cats
14
14
 
15
15
  validates :reference_no, presence: true, uniqueness: true
16
16
  validates :status, inclusion: { in: STATUSES }
17
+ validate :validate_dispatchable, on: :create
17
18
 
18
19
  delegate(:batch_no, :name, :quantity, to: :commodity, prefix: true)
19
20
  delegate(:request_reference, to: :dispatchable, allow_nil: true)
@@ -23,14 +24,40 @@ module Cats
23
24
  plan.upstream = !plan.dispatchable.nil? && plan.dispatchable_type == RhnRequest.name
24
25
  end
25
26
 
27
+ after_save do |plan|
28
+ plan.dispatchable&.reserve if status == DRAFT
29
+ end
30
+
31
+ def validate_dispatchable
32
+ # Check if dispatchable is already reserved and raise error if so.
33
+ return unless dispatchable
34
+
35
+ return if dispatchable.status == RhnRequest::APPROVED
36
+
37
+ errors.add(:dispatchable, 'is already reserved.') if id.nil?
38
+ end
39
+
26
40
  def approve
27
41
  raise(StandardError, 'Dispatch plan already approved.') if status == APPROVED
28
42
 
29
43
  raise(StandardError, 'Dispatch plan is empty.') if dispatch_plan_items.count.zero?
30
44
 
45
+ # Raise error if the total dispatch plan quantity is not equal to the
46
+ # dispatchable quantity
47
+ if dispatchable && dispatchable.quantity != quantity
48
+ raise(StandardError, 'Requested quantity and plan quantity do not match.')
49
+ end
50
+
31
51
  self.status = APPROVED
52
+ dispatchable&.allocate
32
53
  save!
33
54
  end
55
+
56
+ # A method which returns the total quantity in the dispatch plan
57
+ # based on dispatch plan item quantities.
58
+ def quantity
59
+ dispatch_plan_items.sum(:quantity)
60
+ end
34
61
  end
35
62
  end
36
63
  end
@@ -18,6 +18,7 @@ module Cats
18
18
  has_many :plan_item_details, through: :plan_items
19
19
 
20
20
  validates :reference_no, :year, :status, presence: true
21
+ validates :total_days, :rounds, presence: true, numericality: { greater_than: 0 }
21
22
  validates :season, presence: true, inclusion: { in: SEASONS }
22
23
  validates :reference_no, uniqueness: true
23
24
  validates :status, inclusion: { in: STATUSES }
@@ -5,8 +5,9 @@ module Cats
5
5
 
6
6
  DRAFT = 'Draft'.freeze
7
7
  APPROVED = 'Approved'.freeze
8
+ RESERVED = 'Reserved'.freeze
8
9
  ALLOCATED = 'Allocated'.freeze
9
- STATUSES = [DRAFT, APPROVED, ALLOCATED].freeze
10
+ STATUSES = [DRAFT, APPROVED, RESERVED, ALLOCATED].freeze
10
11
 
11
12
  belongs_to :commodity
12
13
 
@@ -43,11 +44,22 @@ module Cats
43
44
  end
44
45
 
45
46
  def approve
47
+ raise(StandardError, 'Request is not in draft state.') unless status == DRAFT
48
+
46
49
  self.status = APPROVED
47
50
  save!
48
51
  end
49
52
 
53
+ def reserve
54
+ raise(StandardError, 'Request is not approved.') unless status == APPROVED
55
+
56
+ self.status = RESERVED
57
+ save!
58
+ end
59
+
50
60
  def allocate
61
+ raise(StandardError, 'Request is not reserved.') unless status == RESERVED
62
+
51
63
  self.status = ALLOCATED
52
64
  save!
53
65
  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
@@ -23,9 +23,8 @@ module Cats
23
23
  end
24
24
  HubAuthorization.insert_all(authorizations)
25
25
  plan.dispatch_plan_items.update_all(status: DispatchPlanItem::SOURCE_AUTHORIZED)
26
- plan.dispatchable.allocate
27
26
  end
28
- # send_notification(plan)
27
+ send_notification(plan)
29
28
  plan
30
29
  end
31
30
 
@@ -33,10 +32,33 @@ module Cats
33
32
  plan = Cats::Core::DispatchPlan.new(params)
34
33
  plan.prepared_by = user
35
34
  plan.save!
35
+
36
36
  plan
37
37
  rescue ActiveRecord::RecordInvalid
38
38
  raise(StandardError, plan.errors.full_messages[0])
39
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
40
62
  end
41
63
  end
42
64
  end
@@ -1,7 +1,7 @@
1
1
  module Cats
2
2
  module Core
3
3
  class DispatchService
4
- def search(user, status)
4
+ def search(user, status, authorized: false)
5
5
  details = user.details
6
6
 
7
7
  unless details['stores'] || details['warehouse'] || details['hub']
@@ -10,18 +10,25 @@ module Cats
10
10
 
11
11
  # Get user's hub
12
12
  hub = if details['stores']
13
- Cats::Core::Store.find(details['stores'][0]).warehouse.parent
13
+ Store.find(details['stores'][0]).warehouse.parent
14
14
  elsif details['warehouse']
15
- Cats::Core::Location.find(details['warehouse']).parent
15
+ Location.find(details['warehouse']).parent
16
16
  else
17
- Cats::Core::Location.find(details['hub'])
17
+ Location.find(details['hub'])
18
18
  end
19
19
 
20
- Cats::Core::Dispatch.joins(:dispatch_plan_item)
21
- .where(
22
- dispatch_plan_item: { destination: hub },
23
- dispatch_status: status
24
- )
20
+ if authorized
21
+ return Dispatch.joins(:dispatch_plan_item)
22
+ .where(
23
+ dispatch_plan_item: { destination: hub, status: DispatchPlanItem::AUTHORIZED },
24
+ dispatch_status: status
25
+ )
26
+ end
27
+ Dispatch.joins(:dispatch_plan_item)
28
+ .where(
29
+ dispatch_plan_item: { destination: hub },
30
+ dispatch_status: status
31
+ )
25
32
  end
26
33
 
27
34
  def start(dispatch)
@@ -49,10 +49,19 @@ module Cats
49
49
  def receipt_stacks(receipt)
50
50
  location = receipt.dispatch.dispatch_plan_item.destination
51
51
  warehouses = location.children
52
- stores = Cats::Core::Store.where(warehouse: warehouses)
52
+ stores = Store.where(warehouse: warehouses)
53
53
 
54
54
  commodity = receipt.dispatch.dispatch_plan_item.dispatch_plan.commodity
55
- Cats::Core::Stack.where(commodity: commodity, store: stores)
55
+ Stack.where(commodity: commodity, store: stores)
56
+ end
57
+
58
+ def dispatch_stacks(dispatch)
59
+ location = dispatch.dispatch_plan_item.source
60
+ warehouses = location.children
61
+ stores = Store.where(warehouse: warehouses)
62
+
63
+ commodity = dispatch.dispatch_plan_item.dispatch_plan.commodity
64
+ Stack.where(commodity: commodity, store: stores)
56
65
  end
57
66
  end
58
67
  end
data/config/routes.rb CHANGED
@@ -137,5 +137,6 @@ Cats::Core::Engine.routes.draw do
137
137
  post '/stores/:id/stacks', controller: :stacks, action: :filter
138
138
  get '/stacks/commodity_for_location', controller: :stacks, action: :commodity_for_location, as: :commodity_for_location
139
139
  get '/receipts/:id/stacks', controller: :stacks, action: :receipt_stacks, as: :receipt_stacks
140
+ get '/dispatches/:id/stacks', controller: :stacks, action: :dispatch_stacks, as: :dispatch_stacks
140
141
  resources :stacks, only: %i[show index create update]
141
142
  end
@@ -5,6 +5,9 @@ class CreateCatsCorePlans < ActiveRecord::Migration[6.1]
5
5
  t.integer :year, null: false
6
6
  t.string :season, null: false
7
7
  t.string :status, null: false, default: 'Draft'
8
+ t.date :start_date
9
+ t.integer :total_days, null: false, default: 180
10
+ t.integer :rounds, null: false
8
11
 
9
12
  t.references :program,
10
13
  null: false,
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.3.39'.freeze
3
+ VERSION = '1.4.1'.freeze
4
4
  end
5
5
  end
@@ -3,6 +3,8 @@ FactoryBot.define do
3
3
  reference_no { FFaker::Name.name }
4
4
  year { 1 }
5
5
  season { Cats::Core::Plan::BELG }
6
+ total_days { 180 }
7
+ rounds { 6 }
6
8
  status { Cats::Core::Plan::DRAFT }
7
9
  program
8
10
  ration
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.39
4
+ version: 1.4.1
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-12 00:00:00.000000000 Z
11
+ date: 2022-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers