diff --git a/resources/functions/constitution/create_title_in_constitution.sql b/resources/functions/constitution/create_title_in_constitution.sql new file mode 100644 index 0000000..dad5dd5 --- /dev/null +++ b/resources/functions/constitution/create_title_in_constitution.sql @@ -0,0 +1,35 @@ +create or replace function create_title_in_constitution(title json, constitution_id uuid default null, out resource json) + language plpgsql as +$$ +declare + _title alias for title; + _constitution_id uuid = coalesce(constitution_id, (title#>>'{constitution_id}')::uuid); + _author_id uuid = (title#>>'{created_by, id}')::uuid; + new_id uuid; +begin + insert into title (created_by_id, name, rank, constitution_id) + select + _author_id, + ti.name, + row_number() OVER (), + _constitution_id + from json_populate_record(null::title, _title) ti + returning id into new_id; + + if (_title->'articles' is not null) then + insert into article_in_title (created_by_id, rank, title_id, article_id, constitution_id) + select + _author_id, + row_number() over (), + new_id, + id, + coalesce ((_title->>'constitution_id')::uuid, _constitution_id) + from json_populate_recordset(null::article, _title->'articles') ; + end if; + + select find_constitution_title_by_id(new_id) + into resource; +end; +$$; + +-- drop function if exists create_title_in_constitution(out json); \ No newline at end of file diff --git a/resources/functions/constitution/find_constitution_title_by_id.sql b/resources/functions/constitution/find_constitution_title_by_id.sql new file mode 100644 index 0000000..d4296b9 --- /dev/null +++ b/resources/functions/constitution/find_constitution_title_by_id.sql @@ -0,0 +1,24 @@ +create or replace function find_constitution_title_by_id(in id uuid, out resource json) language plpgsql as +$$ +declare + _id alias for id; +begin + select to_json(t) + from ( + select + ti.id, + ti.name, + ti.rank, + array_agg(a order by ait.rank) as articles + into resource + from title as ti + left join article_in_title ait on ti.id = ait.title_id + left join article a on ait.article_id = a.id + where ti.id = _id + group by ti.id + order by ti.rank + ) as t; +end; +$$; + +-- drop function if exists find_constitution_title_by_id(uuid, out json); \ No newline at end of file diff --git a/resources/functions/constitution/upsert_constitution.sql b/resources/functions/constitution/upsert_constitution.sql index 0b09868..42fe892 100644 --- a/resources/functions/constitution/upsert_constitution.sql +++ b/resources/functions/constitution/upsert_constitution.sql @@ -3,12 +3,14 @@ create or replace procedure upsert_constitution(inout resource json) $$ declare titles json; + _title json; + _citizen_id uuid = (resource#>>'{created_by, id}')::uuid; new_id uuid; begin insert into constitution (version_id, created_by_id, title, annonymous) select version_id, - (resource#>>'{created_by, id}')::uuid, + _citizen_id, title, annonymous from json_populate_record(null::constitution, resource) @@ -16,14 +18,13 @@ begin titles := (resource->>'titles'); - insert into title (created_by_id, name, rank, constitution_id) - select - coalesce((ti#>>'{created_by, id}')::uuid, (resource#>>'{created_by, id}')::uuid), - ti->>'name', - row_number() OVER (), - new_id - from json_array_elements(titles) ti, - lateral json_populate_record(null::title, ti); + for _title in select json_array_elements(titles) loop + if _title#>>'{created_by, id}' is null then + _title := jsonb_set(_title::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json; + end if; + + perform create_title_in_constitution(_title, new_id); + end loop; select find_constitution_by_id(new_id) into resource; end; diff --git a/resources/sql/migrations/0000-init_schema.up.sql b/resources/sql/migrations/0000-init_schema.up.sql index 1046234..7a6ed8d 100644 --- a/resources/sql/migrations/0000-init_schema.up.sql +++ b/resources/sql/migrations/0000-init_schema.up.sql @@ -161,6 +161,7 @@ begin from title as t where t.id = new.title_id ); + return new; end; $$; diff --git a/resources/tests/constitution.sql b/resources/tests/constitution.sql index 2a95203..8f73638 100644 --- a/resources/tests/constitution.sql +++ b/resources/tests/constitution.sql @@ -4,9 +4,42 @@ declare created_user json := '{"username": "george", "plain_password": "azerty"}'; _user_id uuid; _citizen_id uuid; - created_citizen json := '{"name": {"first_name":"George", "last_name":"MICHEL"}, "birthday": "2001-01-01"}'; - created_article json := '{"version_id":"933b6a1b-50c9-42b6-989f-c02a57814ef9", "title": "Love the world", "annonymous": false, "content": "bla bal bla", "tags": ["love", "test"]}'; - created_constitution json := '{"version_id":"18ff6dd6-3bc1-4c59-82f0-5e2a8d54ae3e", "title": "Love the world", "annonymous": false, "titles": [{"name":"titleOne"},{"name":"titleTwo"}]}'; + created_citizen json := $json$ + { + "name": { + "first_name": "George", + "last_name": "MICHEL" + }, + "birthday": "2001-01-01" + } + $json$; + created_article json := $json$ + { + "version_id": "933b6a1b-50c9-42b6-989f-c02a57814ef9", + "title": "Love the world", + "annonymous": false, + "content": "bla bal bla", + "tags": [ + "love", + "test" + ] + } + $json$; + created_constitution json := $json$ + { + "version_id": "18ff6dd6-3bc1-4c59-82f0-5e2a8d54ae3e", + "title": "Love the world", + "annonymous": false, + "titles": [ + { + "name": "titleOne" + }, + { + "name": "titleTwo" + } + ] + } + $json$; begin -- insert user for context call insert_user(created_user); @@ -27,11 +60,13 @@ begin -- create new constitution created_constitution := jsonb_set(created_constitution::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json; + created_constitution := jsonb_set(created_constitution::jsonb, '{titles, 0, articles}'::text[], jsonb_build_array(jsonb_build_object('id', created_article->>'id')), true)::json; call upsert_constitution(created_constitution); assert (created_constitution->>'version_number')::int = 1, format('version_number must be equal to 1, %s instead', created_constitution->>'version_number'); assert created_constitution#>>'{titles, 0, name}' = 'titleOne'::text, format('the name of the first title of contitution must be %s, not %s', 'titleOne', created_constitution#>>'{titles, 0, name}'); -- delete article and context + delete from article_in_title; delete from title; delete from constitution; delete from article;