cats_core 1.4.45 → 1.4.49

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: 710ffdc5b10d0f97aa5f40aaa8e67a99eaea21120c0b96894d46f86a47b10312
4
- data.tar.gz: 3c1b7594b8717c668bb9f38d481afa54057005f524171bd3c088fdf6047344b2
3
+ metadata.gz: '08b9c239346db9904b66db3df8c7c3461f5c3766c6739b3a039cbc96e3d7fa2e'
4
+ data.tar.gz: 4838b7d3720606e0581d364888771a39ec2c3c69c164bfebe838e2d8faac9314
5
5
  SHA512:
6
- metadata.gz: 4b522fa9d586d12f3255b0a9044caff4c8b694e336e3b284a657bc14d2f10a0e10ad3fce4d082784b65435bd73c396b8a593c6c7630bc90b9ac1388bf6f51915
7
- data.tar.gz: 46fbc7ca6360f71e4f6cc992f03a3711b302f2f351c7dca8996999cee8c8eaf196321324bf9ed3f6bf16940c04f5224c72bd5124147663a7b4533aeddd9f27bd
6
+ metadata.gz: 915436bd0e4a48d08809aedc9cbd6317c89ed6c45d2d2356f75805c41f7abb2c756173b0140a84ecad77cf2483058f42106eb31d692f75f80b874c555b59b060
7
+ data.tar.gz: 324ca7a987fbda8bb7dd50e06c84daeeb58acf0743335f8ce39296dcde740b54503e8caca431b159984b59ad678061c3586838e8607f9dadb12581bf972b289c
@@ -25,11 +25,22 @@ module Cats
25
25
  render json: { success: true, data: serialize(woredas) }
26
26
  end
27
27
 
28
+ def create_fdp
29
+ service = LocationService.new
30
+ p = fdp_params
31
+ fdp = service.create_fdp(p[:code], p[:name], p[:parent_id], p[:description])
32
+ render json: { success: true, data: serialize(fdp) }
33
+ end
34
+
28
35
  private
29
36
 
30
37
  def model_params
31
38
  params.require(:payload).permit(:code, :name, :location_type, :description, :parent_id)
32
39
  end
40
+
41
+ def fdp_params
42
+ params.require(:payload).permit(:code, :name, :description, :parent_id)
43
+ end
33
44
  end
34
45
  end
35
46
  end
@@ -4,28 +4,60 @@ module Cats
4
4
  include Common
5
5
 
6
6
  def index
7
- stores = Store.includes(:store_keeper, :stacks).where(warehouse_id: params[:id])
7
+ stores = Store.includes(:stacks).where(warehouse_id: params[:id])
8
8
  render json: { success: true, data: serialize(stores) }
9
9
  end
10
10
 
11
11
  def filter
12
- query = Store.includes(:store_keeper, :stacks).ransack(params[:q])
12
+ query = Store.includes(:stacks).ransack(params[:q])
13
13
  render json: { success: true, data: serialize(query.result) }
14
14
  end
15
15
 
16
16
  def stores_for_hub
17
17
  warehouses = Location.find(params[:id]).children
18
18
  ids = warehouses.map(&:id)
19
- stores = Store.includes(:store_keeper, :stacks).where(warehouse_id: ids)
19
+ stores = Store.includes(:stacks).where(warehouse_id: ids)
20
20
  render json: { success: true, data: serialize(stores) }
21
21
  end
22
22
 
23
+ def assign_store
24
+ store_keeper = User.find(params[:id])
25
+ store_keeper.details['stores'] ||= []
26
+ store_keeper.details['stores'] += store_params[:store_ids]
27
+ store_keeper.save!
28
+ render json: { success: true, data: serialize(store_keeper) }
29
+ end
30
+
31
+ def unassign_store
32
+ store_keeper = User.find(params[:id])
33
+ if store_keeper.details.key?('stores')
34
+ store_keeper.details['stores'] -= store_params[:store_ids]
35
+ store_keeper.save!
36
+ render json: { success: true, data: serialize(store_keeper) }
37
+ else
38
+ render json: { success: false, error: 'User has no stores assigned.' }
39
+ end
40
+ end
41
+
42
+ def fdp
43
+ store = Store.find(params[:id])
44
+ location = store.warehouse.parent
45
+ if location.location_type == Location::FDP
46
+ render json: { success: true, data: serialize(location) }
47
+ else
48
+ render json: { success: false, error: 'No FDP is associated with store.' }
49
+ end
50
+ end
51
+
23
52
  private
24
53
 
25
54
  def model_params
