diff --git a/.idea/runConfigurations/Fixtures_on_Test.xml b/.idea/runConfigurations/Fixtures_on_Test.xml
index 1edd808..c835ed6 100644
--- a/.idea/runConfigurations/Fixtures_on_Test.xml
+++ b/.idea/runConfigurations/Fixtures_on_Test.xml
@@ -1,7 +1,5 @@
-
-
@@ -13,6 +11,8 @@
FILE
-
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Test_All_SQL.xml b/.idea/runConfigurations/Test_All_SQL.xml
index 91b3691..0c1b39f 100644
--- a/.idea/runConfigurations/Test_All_SQL.xml
+++ b/.idea/runConfigurations/Test_All_SQL.xml
@@ -1,7 +1,5 @@
-
-
@@ -55,6 +53,10 @@
+
+
+
+
@@ -63,8 +65,11 @@
+ FILE
-
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Test_Follow.xml b/.idea/runConfigurations/Test_Follow.xml
index 5b88876..fe3e336 100644
--- a/.idea/runConfigurations/Test_Follow.xml
+++ b/.idea/runConfigurations/Test_Follow.xml
@@ -11,7 +11,7 @@
FILE
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Test_Opinions.xml b/.idea/runConfigurations/Test_Opinions.xml
index 2c59f4e..735f7a7 100644
--- a/.idea/runConfigurations/Test_Opinions.xml
+++ b/.idea/runConfigurations/Test_Opinions.xml
@@ -13,7 +13,7 @@
FILE
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Workgroup_test.xml b/.idea/runConfigurations/Workgroup_test.xml
new file mode 100644
index 0000000..dff779a
--- /dev/null
+++ b/.idea/runConfigurations/Workgroup_test.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/sql/fixtures/04-article.sql b/src/main/resources/sql/fixtures/04-article.sql
index 719c03e..fe2bfdc 100644
--- a/src/main/resources/sql/fixtures/04-article.sql
+++ b/src/main/resources/sql/fixtures/04-article.sql
@@ -9,15 +9,17 @@ declare
}
$tags$;
_citizen_count int = (select count(z) from citizen z);
+ _workgroup_count int = (select count(w) from workgroup w);
begin
delete from article_relations;
delete from article;
- insert into article (id, version_id, created_by_id, title, anonymous, content, description, tags, created_at, draft)
+ insert into article (id, version_id, created_by_id, workgroup_id, title, anonymous, content, description, tags, created_at, draft)
select
uuid_in(md5('article'||row_number() over ())::cstring),
uuid_in(md5('article_v'||row_number() over () % (_citizen_count / 2))::cstring),
z.id,
+ case when row_number() over () % 2 = 0 then w.id end,
'title' || row_number() over (),
row_number() over () % 3 = 0,
'content' || row_number() over (),
@@ -25,7 +27,8 @@ begin
_tags[(row_number() over () % 5):(row_number() over () % 9)],
now() + (row_number() over () * interval '7 minute 3 second'),
(row_number() over () % 7) = 0
- from citizen z;
+ from (select *, row_number() over () rn from citizen z) z
+ join (select *, row_number() over () % _workgroup_count rn from workgroup) w using (rn);
insert into article_relations (source_id, target_id, created_by_id, comment)
select
diff --git a/src/main/resources/sql/functions/article/find_article_by_id.sql b/src/main/resources/sql/functions/article/find_article_by_id.sql
index f2e714d..0707434 100644
--- a/src/main/resources/sql/functions/article/find_article_by_id.sql
+++ b/src/main/resources/sql/functions/article/find_article_by_id.sql
@@ -8,6 +8,7 @@ begin
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by,
+ find_workgroup_by_id(a.workgroup_id) as workgroup,
count_vote(a.id) as votes,
count_opinion(a.id) as opinions
into resource
diff --git a/src/main/resources/sql/functions/article/find_articles.sql b/src/main/resources/sql/functions/article/find_articles.sql
index cd9e5e0..8c6f032 100644
--- a/src/main/resources/sql/functions/article/find_articles.sql
+++ b/src/main/resources/sql/functions/article/find_articles.sql
@@ -22,6 +22,7 @@ begin
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by,
+ find_workgroup_by_id(a.workgroup_id) as workgroup,
count_vote(a.id) as votes,
count_opinion(a.id) as opinions,
zdb.score(a.ctid) _score
diff --git a/src/main/resources/sql/functions/article/find_articles_versions_by_version_id.sql b/src/main/resources/sql/functions/article/find_articles_versions_by_version_id.sql
index 3c16167..31ffdce 100644
--- a/src/main/resources/sql/functions/article/find_articles_versions_by_version_id.sql
+++ b/src/main/resources/sql/functions/article/find_articles_versions_by_version_id.sql
@@ -15,6 +15,7 @@ begin
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by,
+ find_workgroup_by_id(a.workgroup_id) as workgroup,
count_vote(a.id) as votes
from article as a
where a.version_id = _version_id
diff --git a/src/main/resources/sql/functions/article/find_last_article_by_version_id.sql b/src/main/resources/sql/functions/article/find_last_article_by_version_id.sql
index c88ec2f..d0c8d31 100644
--- a/src/main/resources/sql/functions/article/find_last_article_by_version_id.sql
+++ b/src/main/resources/sql/functions/article/find_last_article_by_version_id.sql
@@ -8,6 +8,7 @@ begin
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by,
+ find_workgroup_by_id(a.workgroup_id) as workgroup,
count_vote(a.id) as votes
into resource
from article as a
diff --git a/src/main/resources/sql/functions/article/upsert_article.sql b/src/main/resources/sql/functions/article/upsert_article.sql
index 42e38f9..fd925ba 100644
--- a/src/main/resources/sql/functions/article/upsert_article.sql
+++ b/src/main/resources/sql/functions/article/upsert_article.sql
@@ -19,6 +19,8 @@ begin
if (_existing_draft_id is not null) then
update article a2 set
+ created_by_id = (resource#>>'{created_by, id}')::uuid,
+ workgroup_id = (resource#>>'{workgroup, id}')::uuid,
title = a.title,
anonymous = a.anonymous,
content = a.content,
@@ -29,12 +31,13 @@ begin
where a2.id = (_existing_draft_id)::uuid
returning a2.id into new_id;
else
- insert into article (id, version_id, created_by_id, title, anonymous, content, description, tags, draft)
+ insert into article (id, version_id, created_by_id, workgroup_id, title, anonymous, content, description, tags, draft)
select
case when _id_exist then uuid_generate_v4()
else coalesce(id, uuid_generate_v4()) end,
coalesce(version_id, uuid_generate_v4()),
(resource#>>'{created_by, id}')::uuid,
+ (resource#>>'{workgroup, id}')::uuid,
title,
anonymous,
content,
diff --git a/src/main/resources/sql/functions/workgroup/find_workgroup_by_id.sql b/src/main/resources/sql/functions/workgroup/find_workgroup_by_id.sql
new file mode 100644
index 0000000..7b8173d
--- /dev/null
+++ b/src/main/resources/sql/functions/workgroup/find_workgroup_by_id.sql
@@ -0,0 +1,22 @@
+create or replace function find_workgroup_by_id(in id uuid, out resource json) language plpgsql as
+$$
+declare
+ _id alias for id;
+begin
+ select to_json(t)
+ from (
+ select
+ w.*,
+ find_citizen_by_id(w.created_by_id) as created_by,
+ find_citizen_by_id(w.owner_id) as owner
+ into resource
+ from workgroup as w
+ left join citizen_in_workgroup ciw on w.id = ciw.workgroup_id
+ where w.id = _id
+ and deleted_at is null
+ ) as t;
+end;
+$$;
+
+-- drop function if exists find_workgroup_by_id(uuid, out json);
+-- select * from find_workgroup_by_id('d011ad4c-fa1b-40a3-593b-7816479ff33b')
diff --git a/src/main/resources/sql/functions/workgroup/find_workgroups.sql b/src/main/resources/sql/functions/workgroup/find_workgroups.sql
new file mode 100644
index 0000000..6a5c6c1
--- /dev/null
+++ b/src/main/resources/sql/functions/workgroup/find_workgroups.sql
@@ -0,0 +1,59 @@
+create or replace function find_workgroups(
+ _search text default null,
+ _filter json default '{}',
+ direction text default 'desc',
+ sort text default 'created_at',
+ "limit" int default 50,
+ "offset" int default 0,
+ out resource json,
+ out total int
+) language plpgsql as
+$$
+begin
+ select json_agg(t), (
+ select count(id)
+ from workgroup w
+ where deleted_at is null
+ and (_search is null or _search = '' or w ==> dsl.multi_match('{name^3, description}', _search))
+ and (_filter->>'created_by_id' is null or w.created_by_id = (_filter->>'created_by_id')::uuid)
+ )
+ into resource, total
+ from (
+ select
+ w.*,
+ find_citizen_by_id(w.created_by_id) as created_by,
+ find_citizen_by_id(w.owner_id) as owner,
+ zdb.score(w.ctid) _score
+ from workgroup as w
+ where deleted_at is null
+ and (
+ _search is null
+ or _search = ''
+ or w ==> dsl.multi_match('{name^3, description}', _search)
+ )
+ and (_filter->>'created_by_id' is null or w.created_by_id = (_filter->>'created_by_id')::uuid)
+
+ order by
+ _score desc,
+ case direction when 'asc' then
+ case sort
+ when 'name' then w.name
+ when 'created_at' then w.created_at::text
+ else null
+ end
+ end,
+ case direction when 'desc' then
+ case sort
+ when 'title' then w.name
+ when 'created_at' then w.created_at::text
+ end
+ end
+ desc,
+ w.created_at desc
+ limit "limit" offset "offset"
+ ) as t;
+end;
+$$;
+
+-- drop function if exists find_workgroups(text, json, text, text, int, int);
+-- select * from find_workgroups('49', "limit" := 2)
\ No newline at end of file
diff --git a/src/main/resources/sql/functions/workgroup/upsert_workgroup.sql b/src/main/resources/sql/functions/workgroup/upsert_workgroup.sql
new file mode 100644
index 0000000..c2d825f
--- /dev/null
+++ b/src/main/resources/sql/functions/workgroup/upsert_workgroup.sql
@@ -0,0 +1,29 @@
+create or replace function upsert_workgroup(inout resource json)
+ language plpgsql as
+$$
+declare
+ new_id uuid = coalesce((resource->>'id')::uuid, uuid_generate_v4());
+begin
+ insert into workgroup (id, created_by_id, name, description, anonymous, logo, owner_id)
+ select
+ new_id,
+ (resource#>>'{created_by, id}')::uuid,
+ name,
+ description,
+ anonymous,
+ logo,
+ (resource#>>'{owner, id}')::uuid
+ from json_populate_record(null::workgroup, resource)
+ on conflict (id) do update set
+ name = excluded.name,
+ description = excluded.description,
+ anonymous = excluded.anonymous,
+ logo = excluded.logo,
+ owner_id = excluded.owner_id;
+
+
+ select find_workgroup_by_id(new_id) into resource;
+end;
+$$;
+
+-- drop procedure if exists upsert_workgroup(inout json);
\ No newline at end of file
diff --git a/src/main/resources/sql/migrations/0000-init_schema.up.sql b/src/main/resources/sql/migrations/0000-init_schema.up.sql
index d635838..1e87249 100644
--- a/src/main/resources/sql/migrations/0000-init_schema.up.sql
+++ b/src/main/resources/sql/migrations/0000-init_schema.up.sql
@@ -27,6 +27,7 @@ create table workgroup
id uuid default uuid_generate_v4() not null primary key,
created_at timestamptz default now() not null,
updated_at timestamptz default now() not null check ( updated_at >= created_at ),
+ deleted_at timestamptz null check ( deleted_at is null or deleted_at >= updated_at ),
created_by_id uuid not null references citizen (id),
name varchar(128) not null,
description text null,
@@ -194,6 +195,7 @@ create table article
id uuid default uuid_generate_v4() not null primary key,
created_at timestamptz default now() not null,
created_by_id uuid not null references citizen (id),
+ workgroup_id uuid null references workgroup (id),
version_id uuid default uuid_generate_v4() not null,
version_number int not null,
title text not null check ( length(title) < 128 ),
@@ -740,4 +742,25 @@ create index citizen_idx
using zombodb ((citizen.*))
with (alias ='citizen_idx');
-reindex index citizen_idx;
\ No newline at end of file
+reindex index citizen_idx;
+
+
+-- INDEX workgroup table
+select zdb.define_field_mapping('workgroup', 'name', '{
+ "type": "text",
+ "analyzer": "name_analyzer",
+ "search_analyzer": "name_analyzer"
+}');
+
+select zdb.define_field_mapping('workgroup', 'description', '{
+ "type": "text",
+ "analyzer": "fr_analyzer",
+ "search_analyzer": "fr_analyzer"
+}');
+
+create index workgroup_idx
+ on workgroup
+ using zombodb ((workgroup.*))
+ with (alias ='workgroup_idx');
+
+reindex index workgroup_idx;
\ No newline at end of file
diff --git a/src/test/sql/fixtures/fixture_workgroup.sql b/src/test/sql/fixtures/fixture_workgroup.sql
new file mode 100644
index 0000000..cdf029c
--- /dev/null
+++ b/src/test/sql/fixtures/fixture_workgroup.sql
@@ -0,0 +1,29 @@
+create or replace function fixture_workgroup(in name text default 'vert', _citizen_id uuid default fixture_citizen(), out _article_id uuid)
+ language plpgsql as
+$$
+declare
+ created_workgroup json;
+begin
+ if (name = 'vert') then
+ created_workgroup = '{
+ "name": "Le groupe des vert",
+ "description": "test",
+ "anonymous": false
+ }';
+ elseif (name = 'rouge') then
+ created_workgroup = '{
+ "name": "Le groupe des rouge",
+ "description": "test",
+ "anonymous": false
+ }';
+ end if;
+
+ created_workgroup := jsonb_set(created_workgroup::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ created_workgroup := jsonb_set(created_workgroup::jsonb, '{owner}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ assert created_workgroup#>>'{created_by, id}' = _citizen_id::text, format('citizenId in workgroup must be the same as citizen, %s != %s', created_workgroup#>>'{created_by, id}', _citizen_id::text);
+
+ -- upsert workgroup
+ select upsert_workgroup(created_workgroup) into created_workgroup;
+ assert created_workgroup->>'description' is not null, 'description should not be null';
+end;
+$$
\ No newline at end of file
diff --git a/src/test/sql/workgroup.sql b/src/test/sql/workgroup.sql
new file mode 100644
index 0000000..4afe90d
--- /dev/null
+++ b/src/test/sql/workgroup.sql
@@ -0,0 +1,44 @@
+do
+$$
+declare
+ _citizen_id uuid := fixture_citizen();
+ created_workgroup json := '{
+ "name": "Le groupe des vert",
+ "description": "test",
+ "anonymous": false
+ }';
+ created_workgroup_2 json := '{
+ "name": "hello",
+ "description": "super",
+ "anonymous": false
+ }';
+ selected_workgroup json;
+ selected_workgroup_2 json;
+begin
+ created_workgroup := jsonb_set(created_workgroup::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ created_workgroup := jsonb_set(created_workgroup::jsonb, '{owner}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ assert created_workgroup#>>'{created_by, id}' = _citizen_id::text, format('citizenId in workgroup must be the same as citizen, %s != %s', created_workgroup#>>'{created_by, id}', _citizen_id::text);
+
+ -- upsert workgroup
+ select upsert_workgroup(created_workgroup) into created_workgroup;
+ assert created_workgroup->>'description' is not null, 'description should not be null';
+ assert (created_workgroup->>'name') = 'Le groupe des vert', format('name must be equal to "Le groupe des vert", %s instead', created_workgroup->>'name');
+
+ -- insert another workgroup
+ created_workgroup_2 := jsonb_set(created_workgroup_2::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ created_workgroup_2 := jsonb_set(created_workgroup_2::jsonb, '{owner}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
+ assert created_workgroup_2#>>'{created_by, id}' = _citizen_id::text, format('citizenId in workgroup must be the same as citizen, %s != %s', created_workgroup_2#>>'{created_by, id}', _citizen_id::text);
+ select upsert_workgroup(created_workgroup_2) into created_workgroup_2;
+
+ -- get workgroup by id and check the name
+ select find_workgroup_by_id((created_workgroup->>'id')::uuid) into selected_workgroup;
+ assert selected_workgroup->>'name' = 'Le groupe des vert', format('name must be "Le groupe des vert", %s', selected_workgroup->>'name');
+
+ -- search workgroups and check the name
+ select (w.resource->0) into selected_workgroup from find_workgroups('Le groupe des vert', "limit" := 1) w;
+ assert (selected_workgroup->>'name') = 'Le groupe des vert', format('name must be "Le groupe des vert" instead of : %s', (selected_workgroup->>'name'));
+
+ rollback;
+ raise notice 'workgroup test pass';
+end
+$$;