@churchsoln/dbms 1.0.57 → 1.0.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -64,6 +64,25 @@ const NORMAL_BALANCE = {
64
64
  CREDIT: "Credit",
65
65
  };
66
66
 
67
+ const JOURNAL_ENTRY_SOURCE_TYPE = {
68
+ MANUAL: "Manual",
69
+ CONTRIBUTION: "Contribution",
70
+ PLEDGE: "Pledge",
71
+ BILL: "Bill",
72
+ BILL_PAYMENT: "BillPayment",
73
+ INVOICE: "Invoice",
74
+ RECEIPT: "Receipt",
75
+ PAYROLL: "Payroll",
76
+ BANK_DEPOSIT: "BankDeposit",
77
+ BANK_TRANSFER: "BankTransfer",
78
+ OPENING_BALANCE: "OpeningBalance",
79
+ ADJUSTMENT: "Adjustment",
80
+ };
81
+
82
+ const JOURNAL_ENTRY_STATUS = {
83
+ POSTED: "posted",
84
+ };
85
+
67
86
  const ACCOUNTING_ACCOUNT_TYPES = {
68
87
  ASSET: { name: "Asset", normalBalance: NORMAL_BALANCE.DEBIT },
69
88
  LIABILITY: { name: "Liability", normalBalance: NORMAL_BALANCE.CREDIT },
@@ -231,4 +250,6 @@ module.exports = {
231
250
  NORMAL_BALANCE,
232
251
  ACCOUNTING_ACCOUNT_TYPES,
233
252
  CHART_OF_ACCOUNTS,
253
+ JOURNAL_ENTRY_SOURCE_TYPE,
254
+ JOURNAL_ENTRY_STATUS,
234
255
  };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ module.exports = {
3
+ up: async (queryInterface, DataTypes) => {
4
+ await queryInterface
5
+ .createTable(
6
+ "JournalEntry",
7
+ {
8
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
9
+ entryDate: { type: DataTypes.DATEONLY, allowNull: false },
10
+ sourceType: { type: DataTypes.STRING, allowNull: true },
11
+ contributionTransactionId: { type: DataTypes.INTEGER, allowNull: true },
12
+ description: { type: DataTypes.TEXT, allowNull: true },
13
+ status: { type: DataTypes.STRING, defaultValue: "posted" },
14
+ createdAt: {
15
+ type: DataTypes.DATE,
16
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
17
+ },
18
+ updatedAt: {
19
+ type: DataTypes.DATE,
20
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
21
+ },
22
+ },
23
+ { timestamps: false }
24
+ )
25
+ .then(() =>
26
+ queryInterface.addConstraint("JournalEntry", {
27
+ fields: ["contributionTransactionId"],
28
+ type: "foreign key",
29
+ name: "JournalEntry_ContributionTransactionId_Fkey",
30
+ references: {
31
+ table: "ContributionTransaction",
32
+ field: "id",
33
+ },
34
+ onDelete: "restrict",
35
+ onUpdate: "cascade",
36
+ })
37
+ );
38
+ },
39
+ down: async (queryInterface) => {
40
+ await queryInterface.dropTable("JournalEntry");
41
+ },
42
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ module.exports = {
3
+ up: async (queryInterface, DataTypes) => {
4
+ await queryInterface
5
+ .createTable(
6
+ "JournalEntryLine",
7
+ {
8
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
9
+ journalEntryId: { type: DataTypes.INTEGER, allowNull: false },
10
+ chartOfAccountId: { type: DataTypes.INTEGER, allowNull: false },
11
+ debit: { type: DataTypes.DECIMAL(10, 2), defaultValue: 0 },
12
+ credit: { type: DataTypes.DECIMAL(10, 2), defaultValue: 0 },
13
+ memo: { type: DataTypes.TEXT, allowNull: true },
14
+ createdAt: {
15
+ type: DataTypes.DATE,
16
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
17
+ },
18
+ updatedAt: {
19
+ type: DataTypes.DATE,
20
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
21
+ },
22
+ },
23
+ { timestamps: false }
24
+ )
25
+ .then(() =>
26
+ queryInterface.addConstraint("JournalEntryLine", {
27
+ fields: ["journalEntryId"],
28
+ type: "foreign key",
29
+ name: "JournalEntryLine_JournalEntryId_Fkey",
30
+ references: {
31
+ table: "JournalEntry",
32
+ field: "id",
33
+ },
34
+ onDelete: "cascade",
35
+ onUpdate: "cascade",
36
+ })
37
+ )
38
+ .then(() =>
39
+ queryInterface.addConstraint("JournalEntryLine", {
40
+ fields: ["chartOfAccountId"],
41
+ type: "foreign key",
42
+ name: "JournalEntryLine_ChartOfAccountId_Fkey",
43
+ references: {
44
+ table: "ChartOfAccounts",
45
+ field: "id",
46
+ },
47
+ onDelete: "restrict",
48
+ onUpdate: "cascade",
49
+ })
50
+ );
51
+ },
52
+ down: async (queryInterface) => {
53
+ await queryInterface.dropTable("JournalEntryLine");
54
+ },
55
+ };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ module.exports = {
3
+ up: async (queryInterface, DataTypes) => {
4
+ await queryInterface
5
+ .createTable(
6
+ "FiscalYears",
7
+ {
8
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
9
+ name: { type: DataTypes.STRING(100), allowNull: false },
10
+ startDate: { type: DataTypes.DATEONLY, allowNull: false },
11
+ endDate: { type: DataTypes.DATEONLY, allowNull: false },
12
+ status: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
13
+ createdAt: {
14
+ type: DataTypes.DATE,
15
+ allowNull: false,
16
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
17
+ },
18
+ updatedAt: {
19
+ type: DataTypes.DATE,
20
+ allowNull: false,
21
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
22
+ },
23
+ },
24
+ { timestamps: false }
25
+ )
26
+ .then(() =>
27
+ queryInterface.addConstraint("FiscalYears", {
28
+ fields: ["startDate", "endDate"],
29
+ type: "unique",
30
+ name: "FiscalYears_date_unique",
31
+ })
32
+ )
33
+ .then(() =>
34
+ queryInterface.sequelize.query(`
35
+ ALTER TABLE "FiscalYears"
36
+ ADD CONSTRAINT "FiscalYears_date_check"
37
+ CHECK ("endDate" >= "startDate")
38
+ `)
39
+ );
40
+ },
41
+ down: async (queryInterface) => {
42
+ await queryInterface.dropTable("FiscalYears");
43
+ },
44
+ };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ module.exports = {
3
+ up: async (queryInterface, DataTypes) => {
4
+ await queryInterface
5
+ .createTable(
6
+ "OpeningBalance",
7
+ {
8
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
9
+ fiscalYearId: { type: DataTypes.INTEGER, allowNull: false },
10
+ chartOfAccountId: { type: DataTypes.INTEGER, allowNull: false },
11
+ amount: { type: DataTypes.DECIMAL(18, 2), allowNull: false },
12
+ createdAt: {
13
+ type: DataTypes.DATE,
14
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
15
+ },
16
+ updatedAt: {
17
+ type: DataTypes.DATE,
18
+ defaultValue: DataTypes.literal("CURRENT_TIMESTAMP"),
19
+ },
20
+ },
21
+ { timestamps: false }
22
+ )
23
+ .then(() =>
24
+ queryInterface.addConstraint("OpeningBalance", {
25
+ fields: ["fiscalYearId"],
26
+ type: "foreign key",
27
+ name: "OpeningBalance_FiscalYearId_Fkey",
28
+ references: {
29
+ table: "FiscalYears",
30
+ field: "id",
31
+ },
32
+ onDelete: "restrict",
33
+ onUpdate: "cascade",
34
+ })
35
+ )
36
+ .then(() =>
37
+ queryInterface.addConstraint("OpeningBalance", {
38
+ fields: ["chartOfAccountId"],
39
+ type: "foreign key",
40
+ name: "OpeningBalance_ChartOfAccountId_Fkey",
41
+ references: {
42
+ table: "ChartOfAccounts",
43
+ field: "id",
44
+ },
45
+ onDelete: "restrict",
46
+ onUpdate: "cascade",
47
+ })
48
+ )
49
+ .then(() =>
50
+ queryInterface.addConstraint("OpeningBalance", {
51
+ fields: ["fiscalYearId", "chartOfAccountId"],
52
+ type: "unique",
53
+ name: "OpeningBalance_FiscalYearId_ChartOfAccountId_Unique",
54
+ })
55
+ );
56
+ },
57
+ down: async (queryInterface) => {
58
+ await queryInterface.dropTable("OpeningBalance");
59
+ },
60
+ };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ const { JOURNAL_ENTRY_SOURCE_TYPE } = require("../../constants");
3
+
4
+ module.exports = {
5
+ up: async (queryInterface, DataTypes) => {
6
+ const table = await queryInterface.describeTable("JournalEntry");
7
+ if (table.sourceType) {
8
+ await queryInterface.removeColumn("JournalEntry", "sourceType");
9
+ }
10
+
11
+ const enumValues = Object.values(JOURNAL_ENTRY_SOURCE_TYPE)
12
+ .map((value) => `'${value}'`)
13
+ .join(", ");
14
+
15
+ await queryInterface.sequelize.query(`
16
+ DO $$
17
+ BEGIN
18
+ IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'JournalSourceType') THEN
19
+ CREATE TYPE "JournalSourceType" AS ENUM (${enumValues});
20
+ END IF;
21
+ END
22
+ $$;
23
+ `);
24
+
25
+ await queryInterface.sequelize.query(`
26
+ ALTER TABLE "JournalEntry"
27
+ ADD COLUMN "sourceType" "JournalSourceType"
28
+ `);
29
+ },
30
+ down: async (queryInterface, DataTypes) => {
31
+ const table = await queryInterface.describeTable("JournalEntry");
32
+ if (table.sourceType) {
33
+ await queryInterface.removeColumn("JournalEntry", "sourceType");
34
+ }
35
+ await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "JournalSourceType"`);
36
+ await queryInterface.addColumn("JournalEntry", "sourceType", {
37
+ type: DataTypes.STRING,
38
+ allowNull: true,
39
+ });
40
+ },
41
+ };
@@ -31,6 +31,14 @@ module.exports = (sequelize, DataTypes) => {
31
31
  foreignKey: "chartOfAccountId",
32
32
  as: "accounts",
33
33
  });
34
+ chartOfAccounts.hasMany(models.journalEntryLine, {
35
+ foreignKey: "chartOfAccountId",
36
+ as: "journalEntryLines",
37
+ });
38
+ chartOfAccounts.hasMany(models.openingBalance, {
39
+ foreignKey: "chartOfAccountId",
40
+ as: "openingBalances",
41
+ });
34
42
  };
35
43
  chartOfAccounts.selectedFields = [
36
44
  "id",
@@ -71,6 +71,10 @@ module.exports = (sequelize, DataTypes) => {
71
71
  foreignKey: "contributionTransactionId",
72
72
  as: "contributionTransactionLine",
73
73
  });
74
+ contributionTransaction.hasMany(models.journalEntry, {
75
+ foreignKey: "contributionTransactionId",
76
+ as: "journalEntries",
77
+ });
74
78
  }
75
79
  contributionTransaction.selectedFields = [
76
80
  "id",
@@ -0,0 +1,23 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ const fiscalYears = sequelize.define(
3
+ "FiscalYears",
4
+ {
5
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
6
+ name: { type: DataTypes.STRING(100), allowNull: false },
7
+ startDate: { type: DataTypes.DATEONLY, allowNull: false },
8
+ endDate: { type: DataTypes.DATEONLY, allowNull: false },
9
+ status: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },
10
+ createdAt: { type: DataTypes.DATE },
11
+ updatedAt: { type: DataTypes.DATE },
12
+ },
13
+ { freezeTableName: true, timestamps: false }
14
+ );
15
+ fiscalYears.associate = function (models) {
16
+ fiscalYears.hasMany(models.openingBalance, {
17
+ foreignKey: "fiscalYearId",
18
+ as: "openingBalances",
19
+ });
20
+ };
21
+ fiscalYears.selectedFields = ["id", "name", "startDate", "endDate", "status"];
22
+ return fiscalYears;
23
+ };
@@ -0,0 +1,45 @@
1
+ const { JOURNAL_ENTRY_SOURCE_TYPE } = require("../../constants");
2
+
3
+ module.exports = (sequelize, DataTypes) => {
4
+ const journalEntry = sequelize.define(
5
+ "JournalEntry",
6
+ {
7
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
8
+ entryDate: { type: DataTypes.DATEONLY, allowNull: false },
9
+ sourceType: {
10
+ type: DataTypes.ENUM({
11
+ name: "JournalSourceType",
12
+ values: Object.values(JOURNAL_ENTRY_SOURCE_TYPE),
13
+ }),
14
+ allowNull: true,
15
+ },
16
+ contributionTransactionId: { type: DataTypes.INTEGER, allowNull: true },
17
+ description: { type: DataTypes.TEXT, allowNull: true },
18
+ status: { type: DataTypes.STRING, defaultValue: "posted" },
19
+ createdAt: { type: DataTypes.DATE },
20
+ updatedAt: { type: DataTypes.DATE },
21
+ },
22
+ { freezeTableName: true, timestamps: false }
23
+ );
24
+ journalEntry.associate = function (models) {
25
+ journalEntry.belongsTo(models.contributionTransaction, {
26
+ foreignKey: "contributionTransactionId",
27
+ as: "contributionTransaction",
28
+ });
29
+ journalEntry.hasMany(models.journalEntryLine, {
30
+ foreignKey: "journalEntryId",
31
+ as: "journalEntryLines",
32
+ });
33
+ };
34
+ journalEntry.selectedFields = [
35
+ "id",
36
+ "entryDate",
37
+ "sourceType",
38
+ "contributionTransactionId",
39
+ "description",
40
+ "status",
41
+ "createdAt",
42
+ "updatedAt",
43
+ ];
44
+ return journalEntry;
45
+ };
@@ -0,0 +1,37 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ const journalEntryLine = sequelize.define(
3
+ "JournalEntryLine",
4
+ {
5
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
6
+ journalEntryId: { type: DataTypes.INTEGER, allowNull: false },
7
+ chartOfAccountId: { type: DataTypes.INTEGER, allowNull: false },
8
+ debit: { type: DataTypes.DECIMAL(10, 2), defaultValue: 0 },
9
+ credit: { type: DataTypes.DECIMAL(10, 2), defaultValue: 0 },
10
+ memo: { type: DataTypes.TEXT, allowNull: true },
11
+ createdAt: { type: DataTypes.DATE },
12
+ updatedAt: { type: DataTypes.DATE },
13
+ },
14
+ { freezeTableName: true, timestamps: false }
15
+ );
16
+ journalEntryLine.associate = function (models) {
17
+ journalEntryLine.belongsTo(models.journalEntry, {
18
+ foreignKey: "journalEntryId",
19
+ as: "journalEntry",
20
+ });
21
+ journalEntryLine.belongsTo(models.chartOfAccounts, {
22
+ foreignKey: "chartOfAccountId",
23
+ as: "chartOfAccount",
24
+ });
25
+ };
26
+ journalEntryLine.selectedFields = [
27
+ "id",
28
+ "journalEntryId",
29
+ "chartOfAccountId",
30
+ "debit",
31
+ "credit",
32
+ "memo",
33
+ "createdAt",
34
+ "updatedAt",
35
+ ];
36
+ return journalEntryLine;
37
+ };
@@ -0,0 +1,33 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ const openingBalance = sequelize.define(
3
+ "OpeningBalance",
4
+ {
5
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
6
+ fiscalYearId: { type: DataTypes.INTEGER, allowNull: false },
7
+ chartOfAccountId: { type: DataTypes.INTEGER, allowNull: false },
8
+ amount: { type: DataTypes.DECIMAL(18, 2), allowNull: false },
9
+ createdAt: { type: DataTypes.DATE },
10
+ updatedAt: { type: DataTypes.DATE },
11
+ },
12
+ { freezeTableName: true, timestamps: false }
13
+ );
14
+ openingBalance.associate = function (models) {
15
+ openingBalance.belongsTo(models.fiscalYears, {
16
+ foreignKey: "fiscalYearId",
17
+ as: "fiscalYear",
18
+ });
19
+ openingBalance.belongsTo(models.chartOfAccounts, {
20
+ foreignKey: "chartOfAccountId",
21
+ as: "chartOfAccount",
22
+ });
23
+ };
24
+ openingBalance.selectedFields = [
25
+ "id",
26
+ "fiscalYearId",
27
+ "chartOfAccountId",
28
+ "amount",
29
+ "createdAt",
30
+ "updatedAt",
31
+ ];
32
+ return openingBalance;
33
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@churchsoln/dbms",
3
- "version": "1.0.57",
3
+ "version": "1.0.59",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "prestart": "node db-setup.js",