first pass bankrec test - not run yet
authorGil Moskowitz <gmoskowitz@xtuple.com>
Fri, 27 Jun 2014 19:21:12 +0000 (15:21 -0400)
committerGil Moskowitz <gmoskowitz@xtuple.com>
Fri, 27 Jun 2014 19:21:12 +0000 (15:21 -0400)
test/database/bankrec.js [new file with mode: 0644]

diff --git a/test/database/bankrec.js b/test/database/bankrec.js
new file mode 100644 (file)
index 0000000..9e80904
--- /dev/null
@@ -0,0 +1,384 @@
+/*jshint trailing:true, white:true, indent:2, strict:true, curly:true,
+  immed:true, eqeqeq:true, forin:true, latedef:true,
+  newcap:true, noarg:true, undef:true */
+/*global XT:true, describe:true, it:true, require:true, __dirname:true, before:true */
+
+var _    = require("underscore"),
+  assert = require('chai').assert,
+  path   = require('path');
+
+(function () {
+  "use strict";
+
+  describe('test bank reconciliation functions', function () {
+
+    var loginData = require("../lib/login_data.js").data,
+      datasource = require('../../../xtuple/node-datasource/lib/ext/datasource').dataSource,
+      config = require(path.join(__dirname, "../../node-datasource/config.js")),
+      creds  = _.extend({}, config.databaseServer, {database: loginData.org}),
+      bankaccnt,
+      bankrec,
+      trans1 = { amount: 98.76 },
+      trans2 = { amount: 54.32 },
+      bankRecItemSql = 'SELECT * FROM bankrecitem '             +
+                       ' WHERE bankrecitem_bankrec_id=:brid'    +
+                       '   AND bankrecitem_source_id=:srcid'    +
+                       '   AND bankrecitem_source=:src;',
+      toggleCheckSql = "SELECT toggleBankRecCleared(:bankrec_id,'A/R'"         +
+                       ", gltrans_id, checkhead_curr_rate, checkhead_amount)"  +
+                       "  AS result"                                           +
+                       " FROM checkhead JOIN gltrans ON (gltrans_doctype='CK'" +
+                       "                    AND gltrans_misc_id=checkhead_id)" +
+                       " WHERE checkhead_id=:checkid;",
+      checkCheckSql = "SELECT *,"
+                      "       bankrecitem_amount/bankrecitem_curr_rate AS base"+
+                      " JOIN bankrecitem ON (gltrans_id=bankrecitem_source_id)"+
+                      " JOIN bankrec    ON (bankrecitem_bankrec_id=bankrec_id)"+
+                      " WHERE gltrans_doctype='CK'"                            +
+                      "   AND gltrans_misc_id=:checkid"                        +
+                      "   AND bankrec_id=:bankrec_id;",
+      bankAdjCheckSql = "SELECT *,"
+                    " ABS(bankadj_amount / bankadj_curr_rate) AS baseamt"      +
+                    "  FROM bankadj LEFT OUTER"                                +
+                    "  JOIN bankaccnt ON (bankadj_bankaccnt_id=bankaccnt_id)"  +
+                    "  LEFT OUTER"                                             +
+                    "  JOIN gltrans   ON (bankaccnt_accnt_id=gltrans_accnt_id" +
+                    "                 AND gltrans_doctype='AD'"                +
+                    "                 AND gltrans_notes ~ bankadj_notes"       +
+                    "                 AND gltrans_docnumber=bankadj_docnumber)"+
+                    "  LEFT OUTER"                                             +
+                    "  JOIN bankrecitem ON (bankrec_source='G/L' "             +
+                    "                   AND bankrec_source_id=gltrans_id)"     +
+                    " WHERE bankadj_id=:bankadjid;" // TODO: precise enough?
+      ;
+
+    it('looks for a bank account with no open reconciliations', function (done) {
+      var sql = 'SELECT * FROM bankaccnt WHERE bankaccnt_id IN ('       +
+                '   SELECT bankrec_bankaccnt_id FROM bankrec'           +
+                '   GROUP BY bankrec_bankaccnt_id'                      +
+                '   HAVING BOOL_AND(bankrec_posted)) LIMIT 1;'
+                ;
+      datasource.query(sql, creds, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        bankaccnt = _.clone(res.rows[0]);
+        assert.isNotNull(bankaccnt, 'we found a bank account');
+        done();
+      });
+    });
+
+    it('creates a new open bankrec to test with', function (done) {
+      var sql = 'INSERT INTO bankrec (bankrec_bankaccnt_id,'    +
+                '  bankrec_opendate, bankrec_openbal'           +
+                ') SELECT bankrec_bankaccnt_id,'                +
+                '         bankrec_enddate + 1, bankrec_endbal'  +
+                '    FROM bankrec'                              +
+                '   WHERE bankrec_bankaccnt_id=' + bankaccnt.bankaccnt_id +
+                '     AND bankrec_posted'                       +
+                '   ORDER BY bankrec_enddate DESC'              +
+                '   LIMIT 1 RETURNING *;'
+                ;
+      datasource.query(sql, creds, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        bankrec = _.clone(res.rows[0]);
+        assert.isNotNull(bankrec,              'we have a bank rec');
+        assert.isFalse(bankrec.bankrec_posted, 'we have an open bank rec');
+        done();
+      });
+    });
+
+    it('creates a check as the 1st transaction to reconcile', function (done) {
+      var sql = "SELECT createCheck(" + bankaccnt.bankaccnt_id               +
+                "'V', (SELECT MIN(vend_id) FROM vendinfo), '"                +
+                bankrec.bankrec_opendate + "' + 1, " + trans1.amount + ", "  +
+                bankaccnt.bankaccnt_curr_id + ", NULL, NULL, 'Bearer',"      +
+                ", 'bankrec test 1', TRUE, NULL) RETURNING checkid;"
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].checkid > 0);
+        trans1.checkid = res.row[0].checkid;
+        done();
+      });
+    });
+
+    it('posts the check', function (done) {
+      var sql = 'SELECT postCheck(' + trans1.checkid + ', NULL) AS result;';
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].result > 0);
+        trans1.journalNumber = res.row[0].result;
+        done();
+      });
+    });
+
+    it('marks the check as cleared', function (done) {
+      var sql = _.clone(toggleCheckSql)
+                 .replace(':bankrec_id', bankrec.bankrec_id)
+                 .replace(':checkid',    trans1.checkid);
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].result);
+        done();
+      });
+    });
+
+    it('confirms the check was marked as cleared', function (done) {
+      var sql = _.clone(bankRecItemSql)
+                 .replace(':brid', bankrec.bankrec_id)
+                 .replace(':src', 'A/R')
+                 .replace('=:srcid',
+                          " IN (SELECT gltrans_id FROM gltrans WHERE"  +
+                          " gltrans_doctype='CK' AND gltrans_misc_id=" +
+                          trans1.checkid)
+                 ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].bankrecitem_cleared);
+        assert(res.row[0].bankrecitem_cleared);
+        done();
+      });
+    });
+
+    it('marks the check as /not/ cleared', function (done) {
+      var sql = _.clone(toggleCheckSql)
+                 .replace(':bankrec_id', bankrec.bankrec_id)
+                 .replace(':checkid',    trans1.checkid);
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isFalse(res.row[0].result);
+        done();
+      });
+    });
+
+    it('confirms the check is no longer marked as cleared', function (done) {
+      var sql = _.clone(bankRecItemSql)
+                 .replace(':brid', bankrec.bankrec_id)
+                 .replace(':src', 'A/R')
+                 .replace('=:srcid',
+                          " IN (SELECT gltrans_id FROM gltrans WHERE"  +
+                          " gltrans_doctype='CK' AND gltrans_misc_id=" +
+                          trans1.checkid)
+                 ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 0);
+        done();
+      });
+    });
+
+    it('marks the check as cleared again', function (done) {
+      var sql = _.clone(toggleCheckSql)
+                .replace(':bankrec_id', bankrec.bankrec_id)
+                .replace(':checkid',    trans1.checkid)
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].result);
+        done();
+      });
+    });
+
+    it('confirms that the check is marked as cleared again', function (done) {
+      var sql = bankRecItemSql.replace(':brid', bankrec.bankrec_id)
+                              .replace(':src', 'A/R')
+                              .replace('=:srcid',
+                                       " IN (SELECT gltrans_id FROM gltrans" +
+                                       " WHERE gltrans_doctype='CK' AND "
+                                       " gltrans_misc_id=" + trans1.checkid)
+                              ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].bankrecitem_cleared);
+        assert(res.row[0].bankrecitem_cleared);
+        done();
+      });
+    });
+
+    it('creates a bank adjustment as a second transaction', function (done) {
+      var sql = "INSERT INTO bankadj ("                                      +
+                " bankadj_bankaccnt_id, bankadj_bankadjtype_id,"             +
+                " bankadj_date, bankadj_docnumber,"                          +
+                " bankadj_amount, bankadj_notes, bankadj_curr_id"            +
+                ") SELECT " + bankaccnt.bankaccnt_id + ", bankadjtype_id, '" +
+                bankrec.bankrec_opendate + "' + 1, 'BankRecTest', "          +
+                trans2.amount + ", 'Bank Rec Test Transaction 2', "          +
+                bankaccnt.bankaccnt_curr_id                                  +
+                "    FROM bankadjtype RETURNING *;"
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        _.extend(trans2, res.rows[0]);
+        assert.isOk(trans2.bankadj_id, 'we have a bank adjustment');
+        done();
+      });
+    });
+
+    it('posts the reconciliation', function (done) {
+      var sql = 'SELECT postBankReconciliation(' + bankrec.bankrec_id +
+                ') AS result;'
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.equal(res.row[0].result, bankrec.bankrec_id);
+        done();
+      });
+    });
+
+    it('confirms the check was reconciled properly', function (done) {
+      var sql = _.clone(checkCheckSql)
+                 .replace(':checkid', trans1.checkid)
+                 .replace(':bankrecid', bankrec.bankrec_id)
+                 ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].gltrans_rec);
+        assert.isTrue(res.row[0].bankrec_posted);
+        done();
+      });
+    });
+
+    // TODO: confirm the CashBasedTax reconciliation code worked
+
+    it('confirms the bank adjustment was /not/ posted', function (done) {
+      sql = _.clone(bankAdjCheckSql).replace(':bankadjid', trans2.bankadj_id);
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isFalse(res.row[0].bankadj_posted);
+        assert.notOk(res.row[0].gltrans_id);
+        assert.notOk(res.row[0].bankrecitem_id);
+        done();
+      });
+    });
+
+    it('reopens the reconcilation', function (done) {
+      var sql = 'SELECT reopenBankReconciliation(' + bankrec.bankrec_id +
+                ') AS result;'
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.equal(res.row[0].result, bankrec.bankrec_id);
+        done();
+      });
+    });
+
+    it('confirms the check was handled properly by the reopen', function (done) {
+      var sql = _.clone(checkCheckSql)
+                 .replace(':checkid', trans1.checkid)
+                 .replace(':bankrecid', bankrec.bankrec_id)
+                 ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isFalse(res.row[0].gltrans_rec);
+        assert.isFalse(res.row[0].bankrec_posted);
+        assert.closeTo(Math.abs(res.row[0].gltrans_amount), res.row[0].base,
+                       0.001);
+        done();
+      });
+    });
+
+    // TODO: confirm the CashBasedTax reconciliation code worked
+
+    it('marks the bank adjustment as cleared', function (done) {
+      var sql = "SELECT toggleBankRecCleared(" + bankrec.bankrec_id         +
+                ", 'G/L', gltrans_id, bankadj_curr_rate,"                   +
+                "  bankadj_amount) AS result"                               +
+                " FROM bankadj JOIN gltrans"                                +
+                " ON (gltrans_doctype='AD' AND gltrans_misc_id=bankadj_id)" +
+                " WHERE bankadj_id=" + trans2.bankadj_id + ";"
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].result);
+        done();
+      });
+    });
+
+    it('confirms the bank adjustment was /not/ posted but is cleared', function (done) {
+      sql = _.clone(bankAdjCheckSql).replace(':bankadjid', trans2.bankadj_id);
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isFalse(res.row[0].bankadj_posted);
+        assert(res.row[0].bankrecitem_id >= 0);
+        done();
+      });
+    });
+
+    it('posts the reconciliation again', function (done) {
+      var sql = 'SELECT postBankReconciliation(' + bankrec.bankrec_id +
+                ') AS result;'
+                ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.equal(res.row[0].result, bankrec.bankrec_id);
+        done();
+      });
+    });
+
+    it('confirms the check was reconciled properly', function (done) {
+      var sql = _.clone(checkCheckSql)
+                 .replace(':checkid', trans1.checkid)
+                 .replace(':bankrecid', bankrec.bankrec_id)
+                 ;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].gltrans_rec);
+        assert.isTrue(res.row[0].bankrec_posted);
+        done();
+      });
+    });
+
+    // TODO: confirm the CashBasedTax reconciliation code worked
+
+    it('confirms the bank adjustment was cleared, posted, written to the GL', function (done) {
+      sql = _.clone(bankAdjCheckSql).replace(':bankadjid', trans2.bankadj_id);
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert.isTrue(res.row[0].bankadj_posted);
+        assert(res.row[0].bankadj_sequence >= 0);
+        assert.isTrue(res.row[0].gltrans_rec);
+        assert.closeTo(Math.abs(res.row[0].gltrans_amount), res.row[0].baseamt,
+                       0.001);
+        done();
+      });
+    });
+
+    it('deletes the bankrec', function (done) {
+      var sql = 'SELECT deleteBankReconciliation(' + bankrec.bankrec_id +
+                ') AS result;';
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].result >= 0);
+        done();
+      });
+    });
+
+    it('checks that the bankrec is really gone', function (done) {
+      var sql = 'SELECT COUNT(*) FROM bankrec WHERE bankrec_id = ' +
+                bankrec.bankrec_id;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].result === 0);
+        done();
+      });
+    });
+
+    it('checks that the bankrecitems are gone', function (done) {
+      var sql = 'SELECT COUNT(*) FROM bankrecitem'
+                ' WHERE bankrecitem_bankrec_id = ' + bankrec.bankrec_id;
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].result === 0);
+        done();
+      });
+    });
+
+    it('tries to delete a non-existent bankrec', function (done) {
+      var sql = 'SELECT deleteBankReconciliation(-15) AS result;';
+      datasource.query(sql, cred, function (err, res) {
+        assert.equal(res.rowCount, 1);
+        assert(res.row[0].result === 0); // no, it doesn't complain
+        done();
+      });
+    });
+
+  });
+}());