@goweekdays/core 2.15.2 → 2.15.4
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.
- package/.github/workflows/publish.yml +7 -8
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +27 -4
- package/dist/index.js +476 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +476 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -11116,8 +11116,8 @@ function useOrgService() {
|
|
|
11116
11116
|
mailer.sendMail({
|
|
11117
11117
|
to: verification.email,
|
|
11118
11118
|
subject: "Welcome to GoWeekdays - Your Organization is Ready",
|
|
11119
|
-
|
|
11120
|
-
|
|
11119
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
11120
|
+
html: emailContent
|
|
11121
11121
|
}).catch((error2) => {
|
|
11122
11122
|
import_utils58.logger.log({
|
|
11123
11123
|
level: "error",
|
|
@@ -11253,8 +11253,8 @@ function useOrgService() {
|
|
|
11253
11253
|
mailer.sendMail({
|
|
11254
11254
|
to: verification.email,
|
|
11255
11255
|
subject: "Welcome to GoWeekdays - Your Organization is Ready",
|
|
11256
|
-
|
|
11257
|
-
|
|
11256
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
11257
|
+
html: emailContent
|
|
11258
11258
|
}).catch((error2) => {
|
|
11259
11259
|
import_utils58.logger.log({
|
|
11260
11260
|
level: "error",
|
|
@@ -12163,7 +12163,7 @@ function useVerificationService() {
|
|
|
12163
12163
|
to: email,
|
|
12164
12164
|
subject: "Member Invite",
|
|
12165
12165
|
html: emailContent2,
|
|
12166
|
-
from: "GoWeekdays"
|
|
12166
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12167
12167
|
}).catch((error) => {
|
|
12168
12168
|
import_utils62.logger.log({
|
|
12169
12169
|
level: "error",
|
|
@@ -12185,7 +12185,7 @@ function useVerificationService() {
|
|
|
12185
12185
|
to: email,
|
|
12186
12186
|
subject: "User Invite",
|
|
12187
12187
|
html: emailContent,
|
|
12188
|
-
from: "GoWeekdays"
|
|
12188
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12189
12189
|
}).catch((error) => {
|
|
12190
12190
|
import_utils62.logger.log({
|
|
12191
12191
|
level: "error",
|
|
@@ -12219,7 +12219,7 @@ function useVerificationService() {
|
|
|
12219
12219
|
mailer.sendMail({
|
|
12220
12220
|
to: email,
|
|
12221
12221
|
subject: "Forget Password",
|
|
12222
|
-
from: "GoWeekdays"
|
|
12222
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
12223
12223
|
html: emailContent
|
|
12224
12224
|
}).catch((error) => {
|
|
12225
12225
|
import_utils62.logger.log({
|
|
@@ -12410,7 +12410,7 @@ function useVerificationService() {
|
|
|
12410
12410
|
to: email,
|
|
12411
12411
|
subject: "Sign Up Verification",
|
|
12412
12412
|
html: emailContent,
|
|
12413
|
-
from: "GoWeekdays"
|
|
12413
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12414
12414
|
}).catch((error) => {
|
|
12415
12415
|
import_utils62.logger.log({
|
|
12416
12416
|
level: "error",
|
|
@@ -12502,7 +12502,7 @@ function useVerificationService() {
|
|
|
12502
12502
|
to: value.email,
|
|
12503
12503
|
subject: "Member Invite",
|
|
12504
12504
|
html: emailContent2,
|
|
12505
|
-
from: "GoWeekdays"
|
|
12505
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12506
12506
|
}).catch((error2) => {
|
|
12507
12507
|
import_utils62.logger.log({
|
|
12508
12508
|
level: "error",
|
|
@@ -12524,7 +12524,7 @@ function useVerificationService() {
|
|
|
12524
12524
|
to: value.email,
|
|
12525
12525
|
subject: "User Invite",
|
|
12526
12526
|
html: emailContent,
|
|
12527
|
-
from: "GoWeekdays"
|
|
12527
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12528
12528
|
}).catch((error2) => {
|
|
12529
12529
|
import_utils62.logger.log({
|
|
12530
12530
|
level: "error",
|
|
@@ -12592,16 +12592,11 @@ function useVerificationService() {
|
|
|
12592
12592
|
},
|
|
12593
12593
|
filePath
|
|
12594
12594
|
});
|
|
12595
|
-
mailer.sendMail({
|
|
12595
|
+
await mailer.sendMail({
|
|
12596
12596
|
to: email,
|
|
12597
12597
|
subject: "Forget Password",
|
|
12598
|
-
from: "GoWeekdays"
|
|
12598
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
12599
12599
|
html: emailContent
|
|
12600
|
-
}).catch((error2) => {
|
|
12601
|
-
import_utils62.logger.log({
|
|
12602
|
-
level: "error",
|
|
12603
|
-
message: `Error sending forget password email: ${error2}`
|
|
12604
|
-
});
|
|
12605
12600
|
});
|
|
12606
12601
|
return "Successfully created a link to reset password. Please check your email.";
|
|
12607
12602
|
} catch (error2) {
|
|
@@ -12716,7 +12711,7 @@ function useVerificationService() {
|
|
|
12716
12711
|
to: value.email,
|
|
12717
12712
|
subject: value.pilot ? "Pilot Organization Invitation" : "Organization Invitation",
|
|
12718
12713
|
html: emailContent,
|
|
12719
|
-
from: "GoWeekdays"
|
|
12714
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12720
12715
|
});
|
|
12721
12716
|
await session?.commitTransaction();
|
|
12722
12717
|
return "Successfully created organization invite.";
|
|
@@ -18718,6 +18713,242 @@ function useChartOfAccountRepo() {
|
|
|
18718
18713
|
throw new import_utils95.InternalServerError("Failed to update children count.");
|
|
18719
18714
|
}
|
|
18720
18715
|
}
|
|
18716
|
+
async function getTrialBalance(options) {
|
|
18717
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18718
|
+
options.limit = options.limit ?? 10;
|
|
18719
|
+
try {
|
|
18720
|
+
options.org = new import_mongodb47.ObjectId(options.org);
|
|
18721
|
+
} catch (error) {
|
|
18722
|
+
throw new import_utils95.BadRequestError("Invalid organization ID.");
|
|
18723
|
+
}
|
|
18724
|
+
const cacheKey = (0, import_utils95.makeCacheKey)(namespace_collection, {
|
|
18725
|
+
org: String(options.org),
|
|
18726
|
+
fiscalYear: options.fiscalYear,
|
|
18727
|
+
from: options.from ?? "",
|
|
18728
|
+
to: options.to ?? "",
|
|
18729
|
+
limit: options.limit,
|
|
18730
|
+
page: options.page
|
|
18731
|
+
});
|
|
18732
|
+
import_utils95.logger.log({
|
|
18733
|
+
level: "info",
|
|
18734
|
+
message: `Cache key for getTrialBalance: ${cacheKey}`
|
|
18735
|
+
});
|
|
18736
|
+
try {
|
|
18737
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18738
|
+
if (cachedData) {
|
|
18739
|
+
import_utils95.logger.log({
|
|
18740
|
+
level: "info",
|
|
18741
|
+
message: `Cache hit for getTrialBalance: ${cacheKey}`
|
|
18742
|
+
});
|
|
18743
|
+
return cachedData;
|
|
18744
|
+
}
|
|
18745
|
+
const query = {
|
|
18746
|
+
org: options.org,
|
|
18747
|
+
status: "active",
|
|
18748
|
+
childrenCount: 0
|
|
18749
|
+
};
|
|
18750
|
+
const pipeline = [
|
|
18751
|
+
{ $eq: ["$account", "$$account"] },
|
|
18752
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18753
|
+
];
|
|
18754
|
+
if (options.from !== void 0) {
|
|
18755
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18756
|
+
}
|
|
18757
|
+
if (options.to !== void 0) {
|
|
18758
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18759
|
+
}
|
|
18760
|
+
const accounts = await repo.collection.aggregate([
|
|
18761
|
+
{
|
|
18762
|
+
$match: query
|
|
18763
|
+
},
|
|
18764
|
+
{ $sort: { path: 1 } },
|
|
18765
|
+
{
|
|
18766
|
+
$skip: options.page * options.limit
|
|
18767
|
+
},
|
|
18768
|
+
{
|
|
18769
|
+
$limit: options.limit
|
|
18770
|
+
},
|
|
18771
|
+
{
|
|
18772
|
+
$lookup: {
|
|
18773
|
+
from: "finance.account.balances",
|
|
18774
|
+
let: {
|
|
18775
|
+
account: "$_id"
|
|
18776
|
+
},
|
|
18777
|
+
pipeline: [
|
|
18778
|
+
{
|
|
18779
|
+
$match: {
|
|
18780
|
+
$expr: {
|
|
18781
|
+
$and: pipeline
|
|
18782
|
+
}
|
|
18783
|
+
}
|
|
18784
|
+
},
|
|
18785
|
+
{
|
|
18786
|
+
$group: {
|
|
18787
|
+
_id: "$account",
|
|
18788
|
+
debit: {
|
|
18789
|
+
$sum: "$closingDebit"
|
|
18790
|
+
},
|
|
18791
|
+
credit: {
|
|
18792
|
+
$sum: "$closingCredit"
|
|
18793
|
+
}
|
|
18794
|
+
}
|
|
18795
|
+
}
|
|
18796
|
+
],
|
|
18797
|
+
as: "balance"
|
|
18798
|
+
}
|
|
18799
|
+
},
|
|
18800
|
+
{
|
|
18801
|
+
$unwind: {
|
|
18802
|
+
path: "$balance",
|
|
18803
|
+
preserveNullAndEmptyArrays: true
|
|
18804
|
+
}
|
|
18805
|
+
},
|
|
18806
|
+
{
|
|
18807
|
+
$project: {
|
|
18808
|
+
name: 1,
|
|
18809
|
+
code: 1,
|
|
18810
|
+
type: 1,
|
|
18811
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18812
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18813
|
+
}
|
|
18814
|
+
},
|
|
18815
|
+
{
|
|
18816
|
+
$match: {
|
|
18817
|
+
$or: [{ debit: { $ne: 0 } }, { credit: { $ne: 0 } }]
|
|
18818
|
+
}
|
|
18819
|
+
}
|
|
18820
|
+
]).toArray();
|
|
18821
|
+
const length = await repo.collection.countDocuments(query);
|
|
18822
|
+
const data = (0, import_utils95.paginate)(accounts, options.page, options.limit, length);
|
|
18823
|
+
repo.setCache(cacheKey, data, 300).then(() => {
|
|
18824
|
+
import_utils95.logger.log({
|
|
18825
|
+
level: "info",
|
|
18826
|
+
message: `Cache set for getTrialBalance: ${cacheKey}`
|
|
18827
|
+
});
|
|
18828
|
+
}).catch((err) => {
|
|
18829
|
+
import_utils95.logger.log({
|
|
18830
|
+
level: "error",
|
|
18831
|
+
message: `Failed to set cache for getTrialBalance: ${err.message}`
|
|
18832
|
+
});
|
|
18833
|
+
});
|
|
18834
|
+
return data;
|
|
18835
|
+
} catch (error) {
|
|
18836
|
+
import_utils95.logger.log({
|
|
18837
|
+
level: "error",
|
|
18838
|
+
message: `Error in getTrialBalance: ${error}`
|
|
18839
|
+
});
|
|
18840
|
+
throw new import_utils95.InternalServerError("Failed to get trial balance.");
|
|
18841
|
+
}
|
|
18842
|
+
}
|
|
18843
|
+
async function getBalanceSheet(options) {
|
|
18844
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18845
|
+
options.limit = options.limit ?? 10;
|
|
18846
|
+
try {
|
|
18847
|
+
options.org = new import_mongodb47.ObjectId(options.org);
|
|
18848
|
+
} catch (error) {
|
|
18849
|
+
throw new import_utils95.BadRequestError("Invalid organization ID.");
|
|
18850
|
+
}
|
|
18851
|
+
const cacheKey = (0, import_utils95.makeCacheKey)(namespace_collection, {
|
|
18852
|
+
type: "balance-sheet",
|
|
18853
|
+
org: String(options.org),
|
|
18854
|
+
fiscalYear: options.fiscalYear,
|
|
18855
|
+
from: options.from ?? "",
|
|
18856
|
+
to: options.to ?? "",
|
|
18857
|
+
limit: options.limit,
|
|
18858
|
+
page: options.page
|
|
18859
|
+
});
|
|
18860
|
+
try {
|
|
18861
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18862
|
+
if (cachedData) {
|
|
18863
|
+
return cachedData;
|
|
18864
|
+
}
|
|
18865
|
+
const query = {
|
|
18866
|
+
org: options.org,
|
|
18867
|
+
status: "active",
|
|
18868
|
+
childrenCount: 0
|
|
18869
|
+
};
|
|
18870
|
+
const pipeline = [
|
|
18871
|
+
{ $eq: ["$account", "$$account"] },
|
|
18872
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18873
|
+
];
|
|
18874
|
+
if (options.from !== void 0) {
|
|
18875
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18876
|
+
}
|
|
18877
|
+
if (options.to !== void 0) {
|
|
18878
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18879
|
+
}
|
|
18880
|
+
const accounts = await repo.collection.aggregate([
|
|
18881
|
+
{ $match: query },
|
|
18882
|
+
{ $sort: { path: 1 } },
|
|
18883
|
+
{ $skip: options.page * options.limit },
|
|
18884
|
+
{ $limit: options.limit },
|
|
18885
|
+
{
|
|
18886
|
+
$lookup: {
|
|
18887
|
+
from: "finance.account.balances",
|
|
18888
|
+
let: { account: "$_id" },
|
|
18889
|
+
pipeline: [
|
|
18890
|
+
{
|
|
18891
|
+
$match: {
|
|
18892
|
+
$expr: { $and: pipeline }
|
|
18893
|
+
}
|
|
18894
|
+
},
|
|
18895
|
+
{
|
|
18896
|
+
$group: {
|
|
18897
|
+
_id: "$account",
|
|
18898
|
+
debit: { $sum: "$closingDebit" },
|
|
18899
|
+
credit: { $sum: "$closingCredit" }
|
|
18900
|
+
}
|
|
18901
|
+
}
|
|
18902
|
+
],
|
|
18903
|
+
as: "balance"
|
|
18904
|
+
}
|
|
18905
|
+
},
|
|
18906
|
+
{
|
|
18907
|
+
$unwind: {
|
|
18908
|
+
path: "$balance",
|
|
18909
|
+
preserveNullAndEmptyArrays: true
|
|
18910
|
+
}
|
|
18911
|
+
},
|
|
18912
|
+
{
|
|
18913
|
+
$project: {
|
|
18914
|
+
name: 1,
|
|
18915
|
+
code: 1,
|
|
18916
|
+
type: 1,
|
|
18917
|
+
normalBalance: 1,
|
|
18918
|
+
isContra: 1,
|
|
18919
|
+
parent: 1,
|
|
18920
|
+
childrenCount: 1,
|
|
18921
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18922
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18923
|
+
}
|
|
18924
|
+
},
|
|
18925
|
+
{
|
|
18926
|
+
$match: {
|
|
18927
|
+
$or: [
|
|
18928
|
+
{ childrenCount: { $gt: 0 } },
|
|
18929
|
+
{ debit: { $ne: 0 } },
|
|
18930
|
+
{ credit: { $ne: 0 } }
|
|
18931
|
+
]
|
|
18932
|
+
}
|
|
18933
|
+
}
|
|
18934
|
+
]).toArray();
|
|
18935
|
+
const length = await repo.collection.countDocuments(query);
|
|
18936
|
+
const data = (0, import_utils95.paginate)(accounts, options.page, options.limit, length);
|
|
18937
|
+
repo.setCache(cacheKey, data, 300).catch((err) => {
|
|
18938
|
+
import_utils95.logger.log({
|
|
18939
|
+
level: "error",
|
|
18940
|
+
message: `Failed to set cache for getBalanceSheet: ${err.message}`
|
|
18941
|
+
});
|
|
18942
|
+
});
|
|
18943
|
+
return data;
|
|
18944
|
+
} catch (error) {
|
|
18945
|
+
import_utils95.logger.log({
|
|
18946
|
+
level: "error",
|
|
18947
|
+
message: `Error in getBalanceSheet: ${error}`
|
|
18948
|
+
});
|
|
18949
|
+
throw new import_utils95.InternalServerError("Failed to get balance sheet data.");
|
|
18950
|
+
}
|
|
18951
|
+
}
|
|
18721
18952
|
return {
|
|
18722
18953
|
createIndexes,
|
|
18723
18954
|
add,
|
|
@@ -18728,7 +18959,9 @@ function useChartOfAccountRepo() {
|
|
|
18728
18959
|
deleteById,
|
|
18729
18960
|
updateStatusById,
|
|
18730
18961
|
countByPath,
|
|
18731
|
-
updateChildrenCountById
|
|
18962
|
+
updateChildrenCountById,
|
|
18963
|
+
getTrialBalance,
|
|
18964
|
+
getBalanceSheet
|
|
18732
18965
|
};
|
|
18733
18966
|
}
|
|
18734
18967
|
|
|
@@ -18746,7 +18979,9 @@ function useChartOfAccountService() {
|
|
|
18746
18979
|
updateById: _updateById,
|
|
18747
18980
|
deleteById: _deleteById,
|
|
18748
18981
|
countByPath,
|
|
18749
|
-
updateChildrenCountById
|
|
18982
|
+
updateChildrenCountById,
|
|
18983
|
+
getTrialBalance: _getTrialBalance,
|
|
18984
|
+
getBalanceSheet: _getBalanceSheet
|
|
18750
18985
|
} = useChartOfAccountRepo();
|
|
18751
18986
|
async function add(value) {
|
|
18752
18987
|
const { error } = schemaChartOfAccountBase.validate(value);
|
|
@@ -18887,10 +19122,112 @@ function useChartOfAccountService() {
|
|
|
18887
19122
|
session.endSession();
|
|
18888
19123
|
}
|
|
18889
19124
|
}
|
|
19125
|
+
async function getTrialBalance(options) {
|
|
19126
|
+
const LIMIT = 100;
|
|
19127
|
+
const allAccounts = [];
|
|
19128
|
+
let page = 1;
|
|
19129
|
+
let totalPages = 1;
|
|
19130
|
+
do {
|
|
19131
|
+
const result = await _getTrialBalance({
|
|
19132
|
+
org: options.org,
|
|
19133
|
+
fiscalYear: options.fiscalYear,
|
|
19134
|
+
from: options.from,
|
|
19135
|
+
to: options.to,
|
|
19136
|
+
page,
|
|
19137
|
+
limit: LIMIT
|
|
19138
|
+
});
|
|
19139
|
+
allAccounts.push(...result.items);
|
|
19140
|
+
totalPages = result.pages;
|
|
19141
|
+
page++;
|
|
19142
|
+
} while (page <= totalPages);
|
|
19143
|
+
return allAccounts;
|
|
19144
|
+
}
|
|
19145
|
+
async function getBalanceSheet(options) {
|
|
19146
|
+
const LIMIT = 100;
|
|
19147
|
+
const allAccounts = [];
|
|
19148
|
+
let page = 1;
|
|
19149
|
+
let totalPages = 1;
|
|
19150
|
+
do {
|
|
19151
|
+
const result = await _getBalanceSheet({
|
|
19152
|
+
org: options.org,
|
|
19153
|
+
fiscalYear: options.fiscalYear,
|
|
19154
|
+
from: options.from,
|
|
19155
|
+
to: options.to,
|
|
19156
|
+
page,
|
|
19157
|
+
limit: LIMIT
|
|
19158
|
+
});
|
|
19159
|
+
allAccounts.push(...result.items);
|
|
19160
|
+
totalPages = result.pages;
|
|
19161
|
+
page++;
|
|
19162
|
+
} while (page <= totalPages);
|
|
19163
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19164
|
+
const section = (type) => {
|
|
19165
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19166
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19167
|
+
return { accounts, total };
|
|
19168
|
+
};
|
|
19169
|
+
const assets = section("asset");
|
|
19170
|
+
const liabilities = section("liability");
|
|
19171
|
+
const equity = section("equity");
|
|
19172
|
+
const incomeTotal = allAccounts.filter((a) => a.type === "income").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19173
|
+
const expenseTotal = allAccounts.filter((a) => a.type === "expense").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19174
|
+
const netIncome = incomeTotal - expenseTotal;
|
|
19175
|
+
const totalEquity = equity.total + netIncome;
|
|
19176
|
+
const totalLiabilitiesAndEquity = liabilities.total + totalEquity;
|
|
19177
|
+
return {
|
|
19178
|
+
assets: assets.accounts,
|
|
19179
|
+
liabilities: liabilities.accounts,
|
|
19180
|
+
equity: equity.accounts,
|
|
19181
|
+
netIncome,
|
|
19182
|
+
totalAssets: assets.total,
|
|
19183
|
+
totalLiabilities: liabilities.total,
|
|
19184
|
+
totalEquity,
|
|
19185
|
+
totalLiabilitiesAndEquity,
|
|
19186
|
+
isBalanced: assets.total === totalLiabilitiesAndEquity
|
|
19187
|
+
};
|
|
19188
|
+
}
|
|
19189
|
+
async function getIncomeStatement(options) {
|
|
19190
|
+
const LIMIT = 100;
|
|
19191
|
+
const allAccounts = [];
|
|
19192
|
+
let page = 1;
|
|
19193
|
+
let totalPages = 1;
|
|
19194
|
+
do {
|
|
19195
|
+
const result = await _getBalanceSheet({
|
|
19196
|
+
org: options.org,
|
|
19197
|
+
fiscalYear: options.fiscalYear,
|
|
19198
|
+
from: options.from,
|
|
19199
|
+
to: options.to,
|
|
19200
|
+
page,
|
|
19201
|
+
limit: LIMIT
|
|
19202
|
+
});
|
|
19203
|
+
allAccounts.push(...result.items);
|
|
19204
|
+
totalPages = result.pages;
|
|
19205
|
+
page++;
|
|
19206
|
+
} while (page <= totalPages);
|
|
19207
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19208
|
+
const section = (type) => {
|
|
19209
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19210
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19211
|
+
return { accounts, total };
|
|
19212
|
+
};
|
|
19213
|
+
const revenues = section("income");
|
|
19214
|
+
const expenses = section("expense");
|
|
19215
|
+
const netIncome = revenues.total - expenses.total;
|
|
19216
|
+
return {
|
|
19217
|
+
revenues: revenues.accounts,
|
|
19218
|
+
expenses: expenses.accounts,
|
|
19219
|
+
totalRevenues: revenues.total,
|
|
19220
|
+
totalExpenses: expenses.total,
|
|
19221
|
+
netIncome
|
|
19222
|
+
};
|
|
19223
|
+
}
|
|
18890
19224
|
return {
|
|
18891
19225
|
add,
|
|
18892
19226
|
updateById,
|
|
18893
|
-
deleteById
|
|
19227
|
+
deleteById,
|
|
19228
|
+
getTrialBalance,
|
|
19229
|
+
getBalanceSheet,
|
|
19230
|
+
getIncomeStatement
|
|
18894
19231
|
};
|
|
18895
19232
|
}
|
|
18896
19233
|
|
|
@@ -18905,7 +19242,10 @@ function useChartOfAccountController() {
|
|
|
18905
19242
|
const {
|
|
18906
19243
|
add: _add,
|
|
18907
19244
|
updateById: _updateById,
|
|
18908
|
-
deleteById: _deleteById
|
|
19245
|
+
deleteById: _deleteById,
|
|
19246
|
+
getTrialBalance: _getTrialBalance,
|
|
19247
|
+
getBalanceSheet: _getBalanceSheet,
|
|
19248
|
+
getIncomeStatement: _getIncomeStatement
|
|
18909
19249
|
} = useChartOfAccountService();
|
|
18910
19250
|
async function add(req, res, next) {
|
|
18911
19251
|
const value = req.body;
|
|
@@ -19061,6 +19401,75 @@ function useChartOfAccountController() {
|
|
|
19061
19401
|
next(error);
|
|
19062
19402
|
}
|
|
19063
19403
|
}
|
|
19404
|
+
async function getTrialBalance(req, res, next) {
|
|
19405
|
+
const org = req.params.org ?? "";
|
|
19406
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19407
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : NaN;
|
|
19408
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : NaN;
|
|
19409
|
+
const validation = import_joi80.default.object({
|
|
19410
|
+
org: import_joi80.default.string().hex().required(),
|
|
19411
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19412
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19413
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19414
|
+
});
|
|
19415
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19416
|
+
if (error) {
|
|
19417
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19418
|
+
return;
|
|
19419
|
+
}
|
|
19420
|
+
try {
|
|
19421
|
+
const accounts = await _getTrialBalance({ org, fiscalYear, from, to });
|
|
19422
|
+
res.json(accounts);
|
|
19423
|
+
} catch (error2) {
|
|
19424
|
+
next(error2);
|
|
19425
|
+
}
|
|
19426
|
+
}
|
|
19427
|
+
async function getBalanceSheet(req, res, next) {
|
|
19428
|
+
const org = req.params.org ?? "";
|
|
19429
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19430
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19431
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19432
|
+
const validation = import_joi80.default.object({
|
|
19433
|
+
org: import_joi80.default.string().hex().required(),
|
|
19434
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19435
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19436
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19437
|
+
});
|
|
19438
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19439
|
+
if (error) {
|
|
19440
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19441
|
+
return;
|
|
19442
|
+
}
|
|
19443
|
+
try {
|
|
19444
|
+
const data = await _getBalanceSheet({ org, fiscalYear, from, to });
|
|
19445
|
+
res.json(data);
|
|
19446
|
+
} catch (error2) {
|
|
19447
|
+
next(error2);
|
|
19448
|
+
}
|
|
19449
|
+
}
|
|
19450
|
+
async function getIncomeStatement(req, res, next) {
|
|
19451
|
+
const org = req.params.org ?? "";
|
|
19452
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19453
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19454
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19455
|
+
const validation = import_joi80.default.object({
|
|
19456
|
+
org: import_joi80.default.string().hex().required(),
|
|
19457
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19458
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19459
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19460
|
+
});
|
|
19461
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19462
|
+
if (error) {
|
|
19463
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19464
|
+
return;
|
|
19465
|
+
}
|
|
19466
|
+
try {
|
|
19467
|
+
const data = await _getIncomeStatement({ org, fiscalYear, from, to });
|
|
19468
|
+
res.json(data);
|
|
19469
|
+
} catch (error2) {
|
|
19470
|
+
next(error2);
|
|
19471
|
+
}
|
|
19472
|
+
}
|
|
19064
19473
|
async function updateStatusById(req, res, next) {
|
|
19065
19474
|
const id = req.params.id;
|
|
19066
19475
|
const status2 = req.params.status;
|
|
@@ -19088,7 +19497,10 @@ function useChartOfAccountController() {
|
|
|
19088
19497
|
getById,
|
|
19089
19498
|
updateById,
|
|
19090
19499
|
deleteById,
|
|
19091
|
-
updateStatusById
|
|
19500
|
+
updateStatusById,
|
|
19501
|
+
getTrialBalance,
|
|
19502
|
+
getBalanceSheet,
|
|
19503
|
+
getIncomeStatement
|
|
19092
19504
|
};
|
|
19093
19505
|
}
|
|
19094
19506
|
|
|
@@ -19102,7 +19514,9 @@ var schemaAccountBalance = import_joi81.default.object({
|
|
|
19102
19514
|
accountType: import_joi81.default.string().required(),
|
|
19103
19515
|
period: import_joi81.default.object({
|
|
19104
19516
|
fiscalYear: import_joi81.default.number().required(),
|
|
19105
|
-
|
|
19517
|
+
fiscalMonth: import_joi81.default.number().min(1).max(12).required(),
|
|
19518
|
+
year: import_joi81.default.number().required(),
|
|
19519
|
+
month: import_joi81.default.number().min(1).max(12).required()
|
|
19106
19520
|
}).required(),
|
|
19107
19521
|
openingDebit: import_joi81.default.number().required(),
|
|
19108
19522
|
openingCredit: import_joi81.default.number().required(),
|
|
@@ -19159,10 +19573,18 @@ function useAccountBalanceRepo() {
|
|
|
19159
19573
|
org: 1,
|
|
19160
19574
|
account: 1,
|
|
19161
19575
|
"period.fiscalYear": 1,
|
|
19162
|
-
"period.
|
|
19576
|
+
"period.fiscalMonth": 1
|
|
19163
19577
|
},
|
|
19164
19578
|
unique: true,
|
|
19165
|
-
name: "
|
|
19579
|
+
name: "unique_balance_per_account_fiscal_month"
|
|
19580
|
+
},
|
|
19581
|
+
{
|
|
19582
|
+
key: {
|
|
19583
|
+
org: 1,
|
|
19584
|
+
"period.fiscalYear": 1,
|
|
19585
|
+
"period.fiscalMonth": 1
|
|
19586
|
+
},
|
|
19587
|
+
name: "balance_reporting_fiscal_month"
|
|
19166
19588
|
}
|
|
19167
19589
|
]);
|
|
19168
19590
|
} catch (error) {
|
|
@@ -19221,7 +19643,7 @@ function useAccountBalanceRepo() {
|
|
|
19221
19643
|
}
|
|
19222
19644
|
const items = await repo.collection.aggregate([
|
|
19223
19645
|
{ $match: query },
|
|
19224
|
-
{ $sort: { "period.fiscalYear": -1 } },
|
|
19646
|
+
{ $sort: { "period.fiscalYear": -1, "period.fiscalMonth": -1 } },
|
|
19225
19647
|
{ $skip: options.page * options.limit },
|
|
19226
19648
|
{ $limit: options.limit }
|
|
19227
19649
|
]).toArray();
|
|
@@ -19299,13 +19721,13 @@ function useAccountBalanceRepo() {
|
|
|
19299
19721
|
account,
|
|
19300
19722
|
org,
|
|
19301
19723
|
"period.fiscalYear": options.fiscalYear,
|
|
19302
|
-
"period.
|
|
19724
|
+
"period.fiscalMonth": options.fiscalMonth
|
|
19303
19725
|
};
|
|
19304
19726
|
const cacheKey = (0, import_utils99.makeCacheKey)(namespace_collection, {
|
|
19305
19727
|
account: String(account),
|
|
19306
19728
|
org: String(org),
|
|
19307
19729
|
fiscalYear: options.fiscalYear,
|
|
19308
|
-
|
|
19730
|
+
fiscalMonth: options.fiscalMonth
|
|
19309
19731
|
});
|
|
19310
19732
|
try {
|
|
19311
19733
|
const cached = await repo.getCache(cacheKey);
|
|
@@ -19354,7 +19776,7 @@ function useAccountBalanceRepo() {
|
|
|
19354
19776
|
try {
|
|
19355
19777
|
return await repo.collection.find(
|
|
19356
19778
|
{ account, org, "period.fiscalYear": options.fiscalYear },
|
|
19357
|
-
{ sort: { "period.
|
|
19779
|
+
{ sort: { "period.fiscalMonth": 1 } }
|
|
19358
19780
|
).toArray();
|
|
19359
19781
|
} catch (error) {
|
|
19360
19782
|
if (error instanceof import_utils99.AppError) {
|
|
@@ -19363,7 +19785,7 @@ function useAccountBalanceRepo() {
|
|
|
19363
19785
|
throw new import_utils99.InternalServerError("Failed to get account balances by year.");
|
|
19364
19786
|
}
|
|
19365
19787
|
}
|
|
19366
|
-
async function updateById(account, org, fiscalYear,
|
|
19788
|
+
async function updateById(account, org, fiscalYear, fiscalMonth, options, session) {
|
|
19367
19789
|
const { error } = import_joi82.default.object({
|
|
19368
19790
|
openingDebit: import_joi82.default.number().min(0).optional(),
|
|
19369
19791
|
openingCredit: import_joi82.default.number().min(0).optional(),
|
|
@@ -19394,7 +19816,7 @@ function useAccountBalanceRepo() {
|
|
|
19394
19816
|
account,
|
|
19395
19817
|
org,
|
|
19396
19818
|
"period.fiscalYear": fiscalYear,
|
|
19397
|
-
"period.
|
|
19819
|
+
"period.fiscalMonth": fiscalMonth
|
|
19398
19820
|
},
|
|
19399
19821
|
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } },
|
|
19400
19822
|
{ session, upsert: true }
|
|
@@ -21382,20 +21804,6 @@ function useJournalService() {
|
|
|
21382
21804
|
);
|
|
21383
21805
|
}
|
|
21384
21806
|
session.startTransaction();
|
|
21385
|
-
const MONTHS = [
|
|
21386
|
-
"January",
|
|
21387
|
-
"February",
|
|
21388
|
-
"March",
|
|
21389
|
-
"April",
|
|
21390
|
-
"May",
|
|
21391
|
-
"June",
|
|
21392
|
-
"July",
|
|
21393
|
-
"August",
|
|
21394
|
-
"September",
|
|
21395
|
-
"October",
|
|
21396
|
-
"November",
|
|
21397
|
-
"December"
|
|
21398
|
-
];
|
|
21399
21807
|
if (status2 === "posted") {
|
|
21400
21808
|
await updateStatusByJournal(_id, status2, session);
|
|
21401
21809
|
await _updateStatusById(_id, status2, session);
|
|
@@ -21410,13 +21818,30 @@ function useJournalService() {
|
|
|
21410
21818
|
const linesToPost = await getJournalLinesByEntry(_id);
|
|
21411
21819
|
const journalDate = new Date(journalEntry.date);
|
|
21412
21820
|
const fiscalYear = Number(businessProfile.currentFiscalYear);
|
|
21413
|
-
const
|
|
21821
|
+
const calendarYear = journalDate.getFullYear();
|
|
21822
|
+
const calendarMonth = journalDate.getMonth() + 1;
|
|
21823
|
+
const FISCAL_MONTHS = [
|
|
21824
|
+
"January",
|
|
21825
|
+
"February",
|
|
21826
|
+
"March",
|
|
21827
|
+
"April",
|
|
21828
|
+
"May",
|
|
21829
|
+
"June",
|
|
21830
|
+
"July",
|
|
21831
|
+
"August",
|
|
21832
|
+
"September",
|
|
21833
|
+
"October",
|
|
21834
|
+
"November",
|
|
21835
|
+
"December"
|
|
21836
|
+
];
|
|
21837
|
+
const fiscalStartIdx = FISCAL_MONTHS.indexOf(businessProfile.fiscalYearStart);
|
|
21838
|
+
const fiscalMonth = (calendarMonth - 1 - fiscalStartIdx + 12) % 12 + 1;
|
|
21414
21839
|
for (const line of linesToPost) {
|
|
21415
21840
|
const existingBalance = await getAccountBalance({
|
|
21416
21841
|
account: String(line.account),
|
|
21417
21842
|
org: String(journalEntry.org),
|
|
21418
21843
|
fiscalYear,
|
|
21419
|
-
|
|
21844
|
+
fiscalMonth
|
|
21420
21845
|
});
|
|
21421
21846
|
if (existingBalance) {
|
|
21422
21847
|
const movementDebit = existingBalance.movementDebit + (line.debit || 0);
|
|
@@ -21431,7 +21856,7 @@ function useJournalService() {
|
|
|
21431
21856
|
String(line.account),
|
|
21432
21857
|
String(journalEntry.org),
|
|
21433
21858
|
fiscalYear,
|
|
21434
|
-
|
|
21859
|
+
fiscalMonth,
|
|
21435
21860
|
{
|
|
21436
21861
|
movementDebit,
|
|
21437
21862
|
movementCredit,
|
|
@@ -21448,10 +21873,7 @@ function useJournalService() {
|
|
|
21448
21873
|
org: String(journalEntry.org),
|
|
21449
21874
|
fiscalYear
|
|
21450
21875
|
});
|
|
21451
|
-
const
|
|
21452
|
-
const previousRecord = allYearBalances.filter((r) => MONTHS.indexOf(r.period.month) < currentMonthIdx).sort(
|
|
21453
|
-
(a, b) => MONTHS.indexOf(b.period.month) - MONTHS.indexOf(a.period.month)
|
|
21454
|
-
)[0];
|
|
21876
|
+
const previousRecord = allYearBalances.filter((r) => r.period.fiscalMonth < fiscalMonth).sort((a, b) => b.period.fiscalMonth - a.period.fiscalMonth)[0];
|
|
21455
21877
|
const openingDebit = previousRecord?.closingDebit ?? 0;
|
|
21456
21878
|
const openingCredit = previousRecord?.closingCredit ?? 0;
|
|
21457
21879
|
const movementDebit = line.debit || 0;
|
|
@@ -21467,7 +21889,7 @@ function useJournalService() {
|
|
|
21467
21889
|
org: String(journalEntry.org),
|
|
21468
21890
|
account: String(line.account),
|
|
21469
21891
|
accountType: line.accountType || "",
|
|
21470
|
-
period: { fiscalYear, month },
|
|
21892
|
+
period: { fiscalYear, fiscalMonth, year: calendarYear, month: calendarMonth },
|
|
21471
21893
|
openingDebit,
|
|
21472
21894
|
openingCredit,
|
|
21473
21895
|
movementDebit,
|