26
55
  params.require('payload').permit(:id, :code, :name, :length, :width, :height, :temporary, :has_gangway,
27
- :gangway_length, :gangway_width, :gangway_corner_dist, :warehouse_id,
28
- :store_keeper_id)
56
+ :gangway_length, :gangway_width, :gangway_corner_dist, :warehouse_id)
57
+ end
58
+
59
+ def store_params
60
+ params.require(:payload).permit(store_ids: [])
29
61
  end
30
62
  end
31
63
  end
@@ -60,7 +60,7 @@ module Cats
60
60
  def name
61
61
  # For this to be efficient, our query should use includes like
62
62
  # Commodity.includes(project: { source: commodity_category })
63
- project.source.commodity_category.name
63
+ project.source.commodity_name
64
64
  end
65
65
 
66
66
  def validate_updateability
@@ -75,6 +75,21 @@ module Cats
75
75
  def start
76
76
  self.dispatch_status = STARTED
77
77
  save!
78
+
79
+ # Check if destination is an FDP and create receipt authorization
80
+ location = dispatch_plan_item.destination
81
+ authorized_by = User.find_by(first_name: 'SYSTEM-USER')
82
+ return unless location.location_type == Location::FDP
83
+
84
+ store = location.fdp_store
85
+ ReceiptAuthorization.create!(
86
+ dispatch: self,
87
+ store: store,
88
+ quantity: quantity,
89
+ received_quantity: 0,
90
+ status: Authorization::AUTHORIZED,
91
+ authorized_by: authorized_by
92
+ )
78
93
  end
79
94
 
80
95
  def receive
@@ -5,11 +5,10 @@ module Cats
5
5
  ZONE = 'Zone'.freeze
6
6
  WOREDA = 'Woreda'.freeze
7
7
  FDP = 'Fdp'.freeze
8
- KEBELE = 'Kebele'.freeze
9
8
  HUB = 'Hub'.freeze
10
9
  WAREHOUSE = 'Warehouse'.freeze
11
10
 
12
- LOCATION_TYPES = [REGION, ZONE, WOREDA, KEBELE, HUB, WAREHOUSE, FDP].freeze
11
+ LOCATION_TYPES = [REGION, ZONE, WOREDA, FDP, HUB, WAREHOUSE].freeze
13
12
 
14
13
  has_ancestry
15
14
 
@@ -23,10 +22,9 @@ module Cats
23
22
  REGION => [],
24
23
  ZONE => [REGION],
25
24
  WOREDA => [REGION, ZONE],
26
- KEBELE => [REGION, ZONE, WOREDA],
27
25
  FDP => [REGION, ZONE, WOREDA],
28
- HUB => [REGION, ZONE, WOREDA, KEBELE],
29
- WAREHOUSE => [REGION, ZONE, WOREDA, KEBELE, HUB]
26
+ HUB => [REGION, ZONE, WOREDA, FDP],
27
+ WAREHOUSE => [REGION, ZONE, WOREDA, FDP, HUB]
30
28
  }
31
29
 
32
30
  return if location_type.nil? || location_type.empty?
@@ -46,6 +44,12 @@ module Cats
46
44
  # wrong type of parent to our location.
47
45
  errors.add(:location, "cannot have #{parent.location_type} as parent")
48
46
  end
47
+
48
+ def fdp_store
49
+ return nil unless location_type == FDP
50
+
51
+ Store.find_by(code: "FDP-ST-#{code}")
52
+ end
49
53
  end
50
54
  end
51
55
  end
@@ -21,7 +21,8 @@ module Cats
21
21
  validates :stack_status, inclusion: { in: STACK_STATUSES }
22
22
  validate :validate_coordinates, :validate_dimensions, :validate_distance_from_wall, :validate_overlap,
23
23
  :validate_space_between_stack, :validate_max_height, :validate_max_length, :validate_max_width,
24
- :validate_distance_from_ceiling, unless: -> { store && store.code == 'SUP-STORE' }
24
+ :validate_distance_from_ceiling,
25
+ unless: -> { store && (store.code == 'SUP-STORE' || store.code.start_with?('FDP-ST')) }
25
26
 
26
27
  delegate :batch_no, to: :commodity, prefix: true
27
28
 
@@ -2,7 +2,6 @@ module Cats
2
2
  module Core
3
3
  class Store < ApplicationRecord
4
4
  belongs_to :warehouse, class_name: 'Cats::Core::Location'
5
- belongs_to :store_keeper, class_name: 'Cats::Core::User'
6
5
  has_many :stacks
7
6
 
8
7
  validates :code, :name, :length, :width, :height, presence: true
@@ -17,7 +16,6 @@ module Cats
17
16
  validate :validate_location
18
17
 
19
18
  before_create :update_usable_space
20
- after_save :update_store_keeper
21
19
 
