cats_core 1.4.25 → 1.4.28

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: ad828e18f9f084f3c2e0343af564a1f1cc4832e935c9eec068503f4293442b87
4
- data.tar.gz: 8e0520ff2a6df1e2b4dd3f726a60aef02ef45915158c72c73ccbc74a9ae2786d
3
+ metadata.gz: f2cbd9de4f75e95103bf09a853e5d0098e925f6d63c058567657dca04c8e915e
4
+ data.tar.gz: 39dc39668040493ad924ae291ea3f13b34b3644f113558274bbe8f15564d9f1b
5
5
  SHA512:
6
- metadata.gz: cc1d8fc0861a5f8c46734cbbf029608625e8734d31361cf924834769166cc6d429f247b169b299616a5bedcf9dffd0cdc2ad4960e4caa502757a1a98cfd55865
7
- data.tar.gz: '0850a3f89b88aea548765a78f46a8d4cac259642dc3f8c15837ab54c1d5c7911b311b8b55719972fe19312cf614d07042652376556a134ea2e20c8b1f7227fc1'
6
+ metadata.gz: dca66c438930ac24dc216e3ef8f162bae9d0ef54442efaeb2139953379366e9fd93a3fd13ed08cc396f19b6383007f0cee5433ef69cdc863e39a96da92969f8c
7
+ data.tar.gz: 22e99525720f4e34f0bae5fec105ebfaa80f28c73ce0b60c7323536e167bf54ef735969cafcd602124cfa148983207c9364707f62a4d74835d0fad597f85c793
@@ -3,6 +3,8 @@ module Cats
3
3
  class ReceiptAuthorizationsController < ApplicationController
4
4
  include Common
5
5
 
6
+ skip_before_action :authenticate, only: %i[driver_confirm]
7
+
6
8
  def index
7
9
  super do
8
10
  ReceiptAuthorization.where(dispatch_id: params[:id])
@@ -17,11 +19,40 @@ module Cats
17
19
  render json: { success: false, error: e.message }
18
20
  end
19
21
 
22
+ def driver_confirm
23
+ service = AuthorizationService.new
24
+ authorization = service.driver_confirm(params[:id], driver_confirm_params[:pin])
25
+ render json: { success: true, data: serialize(authorization) }
26
+ rescue StandardError => e
27
+ render json: { success: false, error: e.message }
28
+ end
29
+
30
+ def stack
31
+ service = AuthorizationService.new
32
+ authorization = ReceiptAuthorization.find(params[:id])
33
+ authorization = service.stack(authorization.id)
34
+ render json: { success: true, data: serialize(authorization) }
35
+ rescue StandardError => e
36
+ render json: { success: false, error: e.message }
37
+ end
38
+
39
+ def storekeeper_authorizations
40
+ storekeeper = User.find(params[:id])
41
+ status = params[:status]
42
+ stores = storekeeper.stores
43
+ authorizations = ReceiptAuthorization.where(store: stores, status: status)
44
+ render json: { success: true, data: serialize(authorizations) }
45
+ end
46
+
20
47
  private
21
48
 
22
49
  def model_params
23
50
  params.require(:payload).permit(:dispatch_id, :store_id, :quantity, :remark, :status, :authorized_by_id)
24
51
  end
52
+
53
+ def driver_confirm_params
54
+ params.require(:payload).permit(:pin)
55
+ end
25
56
  end
26
57
  end
27
58
  end
@@ -3,7 +3,7 @@ module Cats
3
3
  class RoundPlansController < ApplicationController
4
4
  include Common
5
5
 
6
- before_action :set_service, only: %i[generate remove_items generate_round_needs]
6
+ before_action :set_service, only: %i[approve generate remove_items generate_round_needs]
7
7
 
8
8
  def index
9
9
  super do
@@ -17,8 +17,7 @@ module Cats
17
17
  end
18
18
 
19
19
  def approve
