BEGIN;

    -- Load the TAP functions.
    CREATE EXTENSION pgtap;

    -- Plan the tests.

    SELECT plan(62);

    -- Add data

    \i sql/modules/test/Base.sql
    \i sql/modules/test/data/Reconciliation.sql

    -- Validate required tables

    SELECT has_table('cr_report');
    SELECT has_table('cr_report_line');
    SELECT has_table('cr_coa_to_account');

    -- Validate required view

    SELECT has_view('recon_payee');

    -- Validate required triggers

    SELECT has_trigger('cr_report','block_change_when_approved');

    -- Validate required functions

    SELECT has_function('cr_report_block_changing_approved','{}'::text[]);
    SELECT has_function('reconciliation__account_list','{}'::text[]);
    SELECT has_function('reconciliation__add_entry',array['integer', 'text', 'text', 'timestamp without time zone', 'numeric']);
    SELECT has_function('reconciliation__check',array['date', 'integer']);
    SELECT has_function('reconciliation__delete_my_report',array['integer']);
    SELECT has_function('reconciliation__delete_unapproved',array['integer']);
    SELECT has_function('reconciliation__get_cleared_balance',array['integer', 'date']);
    SELECT has_function('reconciliation__get_current_balance',array['integer', 'date']);
    SELECT has_function('reconciliation__new_report_id',array['integer', 'numeric', 'date', 'boolean']);
    SELECT has_function('reconciliation__pending_transactions',array['integer', 'numeric']);
    SELECT has_function('reconciliation__previous_report_date',ARRAY['integer','date']);
    SELECT has_function('reconciliation__reject_set',array['integer']);
    SELECT has_function('reconciliation__report_approve',array['integer']);
    SELECT has_function('reconciliation__report_details',array['integer']);
    SELECT has_function('reconciliation__report_details_payee',array['integer']);
    SELECT has_function('reconciliation__report_details_payee_with_days',array['integer', 'date']);
    SELECT has_function('reconciliation__report_summary',array['integer']);
    SELECT has_function('reconciliation__save_set',array['integer', 'integer[]']);
    SELECT has_function('reconciliation__search',array['date', 'date', 'numeric', 'numeric', 'integer', 'boolean', 'boolean']);
    SELECT has_function('reconciliation__submit_set',array['integer', 'integer[]']);

    -- Run tests

--    PREPARE test AS SELECT count(*)
--                      FROM defaults
--                      WHERE setting_key = 'check_prefix';
--    SELECT results_eq('test',ARRAY[1],'check_prefix set');