22
20
  def validate_location
23
21
  return if warehouse.nil?
@@ -25,33 +23,11 @@ module Cats
25
23
  errors.add(:warehouse, 'must be a valid warehouse') unless warehouse.location_type == Location::WAREHOUSE
26
24
  end
27
25
 
28
- def store_keeper_name
29
- "#{store_keeper.first_name} #{store_keeper.last_name}"
30
- end
31
-
32
26
  def update_usable_space
33
27
  self.usable_space = (length - 2) * (width - 2)
34
28
  self.usable_space -= (gangway_length * gangway_width) if has_gangway
35
29
  self.available_space = self.usable_space
36
30
  end
37
-
38
- def update_store_keeper
39
- return unless store_keeper_id_previously_changed?
40
-
41
- unless id_previously_changed?
42
- old_storekeeper = Cats::Core::User.find(store_keeper_id_previously_was)
43
- old_storekeeper.details['stores'].delete(id)
44
- old_storekeeper.save
45
- end
46
- if store_keeper.details.key?('stores')
47
- store_keeper.details['stores'] << id
48
- else
49
- store_keeper.details['stores'] = [id]
50
- end
51
- store_keeper.save
52
- end
53
-
54
- delegate(:phone_number, to: :store_keeper, prefix: true)
55
31
  end
56
32
  end
57
33
  end
@@ -1,9 +1,8 @@
1
1
  module Cats
2
2
  module Core
3
3
  class StoreSerializer < ActiveModel::Serializer
4
- attributes :id, :code, :name, :store_keeper_name, :store_keeper_phone_number, :length, :width, :height,
5
- :temporary, :has_gangway, :gangway_length, :gangway_width, :gangway_corner_dist, :warehouse_id,
6
- :store_keeper_id
4
+ attributes :id, :code, :name, :length, :width, :height, :temporary, :has_gangway, :gangway_length,
5
+ :gangway_width, :gangway_corner_dist, :warehouse_id
7
6
 
8
7
  has_many :stacks
9
8
  end
@@ -24,9 +24,42 @@ module Cats
24
24
  statuses = authorization.dispatch.receipt_authorizations.map(&:driver_confirmed).uniq
25
25
  authorization.dispatch.receive if statuses.length == 1 && statuses[0]
26
26
 
27
+ # Create destination stack and transaction for FDP
28
+ location = authorization.dispatch.dispatch_plan_item.destination
29
+ if location.location_type == Location::FDP
30
+ create_stack(authorization_id)
31
+ stack(authorization_id)
32
+ end
33
+
27
34
  authorization
28
35
  end
29
36
 
37
+ # A method to create stack and stack transactions for FDP
38
+ def create_stack(authorization_id)
39
+ authorization = ReceiptAuthorization.find(authorization_id)
40
+ commodity = authorization.dispatch.dispatch_plan_item.commodity
41
+ stack = Stack.create!(
42
+ code: commodity.batch_no,
43
+ length: 100,
44
+ width: 100,
45
+ height: 100,
46
+ start_x: 2,
47
+ start_y: 2,
48
+ commodity: commodity,
49
+ store: authorization.store,
50
+ commodity_status: Commodity::GOOD,
51
+ stack_status: Stack::ALLOCATED
52
+ )
53
+ ReceiptTransaction.create!(
54
+ receipt_authorization: authorization,
55
+ destination: stack,
56
+ quantity: authorization.received_quantity,
57
+ status: Transaction::DRAFT,
58
+ transaction_date: Date.today
59
+ )
60
+ stack
61
+ end
62
+
30
63
  def stack(authorization_id)
31
64
  authorization = ReceiptAuthorization.find(authorization_id)
32
65
  unless authorization.dispatch.dispatch_status == Dispatch::RECEIVED
@@ -0,0 +1,25 @@
1
+ module Cats
2
+ module Core
3
+ class LocationService
4
+ # This method creates FDP from location params, but also creates the
5
+ # related dummy warehouse and store for the FDP
6
+ def create_fdp(code, name, parent_id, description = nil)
7
+ ActiveRecord::Base.transaction do
8
+ fdp = Location.create!(
9
+ code: code, name: name, description: description, location_type: Location::FDP, parent_id: parent_id
10
+ )
11
+ wh_code = "FDP-WH-#{fdp.code}"
12
+ st_code = "FDP-ST-#{fdp.code}"
13
+
14
+ warehouse = Location.create!(
15
+ code: wh_code, name: wh_code, location_type: Location::WAREHOUSE, parent: fdp
16
+ )
17
+ Store.create!(
18
+ code: st_code, name: st_code, length: 200, width: 200, height: 200, warehouse: warehouse
19
+ )
20
+ fdp
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
data/config/routes.rb CHANGED
@@ -41,6 +41,7 @@ Cats::Core::Engine.routes.draw do
41
41
 