20
- plan = RoundPlan.find(params[:id])
21
- plan.approve
20
+ plan = @service.approve(params[:id])
22
21
  render json: { success: true, data: serialize(plan) }
23
22
  rescue StandardError => e
24
23
  render json: { success: false, error: e.message }, status: :unprocessable_entity
@@ -29,8 +29,8 @@ module Cats
29
29
 
30
30
  def receipt_stacks
31
31
  service = StackService.new
32
- receipt = Receipt.find(params[:id])
33
- stacks = service.receipt_stacks(receipt)
32
+ authorization = ReceiptAuthorization.find(params[:id])
33
+ stacks = service.receipt_stacks(authorization.id)
34
34
  render json: { success: true, data: serialize(stacks) }
35
35
  end
36
36
 
@@ -8,7 +8,28 @@ module Cats
8
8
  validates :beneficiaries, presence: true, numericality: { greater_than: 0 }
9
9
  validates :plan_item_id, uniqueness: { scope: :beneficiary_category_id }
10
10
 
11
+ validates :rounds, presence: true, numericality: { greater_than: 0 }, if: :psnp?
12
+ validates :rounds_served, presence: true, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true, if: :psnp?
13
+ validates :rounds, :rounds_served, absence: true, unless: :psnp?
14
+ validate :validate_rounds
15
+
11
16
  delegate(:name, to: :beneficiary_category, prefix: true)
17
+
18
+ def psnp?
19
+ return false unless plan_item
20
+
21
+ plan_item.plan.program.code == 'PSNP'
22
+ end
23
+
24
+ def validate_rounds
25
+ return unless rounds && rounds_served
26
+
27
+ errors.add(:rounds, 'should not be set for non PSNP plans.') unless psnp?
28
+
29
+ errors.add(:rounds_served, 'should not be set for non PSNP plans.') unless psnp?
30
+
31
+ errors.add(:rounds, 'cannot be lower than rounds served.') if rounds < rounds_served
32
+ end
12
33
  end
13
34
  end
14
35
  end
@@ -7,6 +7,7 @@ module Cats
7
7
 
8
8
  validates :beneficiaries, presence: true, numericality: { greater_than_or_equal_to: 0 }
9
9
  validates :round_plan_item_id, uniqueness: { scope: :beneficiary_category_id }
10
+ validates :beneficiary_plan_item_id, presence: true
10
11
 
11
12
  delegate(:name, to: :beneficiary_category, prefix: true)
12
13
  end
@@ -5,11 +5,10 @@ module Cats
5
5
  APPROVED = 'Approved'.freeze
6
6
  READY_TO_START = 'Ready to Start'.freeze
7
7
  STARTED = 'Started'.freeze
8
- ARRIVED = 'Arrived'.freeze
9
- UNLOADED = 'Unloaded'.freeze
10
8
  RECEIVED = 'Received'.freeze
9
+ STACKED = 'Stacked'.freeze
11
10
 
12
- DISPATCH_STATUSES = [DRAFT, APPROVED, READY_TO_START, STARTED, ARRIVED, UNLOADED, RECEIVED].freeze
11
+ DISPATCH_STATUSES = [DRAFT, APPROVED, READY_TO_START, STARTED, RECEIVED, STACKED].freeze
13
12
 
14
13
  belongs_to :prepared_by, class_name: 'Cats::Core::User'
15
14
  belongs_to :transporter
@@ -73,12 +72,24 @@ module Cats
73
72
  save!
74
73
  end
75
74
 
75
+ def receive
76
+ raise(StandardError, 'Dispatch is not started.') unless dispatch_status == Dispatch::STARTED
77
+
78
+ self.dispatch_status = RECEIVED
79
+ save!
80
+ end
81
+
82
+ def stack
83
+ self.dispatch_status = STACKED
84
+ save!
85
+ end
86
+
76
87
  def self.search_commodity(batch_no)
