Add reference OrgUnit#resource
This commit is contained in:
parent
0c49c40330
commit
68193ec846
|
@ -14,6 +14,10 @@ class OrgUnit < ApplicationRecord
|
|||
inverse_of: :children_units,
|
||||
optional: true
|
||||
|
||||
belongs_to :resource,
|
||||
polymorphic: true,
|
||||
optional: true
|
||||
|
||||
has_many :children_units,
|
||||
class_name: 'OrgUnit',
|
||||
inverse_of: :parent_unit,
|
||||
|
@ -37,6 +41,12 @@ class OrgUnit < ApplicationRecord
|
|||
message: :required,
|
||||
}
|
||||
|
||||
validates :resource,
|
||||
presence: {
|
||||
if: ->(record) { record.kind&.resource_type },
|
||||
message: :required,
|
||||
}
|
||||
|
||||
validate :parent_matches_kind
|
||||
|
||||
#############
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddResourceToOrgUnits < ActiveRecord::Migration[6.0]
|
||||
include Partynest::Migration
|
||||
|
||||
def change
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
execute 'ALTER SEQUENCE org_units_id_seq RESTART WITH 1000'
|
||||
end
|
||||
end
|
||||
|
||||
add_reference :org_units, :resource, polymorphic: true, null: true
|
||||
|
||||
add_func_validate_org_unit_resource
|
||||
|
||||
add_trigger :org_units,
|
||||
:add_func_validate_org_unit_resource,
|
||||
'BEFORE INSERT OR UPDATE',
|
||||
'add_func_validate_org_unit_resource()'
|
||||
end
|
||||
|
||||
def add_func_validate_org_unit_resource
|
||||
add_func :add_func_validate_org_unit_resource, <<~SQL
|
||||
() RETURNS trigger LANGUAGE plpgsql AS
|
||||
$$
|
||||
DECLARE
|
||||
org_unit_kind record;
|
||||
BEGIN
|
||||
IF NEW.kind_id IS NULL THEN
|
||||
IF NEW.resource_type IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
SELECT * FROM org_unit_kinds INTO org_unit_kind WHERE id = NEW.kind_id;
|
||||
|
||||
IF org_unit_kind IS NULL THEN
|
||||
RAISE EXCEPTION 'can not find type';
|
||||
END IF;
|
||||
|
||||
IF org_unit_kind.resource_type IS NULL THEN
|
||||
IF NEW.resource_type IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
ELSE
|
||||
IF NEW.resource_type IS NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NOT NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_type != org_unit_kind.resource_type THEN
|
||||
RAISE EXCEPTION 'resource type is invalid';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
SQL
|
||||
end
|
||||
end
|
|
@ -48,6 +48,61 @@ CREATE TYPE public.sex AS ENUM (
|
|||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: add_func_validate_org_unit_resource(); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION public.add_func_validate_org_unit_resource() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
org_unit_kind record;
|
||||
BEGIN
|
||||
IF NEW.kind_id IS NULL THEN
|
||||
IF NEW.resource_type IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
SELECT * FROM org_unit_kinds INTO org_unit_kind WHERE id = NEW.kind_id;
|
||||
|
||||
IF org_unit_kind IS NULL THEN
|
||||
RAISE EXCEPTION 'can not find type';
|
||||
END IF;
|
||||
|
||||
IF org_unit_kind.resource_type IS NULL THEN
|
||||
IF NEW.resource_type IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
ELSE
|
||||
IF NEW.resource_type IS NULL THEN
|
||||
RAISE EXCEPTION 'resource type is invalid (expected NOT NULL)';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_type != org_unit_kind.resource_type THEN
|
||||
RAISE EXCEPTION 'resource type is invalid';
|
||||
END IF;
|
||||
|
||||
IF NEW.resource_id IS NULL THEN
|
||||
RAISE EXCEPTION 'resource ID is invalid (expected NULL)';
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
--
|
||||
-- Name: ensure_contact_list_id_matches_related_person(); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -732,6 +787,8 @@ CREATE TABLE public.org_units (
|
|||
kind_id bigint NOT NULL,
|
||||
parent_unit_id bigint,
|
||||
level integer NOT NULL,
|
||||
resource_type character varying,
|
||||
resource_id bigint,
|
||||
CONSTRAINT level CHECK ((level >= 0)),
|
||||
CONSTRAINT name CHECK (public.is_good_small_text((name)::text)),
|
||||
CONSTRAINT parent_unit CHECK ((parent_unit_id <> id)),
|
||||
|
@ -1528,6 +1585,13 @@ CREATE UNIQUE INDEX index_org_units_on_name ON public.org_units USING btree (nam
|
|||
CREATE INDEX index_org_units_on_parent_unit_id ON public.org_units USING btree (parent_unit_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_org_units_on_resource_type_and_resource_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_org_units_on_resource_type_and_resource_id ON public.org_units USING btree (resource_type, resource_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_org_units_on_short_name; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -1682,6 +1746,13 @@ CREATE UNIQUE INDEX index_users_on_reset_password_token ON public.users USING bt
|
|||
CREATE UNIQUE INDEX index_users_on_unlock_token ON public.users USING btree (unlock_token);
|
||||
|
||||
|
||||
--
|
||||
-- Name: org_units add_func_validate_org_unit_resource; Type: TRIGGER; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TRIGGER add_func_validate_org_unit_resource BEFORE INSERT OR UPDATE ON public.org_units FOR EACH ROW EXECUTE PROCEDURE public.add_func_validate_org_unit_resource();
|
||||
|
||||
|
||||
--
|
||||
-- Name: accounts ensure_contact_list_id_matches_related_person; Type: TRIGGER; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -1905,6 +1976,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20191001022049'),
|
||||
('20191002002101'),
|
||||
('20191002170727'),
|
||||
('20191021060000');
|
||||
('20191021060000'),
|
||||
('20191021061920');
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
|
||||
FactoryBot.define do
|
||||
factory :federal_subject do
|
||||
initialize_with do
|
||||
FederalSubject.find_or_initialize_by(
|
||||
number: number,
|
||||
english_name: english_name,
|
||||
native_name: native_name,
|
||||
)
|
||||
end
|
||||
|
||||
number { rand 1..2**31 - 1 }
|
||||
|
||||
english_name do
|
||||
|
@ -16,4 +24,20 @@ FactoryBot.define do
|
|||
|
||||
timezone { "#{[nil, :-].sample}#{rand(0..11).to_s.rjust(2, '0')}:00:00" }
|
||||
end
|
||||
|
||||
factory :moscow_federal_subject, parent: :federal_subject do
|
||||
number { 77 }
|
||||
english_name { 'Moscow' }
|
||||
native_name { 'Москва' }
|
||||
centre { 'Москва' }
|
||||
timezone { '03:00:00' }
|
||||
end
|
||||
|
||||
factory :perm_federal_subject, parent: :federal_subject do
|
||||
number { 27 }
|
||||
english_name { 'Perm Krai' }
|
||||
native_name { 'Пермский край' }
|
||||
centre { 'Пермь' }
|
||||
timezone { '05:00:00' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,6 +35,7 @@ FactoryBot.define do
|
|||
|
||||
association :kind, factory: :reg_dept_org_unit_kind
|
||||
association :parent_unit, factory: :lpr_org_unit
|
||||
association :resource, factory: :moscow_federal_subject
|
||||
end
|
||||
|
||||
factory :perm_reg_dept_org_unit, parent: :lpr_org_unit do
|
||||
|
@ -46,6 +47,7 @@ FactoryBot.define do
|
|||
|
||||
association :kind, factory: :reg_dept_org_unit_kind
|
||||
association :parent_unit, factory: :lpr_org_unit
|
||||
association :resource, factory: :perm_federal_subject
|
||||
end
|
||||
|
||||
factory :fed_management_org_unit, parent: :lpr_org_unit do
|
||||
|
|
|
@ -35,7 +35,7 @@ RSpec.describe OrgUnit do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when organizational unit type does not require parent' do
|
||||
context 'when organizational unit type requires parent' do
|
||||
subject { create :some_children_org_unit }
|
||||
|
||||
it do
|
||||
|
@ -46,6 +46,41 @@ RSpec.describe OrgUnit do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#resource' do
|
||||
it { is_expected.to belong_to(:resource).optional }
|
||||
|
||||
context 'when organizational unit type does not require resource' do
|
||||
subject { create :some_children_org_unit }
|
||||
|
||||
it do
|
||||
is_expected.not_to \
|
||||
validate_presence_of(:resource)
|
||||
.with_message(:required)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when organizational unit type requires resource' do
|
||||
subject do
|
||||
create :some_children_org_unit,
|
||||
kind: org_unit_kind,
|
||||
resource: resource
|
||||
end
|
||||
|
||||
let :org_unit_kind do
|
||||
create :some_children_org_unit_kind,
|
||||
resource_type: resource.class.name
|
||||
end
|
||||
|
||||
let(:resource) { create :federal_subject }
|
||||
|
||||
it do
|
||||
is_expected.to \
|
||||
validate_presence_of(:resource)
|
||||
.with_message(:required)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#children_units' do
|
||||
it do
|
||||
is_expected.to \
|
||||
|
|
Reference in New Issue