diff --git a/app/controllers/staffs/org_units_controller.rb b/app/controllers/staffs/org_units_controller.rb
new file mode 100644
index 0000000..12adb57
--- /dev/null
+++ b/app/controllers/staffs/org_units_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Staffs::OrgUnitsController < ApplicationController
+ before_action :set_org_unit, only: :show
+
+ # GET /staff/org_units
+ def index
+ authorize [:staff, OrgUnit]
+ @org_units = policy_scope(
+ OrgUnit,
+ policy_scope_class: Staff::OrgUnitPolicy::Scope,
+ ).page(params[:page])
+ end
+
+ # GET /staff/org_units/:id
+ def show
+ authorize [:staff, @org_unit]
+ end
+
+private
+
+ def set_org_unit
+ @org_unit = OrgUnit.find params[:id]
+ end
+end
diff --git a/app/policies/staff/org_unit_policy.rb b/app/policies/staff/org_unit_policy.rb
new file mode 100644
index 0000000..068d675
--- /dev/null
+++ b/app/policies/staff/org_unit_policy.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Staff::OrgUnitPolicy < ApplicationPolicy
+ def index?
+ return false if restricted?
+
+ account&.superuser?
+ end
+
+ def show?
+ return false if restricted?
+
+ account&.superuser?
+ end
+
+ class Scope < Scope
+ def resolve
+ return scope.none if restricted?
+
+ return scope.all if account&.superuser?
+
+ scope.none
+ end
+ end
+end
diff --git a/app/views/staffs/home/show.html.erb b/app/views/staffs/home/show.html.erb
index 3518991..32207f1 100644
--- a/app/views/staffs/home/show.html.erb
+++ b/app/views/staffs/home/show.html.erb
@@ -41,5 +41,12 @@
staff_org_unit_kinds_path %>
<% end %>
+
+ <% if policy([:staff, OrgUnit]).index? %>
+
+ <%= link_to OrgUnit.model_name.human(count: 0),
+ staff_org_units_path %>
+
+ <% end %>
diff --git a/app/views/staffs/org_units/_table.html.erb b/app/views/staffs/org_units/_table.html.erb
new file mode 100644
index 0000000..aba7d82
--- /dev/null
+++ b/app/views/staffs/org_units/_table.html.erb
@@ -0,0 +1,27 @@
+
+
+
+
+ <%= OrgUnit.human_attribute_name :short_name %>
+ |
+
+ <%= OrgUnit.human_attribute_name :name %>
+ |
+ |
+
+
+
+
+ <% org_units.each do |org_unit| %>
+
+ <%= org_unit.short_name %> |
+ <%= org_unit.name %> |
+
+ <% if policy([:staff, org_unit]).show? %>
+ <%= open_action [:staff, org_unit] %>
+ <% end %>
+ |
+
+ <% end %>
+
+
diff --git a/app/views/staffs/org_units/index.html.erb b/app/views/staffs/org_units/index.html.erb
new file mode 100644
index 0000000..f3a063e
--- /dev/null
+++ b/app/views/staffs/org_units/index.html.erb
@@ -0,0 +1,9 @@
+
+ <%= nav_breadcrumb(
+ [translate(:staff_services), staff_root_path],
+ OrgUnit.model_name.human(count: 0),
+ ) %>
+
+ <%= render partial: 'table', locals: { org_units: @org_units } %>
+ <%= pagination @org_units %>
+
diff --git a/app/views/staffs/org_units/show.html.erb b/app/views/staffs/org_units/show.html.erb
new file mode 100644
index 0000000..fa51261
--- /dev/null
+++ b/app/views/staffs/org_units/show.html.erb
@@ -0,0 +1,39 @@
+
+ <%= nav_breadcrumb(
+ [translate(:staff_services), staff_root_path],
+ [OrgUnit.model_name.human(count: 0), staff_org_units_path],
+ @org_unit.name,
+ ) %>
+
+
+ - <%= OrgUnit.human_attribute_name :kind %>
+ -
+ <% if @org_unit.kind.nil? %>
+ <%= none %>
+ <% elsif policy([:staff, @org_unit.kind]).show? %>
+ <%= link_to @org_unit.kind.name,
+ [:staff, @org_unit.kind] %>
+ <% else %>
+ <%= @org_unit.kind.name %>
+ <% end %>
+
+
+ - <%= OrgUnit.human_attribute_name :short_name %>
+ - <%= @org_unit.short_name %>
+
+ - <%= OrgUnit.human_attribute_name :name %>
+ - <%= @org_unit.name %>
+
+ - <%= OrgUnit.human_attribute_name :parent %>
+ -
+ <% if @org_unit.parent.nil? %>
+ <%= none %>
+ <% elsif policy([:staff, @org_unit.parent]).show? %>
+ <%= link_to @org_unit.parent.name,
+ [:staff, @org_unit.parent] %>
+ <% else %>
+ <%= @org_unit.parent.name %>
+ <% end %>
+
+
+
diff --git a/config/locales/activerecord/en.yml b/config/locales/activerecord/en.yml
index 1f0c09b..b21f2e6 100644
--- a/config/locales/activerecord/en.yml
+++ b/config/locales/activerecord/en.yml
@@ -14,6 +14,10 @@ en:
federal_subject:
one: State
many: States
+ org_unit:
+ one: Organizational unit
+ few: Organizational unit
+ many: Organizational units
org_unit_kind:
one: Organizational unit type
few: Organizational unit types
@@ -68,6 +72,12 @@ en:
centre: Administrative centre
number: Number
timezone: Time zone
+ org_unit:
+ id: ID
+ kind: Type
+ short_name: Short name
+ name: Name
+ parent: Parent
org_unit_kind:
id: ID
codename: Codename
diff --git a/config/locales/activerecord/ru.yml b/config/locales/activerecord/ru.yml
index d9776b0..34268da 100644
--- a/config/locales/activerecord/ru.yml
+++ b/config/locales/activerecord/ru.yml
@@ -14,6 +14,10 @@ ru:
federal_subject:
one: Регион
many: Регионы
+ org_unit:
+ one: Организационное подразделение
+ few: Организационные подразделения
+ many: Организационные подразделения
org_unit_kind:
one: Тип организационных подразделений
few: Типы организационных подразделений
@@ -68,6 +72,12 @@ ru:
centre: Административный центр
number: Номер
timezone: Часовой пояс
+ org_unit:
+ id: ID
+ kind: Тип
+ short_name: Короткое развание
+ name: Название
+ parent: Родитель
org_unit_kind:
id: ID
codename: Кодовое имя
diff --git a/config/routes.rb b/config/routes.rb
index 27a2380..09348a3 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -65,6 +65,8 @@ Rails.application.routes.draw do
resources :org_unit_kinds, param: :codename, only: %i[index show]
+ resources :org_units, only: %i[index show]
+
resources :people, only: %i[index show new create] do
resources :person_comments,
path: 'comments',
diff --git a/spec/policies/staff/org_unit_policy_spec.rb b/spec/policies/staff/org_unit_policy_spec.rb
new file mode 100644
index 0000000..eaa78f4
--- /dev/null
+++ b/spec/policies/staff/org_unit_policy_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Staff::OrgUnitPolicy do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/requests/staff/org_units/index_spec.rb b/spec/requests/staff/org_units/index_spec.rb
new file mode 100644
index 0000000..f01d22d
--- /dev/null
+++ b/spec/requests/staff/org_units/index_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'GET /staff/org_units' do
+ let(:current_account) { create :superuser_account }
+
+ let :org_units_count do
+ [0, 1, rand(2..4), rand(5..10), rand(20..40)].sample
+ end
+
+ before do
+ sign_in current_account.user if current_account&.user
+
+ create_list :some_root_org_unit, org_units_count
+
+ get '/staff/org_units'
+ end
+
+ for_account_types nil, :usual do
+ specify do
+ expect(response).to have_http_status :forbidden
+ end
+ end
+
+ for_account_types :superuser do
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when there are no organizational units' do
+ let(:org_units_count) { 0 }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when there is one organizational unit' do
+ let(:org_units_count) { 1 }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when there are few organizational units' do
+ let(:org_units_count) { rand 2..4 }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when there are many organizational units' do
+ let(:org_units_count) { rand 5..10 }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when there are lot of organizational units' do
+ let(:org_units_count) { rand 20..40 }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+end
diff --git a/spec/requests/staff/org_units/show_spec.rb b/spec/requests/staff/org_units/show_spec.rb
new file mode 100644
index 0000000..cb895bf
--- /dev/null
+++ b/spec/requests/staff/org_units/show_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'GET /staff/org_units/:id' do
+ let(:current_account) { create :superuser_account }
+
+ let(:some_org_unit) { create :some_root_org_unit }
+
+ def make_request
+ get "/staff/org_units/#{some_org_unit.id}"
+ end
+
+ before do
+ sign_in current_account.user if current_account&.user
+ make_request
+ end
+
+ for_account_types nil, :usual do
+ specify do
+ expect(response).to have_http_status :forbidden
+ end
+ end
+
+ for_account_types :superuser do
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+
+ context 'when organizational unit has parent' do
+ let(:some_org_unit) { create :some_children_org_unit }
+
+ specify do
+ expect(response).to have_http_status :ok
+ end
+ end
+end