77
88
  commodity = Commodity.find_by(batch_no: batch_no)
78
89
  dispatches = Dispatch.includes(:dispatch_transactions)
79
90
  .joins(:transporter)
80
91
  .where(
81
- dispatch_status: [APPROVED, STARTED, ARRIVED, UNLOADED]
92
+ dispatch_status: [APPROVED, STARTED]
82
93
  )
83
94
  dispatches.map do |dispatch|
84
95
  {
@@ -18,8 +18,28 @@ module Cats
18
18
  authorization.save!
19
19
  raise(StandardError, 'Pin has expired.')
20
20
  end
21
+
21
22
  authorization.driver_confirmed = true
22
23
  authorization.save!
24
+ statuses = authorization.dispatch.receipt_authorizations.map(&:driver_confirmed).uniq
25
+ authorization.dispatch.receive if statuses.length == 1 && statuses[0]
26
+
27
+ authorization
28
+ end
29
+
30
+ def stack(authorization_id)
31
+ authorization = ReceiptAuthorization.find(authorization_id)
32
+ unless authorization.dispatch.dispatch_status == Dispatch::RECEIVED
33
+ raise(StandardError, 'Dispatch is not received.')
34
+ end
35
+
36
+ total = authorization.transactions.sum(:quantity)
37
+ if total != authorization.received_quantity
38
+ raise(StandardError, 'Received quantity is not the same as quantity to be stacked.')
39
+ end
40
+
41
+ authorization.transactions.each(&:commit)
42
+ authorization.dispatch.stack
23
43
  authorization
24
44
  end
25
45
  end
@@ -79,7 +79,8 @@ module Cats
79
79
  round_plan_item_id: item[0],
80
80
  beneficiary_category_id: ben_plan_item.beneficiary_category_id,
81
81
  planned_beneficiaries: ben_plan_item.beneficiaries,
82
- beneficiaries: ben_plan_item.beneficiaries
82
+ beneficiaries: ben_plan_item.beneficiaries,
83
+ beneficiary_plan_item_id: ben_plan_item.id
83
84
  }
84
85
  end
85
86
  Cats::Core::BeneficiaryRoundPlanItem.insert_all!(ben_round_plan_items, record_timestamps: true)
@@ -103,6 +104,41 @@ module Cats
103
104
  Cats::Core::RoundPlanItem.delete_by(id: ids)
104
105
  plan
105
106
  end
107
+
108
+ def approve(plan_id)
109
+ plan = RoundPlan.find(plan_id)
110
+ if plan.plan.program.code == 'PSNP'
111
+ rounds = plan.rounds.count
112
+ item_ids = plan.beneficiary_round_plan_items.pluck('beneficiary_plan_item_id').flatten
113
+ plan_items = BeneficiaryPlanItem.where(id: item_ids)
114
+ invalid = plan_items.select { |pi| pi.rounds - (pi.rounds_served || 0) < rounds }
115
+ error = 'There are plan items whose served rounds may exceed the allowed number of rounds.'
116
+ raise(StandardError, error) if invalid.count.positive?
117
+
118
+ items = plan_items.each_with_object([]) do |plan_item, res|
119
+ rounds_served = plan_item.rounds_served || 0
120
+ res << "(#{plan_item.id}, #{rounds + rounds_served})"
121
+ end
122
+ values = items.join(',')
123
+ sql = <<-SQL
124
+ UPDATE cats_core_beneficiary_plan_items AS bpi
125
+ SET
126
+ rounds_served = l.rounds_served
127
+ FROM (
128
+ VALUES
129
+ #{values}
130
+ ) AS l(id, rounds_served)
131
+ WHERE l.id = bpi.id
132
+ SQL
133
+ ActiveRecord::Base.transaction do
134
+ ActiveRecord::Base.connection.execute(sql)
135
+ plan.approve
136
+ end
137
+ else
138
+ plan.approve
139
+ end
140
+ plan
141
+ end
106
142
  end