42
42
  get '/regions/:id/woredas', controller: :locations, action: :woredas, as: :region_woredas
43
43
  post '/locations/filter', controller: :locations, action: :filter
44
+ post '/locations/fdp/create', controller: :locations, action: :create_fdp
44
45
  resources :locations, except: %i[destroy] do
45
46
  member do
46
47
  get 'children'
@@ -142,6 +143,18 @@ Cats::Core::Engine.routes.draw do
142
143
  action: :storekeeper_authorizations,
143
144
  as: :storekeeper_receipt_authorizations
144
145
  )
146
+ post(
147
+ '/storekeeper/:id/assign_stores',
148
+ controller: :stores,
149
+ action: :assign_store,
150
+ as: :assign_stores_to_storekeeper
151
+ )
152
+ post(
153
+ '/storekeeper/:id/unassign_stores',
154
+ controller: :stores,
155
+ action: :unassign_store,
156
+ as: :unassign_stores_to_storekeeper
157
+ )
145
158
  post(
146
159
  '/receipt_authorizations/generate',
147
160
  controller: :receipt_authorizations,
@@ -200,6 +213,10 @@ Cats::Core::Engine.routes.draw do
200
213
 
201
214
  get '/warehouses/:id/stores', controller: :stores, action: :index, as: :stores_warehouse
202
215
  get '/hubs/:id/stores', controller: :stores, action: :stores_for_hub, as: :stores_hub
203
- resources :stores, only: %i[index show create update]
216
+ resources :stores, only: %i[index show create update] do
217
+ member do
218
+ get 'fdp'
219
+ end
220
+ end
204
221
  post '/stores/filter', controller: :stores, action: :filter
205
222
  end
@@ -17,10 +17,7 @@ class CreateCatsCoreStores < ActiveRecord::Migration[6.1]
17
17
  null: false,
18
18
  index: { name: 'warehouse_on_stores_indx' },
19
19
  foreign_key: { to_table: :cats_core_locations }
20
- t.references :store_keeper,
21
- null: false,
22
- index: { name: 'store_keeper_on_store_indx' },
23
- foreign_key: { to_table: :cats_core_users }
20
+
24
21
  t.timestamps
25
22
  end
26
23
  end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.4.45'.freeze
3
+ VERSION = '1.4.49'.freeze
4
4
  end
5
5
  end
@@ -2,7 +2,7 @@ FactoryBot.define do
2
2
  factory :dispatch_plan_item, class: 'Cats::Core::DispatchPlanItem' do
3
3
  reference_no { FFaker::Name.name }
4
4
  source factory: :location
5
- destination factory: :location
5
+ destination factory: :woreda
6
6
  dispatch_plan
7
7
  quantity { 100 }
8
8
  unit factory: :unit_of_measure
@@ -19,6 +19,15 @@ FactoryBot.define do
19
19
  factory :fdp, parent: :woreda, class: 'Cats::Core::Location' do
20
20
  location_type { Cats::Core::Location::FDP }
21
21
  parent factory: :woreda
22
+
23
+ trait :with_store do
24
+ after(:create) do |obj|
25
+ wh_code = "FDP-WH-#{obj.code}"
26
+ st_code = "FDP-ST-#{obj.code}"
27
+ warehouse = create(:warehouse, code: wh_code, name: wh_code, parent: obj)
28
+ create(:store, code: st_code, name: st_code, warehouse: warehouse)
29
+ end
30
+ end
22
31
  end
23
32
 
24
33
  factory :hub, parent: :location, class: 'Cats::Core::Location' do
@@ -11,7 +11,5 @@ FactoryBot.define do
11
11
  gangway_width { 4 }
12
12
  gangway_corner_dist { 18 }
13
13
  warehouse
14
- store_keeper factory: :user
15
- store_keeper_id { create(:user).id }
16
14
  end
17
15
  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.45
4
+ version: 1.4.49
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-06-27 00:00:00.000000000 Z
11
+ date: 2022-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 6.0.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: sablon
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: database_cleaner
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -377,6 +391,7 @@ files:
377
391
  - app/services/cats/core/beneficiary_service.rb
378
392
  - app/services/cats/core/dispatch_plan_service.rb
379
393
  - app/services/cats/core/dispatch_service.rb
394
+ - app/services/cats/core/location_service.rb
380
395
  - app/services/cats/core/menu_service.rb
381
396
  - app/services/cats/core/notification_service.rb
382
397
  - app/services/cats/core/round_plan_service.rb