--    UPDATE defaults
--    SET value = 'Recon gl test '
--    WHERE setting_key = 'check_prefix';

    CREATE TEMPORARY TABLE test_parameters (id int);
    INSERT INTO test_parameters(id) VALUES(nextval('cr_report_id_seq'));

    PREPARE test AS SELECT COUNT(*)::INT FROM acc_trans
                    WHERE cleared
                    AND entry_id NOT IN (SELECT ledger_id FROM cr_report_line);
    SELECT results_eq('test', Array[4], 'Transactions that should be in cr_report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__previous_report_date(test_get_account_id('-11111'), now()::date);
    SELECT results_eq('test', ARRAY[]::cr_report[], 'No previous report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__new_report_id(test_get_account_id('-11111'), 100, '1001-01-01', false);
    SELECT results_eq('test', $$ SELECT id+1 FROM test_parameters $$, 'Create Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__delete_my_report(currval('cr_report_id_seq')::int);
    SELECT results_eq('test',ARRAY[true],'Delete Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__previous_report_date(test_get_account_id('-11111'), now()::date);
    SELECT results_eq('test', ARRAY[]::cr_report[], 'Deleted previous report doesn''t show up');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__new_report_id(test_get_account_id('-11111'), 100, '1001-01-01', false);
    SELECT results_eq('test', $$ SELECT id+2 FROM test_parameters $$, 'Create Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__pending_transactions(currval('cr_report_id_seq')::int, 110) > 0;
    SELECT results_eq('test',ARRAY[true],'Pending Transactions Ran');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',Array[10],'Correct number of transactions 1');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE scn LIKE '% gl %'
                      AND report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test', ARRAY[3], 'Correct number of GL groups');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[10],'Correct number of report lines');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__submit_set(currval('cr_report_id_seq')::int, (select as_array(id::int) from cr_report_line where report_id = currval('cr_report_id_seq')::int));
    SELECT results_eq('test',ARRAY[true],'Report Submitted');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__previous_report_date(test_get_account_id('-11111'), '1001-01-01');
    SELECT results_eq('test', ARRAY[]::cr_report[], 'No previous report before 1001-01-01');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__report_approve(currval('cr_report_id_seq')::int) > 0;
    SELECT results_eq('test',ARRAY[true],'1 Report Approved');
    DEALLOCATE test;

    PREPARE test AS SELECT end_date FROM reconciliation__previous_report_date(test_get_account_id('-11111'), '1001-01-02');
    SELECT results_eq('test', ARRAY['1001-01-01']::date[], 'One previous report at 1001-01-01');
    DEALLOCATE test;

    PREPARE test as SELECT count(*)::int
                      FROM acc_trans
                      JOIN account a ON (acc_trans.chart_id = a.id)
                      WHERE a.accno = '-11111'
                      AND NOT cleared;
    SELECT results_eq('test',ARRAY[2],'1 Transactions closed');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__new_report_id(test_get_account_id('-11112'), 100, now()::date, false) > 0;
    SELECT results_eq('test',ARRAY[true],'1 Create Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__pending_transactions(currval('cr_report_id_seq')::int, 110) > 0;
    SELECT results_eq('test',ARRAY[true],'1 Pending Transactions Ran');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[10],'Correct number of transactions 2');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__pending_transactions(currval('cr_report_id_seq')::int, 110);
    SELECT results_eq('test',$$ SELECT id+3 FROM test_parameters $$,'1 Pending Transactions Ran');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[10],'Correct number of transactions 3');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE scn like '% gl %'
                      AND report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[3],'1 Correct number of GL groups');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[10],'1 Correct number of report lines');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__submit_set(currval('cr_report_id_seq')::int, '{}');
    SELECT results_eq('test',ARRAY[true],'1 Report Submitted');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__get_cleared_balance(test_get_account_id('-11112')) = -10;
    SELECT results_eq('test',ARRAY[true],'1 Cleared balance pre-approval is 10');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__report_approve(currval('cr_report_id_seq')::int) > 0;
    SELECT results_eq('test',ARRAY[true],'1 Report Approved');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM acc_trans
                      JOIN account ON (acc_trans.chart_id = account.id)
                      WHERE accno = '-11112'
                      AND NOT cleared;
    SELECT results_eq('test',ARRAY[14],'1 Transactions open');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__get_cleared_balance(test_get_account_id('-11112')) = -10;
    SELECT results_eq('test',ARRAY[true],'1 Cleared balance post-approval is 10');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__new_report_id(test_get_account_id('-11112'), 100, now()::date, false);
    SELECT results_eq('test',$$ SELECT id+4 FROM test_parameters $$,'1 Create Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__pending_transactions(currval('cr_report_id_seq')::int, 110);
    SELECT results_eq('test',$$ SELECT id+4 FROM test_parameters $$,'1 Pending Transactions Ran');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int;
    SELECT results_eq('test',ARRAY[10],'Correct number of transactions 4');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__submit_set(currval('cr_report_id_seq')::int, (select as_array(id::int)
                      FROM cr_report_line
                      WHERE report_id = currval('cr_report_id_seq')::int));
    SELECT results_eq('test',ARRAY[true],'Report Submitted');
    DEALLOCATE test;

    PREPARE test AS SELECT their_total::int
                      FROM reconciliation__report_summary(currval('cr_report_id_seq')::int);
    SELECT results_eq('test',ARRAY[110],'Their Balance Updated');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__get_cleared_balance(test_get_account_id('-11112'))= -10;
    SELECT results_eq('test',ARRAY[true],'Cleared balance pre-approval is 10');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__report_approve(currval('cr_report_id_seq')::int) > 0;
    SELECT results_eq('test',ARRAY[true],'Report Approved');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__delete_my_report(currval('cr_report_id_seq')::int) IS NULL;
    -- Should we thrown an exception?
    SELECT results_eq('test',ARRAY[true],'Cannot Delete Approved Recon Report');
    DEALLOCATE test;

    PREPARE test AS SELECT count(*)::int
                      FROM acc_trans
                      JOIN account a ON (acc_trans.chart_id = a.id)
                      WHERE accno = '-11112'
                      AND NOT cleared;
    SELECT results_eq('test',ARRAY[2],'Transactions closed');
    DEALLOCATE test;

    PREPARE test AS SELECT reconciliation__get_cleared_balance(test_get_account_id('-11112'));
    SELECT results_eq('test',ARRAY[-130.],'Cleared balance post-approval is 130');
    DEALLOCATE test;

    -- Finish the tests and clean up.
    SELECT * FROM finish();

ROLLBACK;