107
143
  end
108
144
  end
@@ -34,13 +34,10 @@ module Cats
34
34
  end
35
35
  end
36
36
 
37
- def receipt_stacks(receipt)
38
- location = receipt.dispatch.dispatch_plan_item.destination
39
- warehouses = location.children
40
- stores = Store.where(warehouse: warehouses)
41
-
42
- commodity = receipt.dispatch.dispatch_plan_item.commodity
43
- Stack.where(commodity: commodity, store: stores)
37
+ def receipt_stacks(authorization_id)
38
+ authorization = ReceiptAuthorization.find(authorization_id)
39
+ commodity = authorization.dispatch.dispatch_plan_item.commodity
40
+ Stack.where(commodity: commodity, store_id: authorization.store_id)
44
41
  end
45
42
 
46
43
  def dispatch_stacks(dispatch)
data/config/routes.rb CHANGED
@@ -119,17 +119,26 @@ Cats::Core::Engine.routes.draw do
119
119
  end
120
120
 
121
121
  get(
122
- '/storekeeper/:id/authorizations',
122
+ '/storekeeper/:id/dispatch_authorizations',
123
123
  controller: :dispatch_authorizations,
124
124
  action: :storekeeper_authorizations,
125
- as: :storekeeper_authorizations
125
+ as: :storekeeper_dispatch_authorizations
126
+ )
127
+ get(
128
+ '/storekeeper/:id/receipt_authorizations',
129
+ controller: :receipt_authorizations,
130
+ action: :storekeeper_authorizations,
131
+ as: :storekeeper_receipt_authorizations
126
132
  )
127
133
  resources :receipt_authorizations, except: %i[index destroy] do
128
134
  member do
129
135
  get 'transactions', controller: :receipt_transactions, action: :index
130
136
  get 'lost', controller: :lost_commodities, action: :index
131
137
  get 'receipts', controller: :receipts, action: :index
132
- post 'confirm', controller: :receipt_authorizations, action: :confirm
138
+ get 'stacks', controller: :stacks, action: :receipt_stacks
139
+ post 'confirm'
140
+ post 'driver_confirm'
141
+ post 'stack'
133
142
  end
134
143
  end
135
144
 
@@ -11,6 +11,9 @@ class CreateCatsCoreBeneficiaryPlanItems < ActiveRecord::Migration[7.0]
11
11
  foreign_key: { to_table: :cats_core_beneficiary_categories }
12
12
  t.integer :beneficiaries, null: false
13
13
 
14
+ t.integer :rounds
15
+ t.integer :rounds_served
16
+
14
17
  t.timestamps
15
18
  end
16
19
  add_index(
@@ -11,6 +11,7 @@ class CreateCatsCoreBeneficiaryRoundPlanItems < ActiveRecord::Migration[7.0]
11
11
  foreign_key: { to_table: :cats_core_beneficiary_categories }
12
12
  t.integer :planned_beneficiaries, null: false
13
13
  t.integer :beneficiaries, null: false
14
+ t.integer :beneficiary_plan_item_id, null: false
14
15
 
15
16
  t.timestamps
16
17
  end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.4.25'.freeze
3
+ VERSION = '1.4.28'.freeze
4
4
  end
5
5
  end
@@ -3,5 +3,7 @@ FactoryBot.define do
3
3
  plan_item
4
4
  beneficiary_category
5
5
  beneficiaries { 100 }
6
+ rounds { nil }
7
+ rounds_served { nil }
6
8
  end
7
9
  end
@@ -4,5 +4,6 @@ FactoryBot.define do
4
4
  beneficiary_category
5
5
  planned_beneficiaries { 100 }
6
6
  beneficiaries { 50 }
7
+ beneficiary_plan_item_id { 1 }
7
8
  end
8
9
  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.4.25
4
+ version: 1.4.28
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-29 00:00:00.000000000 Z
11
+ date: 2022-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers