diff --git a/schema/deploy/mutations/create_application_revision_mutation_chain.sql b/schema/deploy/mutations/create_application_revision_mutation_chain.sql index ddba67b062..53710927da 100644 --- a/schema/deploy/mutations/create_application_revision_mutation_chain.sql +++ b/schema/deploy/mutations/create_application_revision_mutation_chain.sql @@ -25,7 +25,7 @@ begin values (application_id_input, new_version_number); select reporting_year from ggircs_portal.opened_reporting_year() into current_reporting_year; - if current_reporting_year is null then + if new_version_number <= 1 and current_reporting_year is null then raise exception 'The application window is closed'; end if; diff --git a/schema/deploy/mutations/create_application_revision_mutation_chain@v1.5.0.sql b/schema/deploy/mutations/create_application_revision_mutation_chain@v1.5.0.sql new file mode 100644 index 0000000000..ddba67b062 --- /dev/null +++ b/schema/deploy/mutations/create_application_revision_mutation_chain@v1.5.0.sql @@ -0,0 +1,111 @@ +-- Deploy ggircs-portal:function_create_application_revision_mutation_chain to pg +-- requires: table_application_revision_status + +begin; + +create or replace function ggircs_portal.create_application_revision_mutation_chain(application_id_input int, last_revision_id_input int) +returns ggircs_portal.application_revision +as $function$ +declare + new_version_number int; + form_result_id int; + current_reporting_year int; + temp_row record; + form_result jsonb; + init_function varchar(1000); + query text; + result ggircs_portal.application_revision; + facility_id_input int; + has_swrs_data boolean default false; +begin + new_version_number := last_revision_id_input + 1; + + -- Insert new row in application_revision + insert into ggircs_portal.application_revision(application_id, version_number) + values (application_id_input, new_version_number); + + select reporting_year from ggircs_portal.opened_reporting_year() into current_reporting_year; + if current_reporting_year is null then + raise exception 'The application window is closed'; + end if; + + -- Insert new value with application_id fk and version 1 into application_revision_status + insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) + values (application_id_input, new_version_number, 'draft'); + + select facility_id from ggircs_portal.application where id = application_id_input into facility_id_input; + + for temp_row in + select form_id from ggircs_portal.ciip_application_wizard + loop + -- Populate new revision of form_results with data from previous result on new revision creation + if last_revision_id_input > 0 then + select fr.form_result from ggircs_portal.form_result fr + where fr.form_id = temp_row.form_id + and fr.application_id = application_id_input + and fr.version_number=last_revision_id_input + into form_result; + + else + -- Populate initial version of application form results with data from swrs or empty results + if ((select fj.name from ggircs_portal.form_json as fj where temp_row.form_id = fj.id) in ('Production', 'fuel')) then + form_result='[{}]'; + else + form_result = '{}'; + end if; + if (select prepopulate_from_swrs from ggircs_portal.form_json where id = temp_row.form_id) then + select form_result_init_function from ggircs_portal.form_json where id = temp_row.form_id into init_function; + if (init_function is not null) then + query := format('select * from ggircs_portal.%I($1, $2);', init_function); + execute query + using facility_id_input, current_reporting_year + into form_result; + end if; + end if; + + end if; + + -- loop over what is in the wizard, not the forms in case some forms get added/disabled etc + insert into ggircs_portal.form_result(form_id, application_id, version_number, form_result) + values (temp_row.form_id, application_id_input, new_version_number, form_result) returning id into form_result_id; + + if last_revision_id_input = 0 then + -- Create form result statuses + insert into ggircs_portal.form_result_status(application_id, form_id, form_result_status) + values (application_id_input, temp_row.form_id, 'in review'); + end if; + + end loop; + + -- If the application's facility has a report_id then there is a swrs report. + if (exists(select id from ggircs_portal.facility where id=facility_id_input and report_id is not null) + and last_revision_id_input = 0) then + has_swrs_data := true; + end if; + + -- Create a duplicate revision 'version 0' with form_results if has_swrs_data = true; + if (has_swrs_data) then + insert into ggircs_portal.application_revision(application_id, version_number) + values (application_id_input, 0); + insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) + values (application_id_input, 0, 'submitted'); + for temp_row in + select form_id from ggircs_portal.ciip_application_wizard + loop + insert into ggircs_portal.form_result(form_id, application_id, version_number, form_result) + values (temp_row.form_id, application_id_input, 0, (select fr.form_result + from ggircs_portal.form_result fr + where fr.application_id = application_id_input + and fr.form_id = temp_row.form_id + and fr.version_number = 1)); + end loop; + end if; + + select * from ggircs_portal.application_revision where application_id = application_id_input and version_number = new_version_number into result; + return result; +end; +$function$ language plpgsql strict volatile; + +grant execute on function ggircs_portal.create_application_revision_mutation_chain to ciip_administrator, ciip_analyst, ciip_industry_user; + +commit; diff --git a/schema/deploy/trigger_functions/ensure_window_open_submit_application_status.sql b/schema/deploy/trigger_functions/ensure_window_open_submit_application_status.sql index f7c91e3723..30f1d5435c 100644 --- a/schema/deploy/trigger_functions/ensure_window_open_submit_application_status.sql +++ b/schema/deploy/trigger_functions/ensure_window_open_submit_application_status.sql @@ -5,7 +5,7 @@ begin; create or replace function ggircs_portal_private.ensure_window_open_submit_application_status() returns trigger as $$ begin - if (select reporting_year from ggircs_portal.opened_reporting_year()) is null then + if (select reporting_year from ggircs_portal.opened_reporting_year()) is null and new.version_number <= 1 then if (new.application_revision_status = 'submitted') then raise exception 'You cannot submit an application when the application window is closed'; end if; @@ -19,6 +19,6 @@ create or replace function ggircs_portal_private.ensure_window_open_submit_appli grant execute on function ggircs_portal_private.ensure_window_open_submit_application_status to ciip_administrator, ciip_analyst, ciip_industry_user; -comment on function ggircs_portal_private.ensure_window_open_submit_application_status is 'a trigger function that throws an exception if the application window is not opened and the new status is either "draft" or "submitted"'; +comment on function ggircs_portal_private.ensure_window_open_submit_application_status is 'a trigger function that throws an exception if the application window is not opened, the application version number is <= 1, and the new status is either "draft" or "submitted"'; commit; diff --git a/schema/deploy/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql b/schema/deploy/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql new file mode 100644 index 0000000000..f7c91e3723 --- /dev/null +++ b/schema/deploy/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql @@ -0,0 +1,24 @@ +-- Deploy ggircs-portal:trigger_functions/ensure_window_open_submit_application_status to pg + +begin; + +create or replace function ggircs_portal_private.ensure_window_open_submit_application_status() + returns trigger as $$ + begin + if (select reporting_year from ggircs_portal.opened_reporting_year()) is null then + if (new.application_revision_status = 'submitted') then + raise exception 'You cannot submit an application when the application window is closed'; + end if; + if (new.application_revision_status = 'draft') then + raise exception 'You cannot start a draft when the application window is closed'; + end if; + end if; + return new; + end; + $$ language plpgsql; + +grant execute on function ggircs_portal_private.ensure_window_open_submit_application_status to ciip_administrator, ciip_analyst, ciip_industry_user; + +comment on function ggircs_portal_private.ensure_window_open_submit_application_status is 'a trigger function that throws an exception if the application window is not opened and the new status is either "draft" or "submitted"'; + +commit; diff --git a/schema/revert/mutations/create_application_revision_mutation_chain.sql b/schema/revert/mutations/create_application_revision_mutation_chain.sql index 46d6dd93e4..ddba67b062 100644 --- a/schema/revert/mutations/create_application_revision_mutation_chain.sql +++ b/schema/revert/mutations/create_application_revision_mutation_chain.sql @@ -1,7 +1,111 @@ --- Revert ggircs-portal:function_create_application_revision_mutation_chain from pg +-- Deploy ggircs-portal:function_create_application_revision_mutation_chain to pg +-- requires: table_application_revision_status begin; -drop function ggircs_portal.create_application_revision_mutation_chain; +create or replace function ggircs_portal.create_application_revision_mutation_chain(application_id_input int, last_revision_id_input int) +returns ggircs_portal.application_revision +as $function$ +declare + new_version_number int; + form_result_id int; + current_reporting_year int; + temp_row record; + form_result jsonb; + init_function varchar(1000); + query text; + result ggircs_portal.application_revision; + facility_id_input int; + has_swrs_data boolean default false; +begin + new_version_number := last_revision_id_input + 1; + + -- Insert new row in application_revision + insert into ggircs_portal.application_revision(application_id, version_number) + values (application_id_input, new_version_number); + + select reporting_year from ggircs_portal.opened_reporting_year() into current_reporting_year; + if current_reporting_year is null then + raise exception 'The application window is closed'; + end if; + + -- Insert new value with application_id fk and version 1 into application_revision_status + insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) + values (application_id_input, new_version_number, 'draft'); + + select facility_id from ggircs_portal.application where id = application_id_input into facility_id_input; + + for temp_row in + select form_id from ggircs_portal.ciip_application_wizard + loop + -- Populate new revision of form_results with data from previous result on new revision creation + if last_revision_id_input > 0 then + select fr.form_result from ggircs_portal.form_result fr + where fr.form_id = temp_row.form_id + and fr.application_id = application_id_input + and fr.version_number=last_revision_id_input + into form_result; + + else + -- Populate initial version of application form results with data from swrs or empty results + if ((select fj.name from ggircs_portal.form_json as fj where temp_row.form_id = fj.id) in ('Production', 'fuel')) then + form_result='[{}]'; + else + form_result = '{}'; + end if; + if (select prepopulate_from_swrs from ggircs_portal.form_json where id = temp_row.form_id) then + select form_result_init_function from ggircs_portal.form_json where id = temp_row.form_id into init_function; + if (init_function is not null) then + query := format('select * from ggircs_portal.%I($1, $2);', init_function); + execute query + using facility_id_input, current_reporting_year + into form_result; + end if; + end if; + + end if; + + -- loop over what is in the wizard, not the forms in case some forms get added/disabled etc + insert into ggircs_portal.form_result(form_id, application_id, version_number, form_result) + values (temp_row.form_id, application_id_input, new_version_number, form_result) returning id into form_result_id; + + if last_revision_id_input = 0 then + -- Create form result statuses + insert into ggircs_portal.form_result_status(application_id, form_id, form_result_status) + values (application_id_input, temp_row.form_id, 'in review'); + end if; + + end loop; + + -- If the application's facility has a report_id then there is a swrs report. + if (exists(select id from ggircs_portal.facility where id=facility_id_input and report_id is not null) + and last_revision_id_input = 0) then + has_swrs_data := true; + end if; + + -- Create a duplicate revision 'version 0' with form_results if has_swrs_data = true; + if (has_swrs_data) then + insert into ggircs_portal.application_revision(application_id, version_number) + values (application_id_input, 0); + insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) + values (application_id_input, 0, 'submitted'); + for temp_row in + select form_id from ggircs_portal.ciip_application_wizard + loop + insert into ggircs_portal.form_result(form_id, application_id, version_number, form_result) + values (temp_row.form_id, application_id_input, 0, (select fr.form_result + from ggircs_portal.form_result fr + where fr.application_id = application_id_input + and fr.form_id = temp_row.form_id + and fr.version_number = 1)); + end loop; + end if; + + select * from ggircs_portal.application_revision where application_id = application_id_input and version_number = new_version_number into result; + return result; +end; +$function$ language plpgsql strict volatile; + +grant execute on function ggircs_portal.create_application_revision_mutation_chain to ciip_administrator, ciip_analyst, ciip_industry_user; commit; diff --git a/schema/revert/mutations/create_application_revision_mutation_chain@v1.5.0.sql b/schema/revert/mutations/create_application_revision_mutation_chain@v1.5.0.sql new file mode 100644 index 0000000000..46d6dd93e4 --- /dev/null +++ b/schema/revert/mutations/create_application_revision_mutation_chain@v1.5.0.sql @@ -0,0 +1,7 @@ +-- Revert ggircs-portal:function_create_application_revision_mutation_chain from pg + +begin; + +drop function ggircs_portal.create_application_revision_mutation_chain; + +commit; diff --git a/schema/revert/trigger_functions/ensure_window_open_submit_application_status.sql b/schema/revert/trigger_functions/ensure_window_open_submit_application_status.sql index ca62a508ee..f7c91e3723 100644 --- a/schema/revert/trigger_functions/ensure_window_open_submit_application_status.sql +++ b/schema/revert/trigger_functions/ensure_window_open_submit_application_status.sql @@ -1,7 +1,24 @@ --- Revert ggircs-portal:trigger_functions/ensure_window_open_submit_application_status from pg +-- Deploy ggircs-portal:trigger_functions/ensure_window_open_submit_application_status to pg begin; -drop function ggircs_portal_private.ensure_window_open_submit_application_status; +create or replace function ggircs_portal_private.ensure_window_open_submit_application_status() + returns trigger as $$ + begin + if (select reporting_year from ggircs_portal.opened_reporting_year()) is null then + if (new.application_revision_status = 'submitted') then + raise exception 'You cannot submit an application when the application window is closed'; + end if; + if (new.application_revision_status = 'draft') then + raise exception 'You cannot start a draft when the application window is closed'; + end if; + end if; + return new; + end; + $$ language plpgsql; + +grant execute on function ggircs_portal_private.ensure_window_open_submit_application_status to ciip_administrator, ciip_analyst, ciip_industry_user; + +comment on function ggircs_portal_private.ensure_window_open_submit_application_status is 'a trigger function that throws an exception if the application window is not opened and the new status is either "draft" or "submitted"'; commit; diff --git a/schema/revert/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql b/schema/revert/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql new file mode 100644 index 0000000000..ca62a508ee --- /dev/null +++ b/schema/revert/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql @@ -0,0 +1,7 @@ +-- Revert ggircs-portal:trigger_functions/ensure_window_open_submit_application_status from pg + +begin; + +drop function ggircs_portal_private.ensure_window_open_submit_application_status; + +commit; diff --git a/schema/sqitch.plan b/schema/sqitch.plan index 56a4784097..a2a755b8ae 100644 --- a/schema/sqitch.plan +++ b/schema/sqitch.plan @@ -183,3 +183,5 @@ search_functions/search_certification_requests [search_functions/search_certific policies/facility_policies [policies/facility_policies@v1.5.0] 2020-08-27T20:57:07Z Dylan Leard # Migration: make certifier_email comparison case insensitive @v1.6.1 2020-08-28T16:58:22Z Matthieu Foucault # release v1.6.1 search_functions/search_all_facilities [search_functions/search_all_facilities@v1.5.0] 2020-08-24T20:55:30Z Dylan Leard # Migration: allow function to filter on different reporting years +trigger_functions/ensure_window_open_submit_application_status [trigger_functions/ensure_window_open_submit_application_status@v1.5.0] 2020-08-24T17:54:35Z Matthieu Foucault # Applications can be started or submitted when the window is closed if version > 1 +mutations/create_application_revision_mutation_chain [mutations/create_application_revision_mutation_chain@v1.5.0] 2020-08-24T18:28:33Z Matthieu Foucault # allow revisions to be created when the window is closed if version_number > 1 diff --git a/schema/test/unit/mutations/create_application_revision_mutation_chain_test.sql b/schema/test/unit/mutations/create_application_revision_mutation_chain_test.sql index f8b19a0479..de424fc21c 100644 --- a/schema/test/unit/mutations/create_application_revision_mutation_chain_test.sql +++ b/schema/test/unit/mutations/create_application_revision_mutation_chain_test.sql @@ -3,7 +3,33 @@ create extension if not exists pgtap; reset client_min_messages; begin; -select plan(9); + +create or replace function open_application_window() returns void as +$fun$ + create or replace function ggircs_portal.current_timestamp() returns timestamptz as + $$ + select application_open_time + from ggircs_portal.reporting_year + order by reporting_year + limit 1 + offset 2; + $$ language sql; +$fun$language sql; + +create or replace function close_application_window() returns void as +$fun$ + -- Set the timestamp to a time where the application window is closed + create or replace function ggircs_portal.current_timestamp() returns timestamptz as + $$ + select application_open_time - interval '1 second' + from ggircs_portal.reporting_year + order by reporting_year + limit 1 + offset 2; + $$ language sql; +$fun$language sql; + +select plan(10); select has_function( 'ggircs_portal', 'create_application_revision_mutation_chain', array['integer', 'integer'], @@ -14,18 +40,11 @@ alter table ggircs_portal.application_revision_status disable trigger _status_ch alter table ggircs_portal.application disable trigger _send_draft_application_email; --- Set the timestamp to a time where the application window is open -create or replace function ggircs_portal.current_timestamp() returns timestamptz as -$$ - select application_open_time - from ggircs_portal.reporting_year - order by reporting_year - limit 1 - offset 2; -$$ language sql; +select open_application_window(); insert into ggircs_portal.organisation(operator_name) values ('test org'); insert into ggircs_portal.facility(organisation_id, facility_name) values (1, 'test facility'); +truncate ggircs_portal.application_revision restart identity cascade; select ggircs_portal.create_application_mutation_chain((select id from ggircs_portal.facility where facility_name = 'test facility')); @@ -137,26 +156,52 @@ select results_eq( 'If an application has a swrs report, the version 0 swrs revision has a default status of SUBMITTED' ); --- Set the timestamp to a time where the application window is closed -create or replace function ggircs_portal.current_timestamp() returns timestamptz as -$$ - select application_open_time - interval '1 second' - from ggircs_portal.reporting_year - order by reporting_year - limit 1 - offset 2; -$$ language sql; +select open_application_window(); +truncate ggircs_portal.application restart identity cascade; + +insert into ggircs_portal.application( + facility_id, + reporting_year, + report_id +) +values ( + (select id from ggircs_portal.facility where facility_name = 'test facility'), + (select reporting_year from ggircs_portal.opened_reporting_year()), + (select report_id from ggircs_portal.facility where facility_name = 'test facility') +); + +select close_application_window(); select throws_ok( $$ with app_id as ( select a.id from ggircs_portal.application a join ggircs_portal.facility f on a.facility_id = f.id and facility_name = 'test facility' - ) select ggircs_portal.create_application_revision_mutation_chain((select id from app_id), (select max(version_number) from ggircs_portal.application_revision where application_id = (select id from app_id))) + ) select ggircs_portal.create_application_revision_mutation_chain((select id from app_id), 0) $$, 'The application window is closed', - 'create_application_mutation_chain should throw an exception if the application window is closed' + 'create_application_mutation_chain should throw an exception if the application window is closed and the last version_number is 0' +); + +select open_application_window(); +with app_id as ( + select a.id from ggircs_portal.application a + join ggircs_portal.facility f on a.facility_id = f.id + and facility_name = 'test facility' +) select ggircs_portal.create_application_revision_mutation_chain((select id from app_id), 0); + +select close_application_window(); + +select lives_ok( + $$ + with app_id as ( + select a.id from ggircs_portal.application a + join ggircs_portal.facility f on a.facility_id = f.id + and facility_name = 'test facility' + ) select ggircs_portal.create_application_revision_mutation_chain((select id from app_id), 1) + $$, + 'create_application_mutation_chain should no throw an exception if the application window is closed and the last version_number is >= 1' ); select finish(); diff --git a/schema/test/unit/trigger_functions/ensure_window_open_submit_application_status_test.sql b/schema/test/unit/trigger_functions/ensure_window_open_submit_application_status_test.sql index b17312d223..1fc1120390 100644 --- a/schema/test/unit/trigger_functions/ensure_window_open_submit_application_status_test.sql +++ b/schema/test/unit/trigger_functions/ensure_window_open_submit_application_status_test.sql @@ -3,7 +3,7 @@ create extension if not exists pgtap; reset client_min_messages; begin; -select plan(6); +select plan(8); select has_function( 'ggircs_portal_private', 'ensure_window_open_submit_application_status', @@ -35,6 +35,16 @@ select throws_ok( 'The trigger throws an error if submitting an application when the application window is closed ' ); +select lives_ok( + $$insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) values (1, 2, 'draft')$$, + 'The trigger does not throw an error if starting a draft for a version > 1 when the application window is closed' +); + +select lives_ok( + $$insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) values (1, 2, 'submitted')$$, + 'The trigger does not throw an error if submitting an application for a version > 1 when the application window is closed ' +); + select lives_ok( $$insert into ggircs_portal.application_revision_status(application_id, version_number, application_revision_status) values (1, 1, 'approved')$$, 'The trigger does not throw when setting a status of approved' diff --git a/schema/verify/mutations/create_application_revision_mutation_chain@v1.5.0.sql b/schema/verify/mutations/create_application_revision_mutation_chain@v1.5.0.sql new file mode 100644 index 0000000000..762706ac86 --- /dev/null +++ b/schema/verify/mutations/create_application_revision_mutation_chain@v1.5.0.sql @@ -0,0 +1,7 @@ +-- Verify ggircs-portal:function_create_application_revision_mutation_chain on pg + +begin; + +select pg_get_functiondef('ggircs_portal.create_application_revision_mutation_chain(int, int)'::regprocedure); + +rollback; diff --git a/schema/verify/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql b/schema/verify/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql new file mode 100644 index 0000000000..b0af6057ee --- /dev/null +++ b/schema/verify/trigger_functions/ensure_window_open_submit_application_status@v1.5.0.sql @@ -0,0 +1,7 @@ +-- Verify ggircs-portal:trigger_functions/ensure_window_open_submit_application_status on pg + +begin; + +select pg_get_functiondef('ggircs_portal_private.ensure_window_open_submit_application_status()'::regprocedure); + +rollback;