@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.mjs
CHANGED
|
@@ -11021,8 +11021,8 @@ function useOrgService() {
|
|
|
11021
11021
|
mailer.sendMail({
|
|
11022
11022
|
to: verification.email,
|
|
11023
11023
|
subject: "Welcome to GoWeekdays - Your Organization is Ready",
|
|
11024
|
-
|
|
11025
|
-
|
|
11024
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
11025
|
+
html: emailContent
|
|
11026
11026
|
}).catch((error2) => {
|
|
11027
11027
|
logger28.log({
|
|
11028
11028
|
level: "error",
|
|
@@ -11158,8 +11158,8 @@ function useOrgService() {
|
|
|
11158
11158
|
mailer.sendMail({
|
|
11159
11159
|
to: verification.email,
|
|
11160
11160
|
subject: "Welcome to GoWeekdays - Your Organization is Ready",
|
|
11161
|
-
|
|
11162
|
-
|
|
11161
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
11162
|
+
html: emailContent
|
|
11163
11163
|
}).catch((error2) => {
|
|
11164
11164
|
logger28.log({
|
|
11165
11165
|
level: "error",
|
|
@@ -12072,7 +12072,7 @@ function useVerificationService() {
|
|
|
12072
12072
|
to: email,
|
|
12073
12073
|
subject: "Member Invite",
|
|
12074
12074
|
html: emailContent2,
|
|
12075
|
-
from: "GoWeekdays"
|
|
12075
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12076
12076
|
}).catch((error) => {
|
|
12077
12077
|
logger30.log({
|
|
12078
12078
|
level: "error",
|
|
@@ -12094,7 +12094,7 @@ function useVerificationService() {
|
|
|
12094
12094
|
to: email,
|
|
12095
12095
|
subject: "User Invite",
|
|
12096
12096
|
html: emailContent,
|
|
12097
|
-
from: "GoWeekdays"
|
|
12097
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12098
12098
|
}).catch((error) => {
|
|
12099
12099
|
logger30.log({
|
|
12100
12100
|
level: "error",
|
|
@@ -12128,7 +12128,7 @@ function useVerificationService() {
|
|
|
12128
12128
|
mailer.sendMail({
|
|
12129
12129
|
to: email,
|
|
12130
12130
|
subject: "Forget Password",
|
|
12131
|
-
from: "GoWeekdays"
|
|
12131
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
12132
12132
|
html: emailContent
|
|
12133
12133
|
}).catch((error) => {
|
|
12134
12134
|
logger30.log({
|
|
@@ -12319,7 +12319,7 @@ function useVerificationService() {
|
|
|
12319
12319
|
to: email,
|
|
12320
12320
|
subject: "Sign Up Verification",
|
|
12321
12321
|
html: emailContent,
|
|
12322
|
-
from: "GoWeekdays"
|
|
12322
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12323
12323
|
}).catch((error) => {
|
|
12324
12324
|
logger30.log({
|
|
12325
12325
|
level: "error",
|
|
@@ -12411,7 +12411,7 @@ function useVerificationService() {
|
|
|
12411
12411
|
to: value.email,
|
|
12412
12412
|
subject: "Member Invite",
|
|
12413
12413
|
html: emailContent2,
|
|
12414
|
-
from: "GoWeekdays"
|
|
12414
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12415
12415
|
}).catch((error2) => {
|
|
12416
12416
|
logger30.log({
|
|
12417
12417
|
level: "error",
|
|
@@ -12433,7 +12433,7 @@ function useVerificationService() {
|
|
|
12433
12433
|
to: value.email,
|
|
12434
12434
|
subject: "User Invite",
|
|
12435
12435
|
html: emailContent,
|
|
12436
|
-
from: "GoWeekdays"
|
|
12436
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12437
12437
|
}).catch((error2) => {
|
|
12438
12438
|
logger30.log({
|
|
12439
12439
|
level: "error",
|
|
@@ -12501,16 +12501,11 @@ function useVerificationService() {
|
|
|
12501
12501
|
},
|
|
12502
12502
|
filePath
|
|
12503
12503
|
});
|
|
12504
|
-
mailer.sendMail({
|
|
12504
|
+
await mailer.sendMail({
|
|
12505
12505
|
to: email,
|
|
12506
12506
|
subject: "Forget Password",
|
|
12507
|
-
from: "GoWeekdays"
|
|
12507
|
+
from: `"GoWeekdays" <support@goweekdays.com>`,
|
|
12508
12508
|
html: emailContent
|
|
12509
|
-
}).catch((error2) => {
|
|
12510
|
-
logger30.log({
|
|
12511
|
-
level: "error",
|
|
12512
|
-
message: `Error sending forget password email: ${error2}`
|
|
12513
|
-
});
|
|
12514
12509
|
});
|
|
12515
12510
|
return "Successfully created a link to reset password. Please check your email.";
|
|
12516
12511
|
} catch (error2) {
|
|
@@ -12625,7 +12620,7 @@ function useVerificationService() {
|
|
|
12625
12620
|
to: value.email,
|
|
12626
12621
|
subject: value.pilot ? "Pilot Organization Invitation" : "Organization Invitation",
|
|
12627
12622
|
html: emailContent,
|
|
12628
|
-
from: "GoWeekdays"
|
|
12623
|
+
from: `"GoWeekdays" <support@goweekdays.com>`
|
|
12629
12624
|
});
|
|
12630
12625
|
await session?.commitTransaction();
|
|
12631
12626
|
return "Successfully created organization invite.";
|
|
@@ -18701,6 +18696,242 @@ function useChartOfAccountRepo() {
|
|
|
18701
18696
|
throw new InternalServerError38("Failed to update children count.");
|
|
18702
18697
|
}
|
|
18703
18698
|
}
|
|
18699
|
+
async function getTrialBalance(options) {
|
|
18700
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18701
|
+
options.limit = options.limit ?? 10;
|
|
18702
|
+
try {
|
|
18703
|
+
options.org = new ObjectId47(options.org);
|
|
18704
|
+
} catch (error) {
|
|
18705
|
+
throw new BadRequestError88("Invalid organization ID.");
|
|
18706
|
+
}
|
|
18707
|
+
const cacheKey = makeCacheKey27(namespace_collection, {
|
|
18708
|
+
org: String(options.org),
|
|
18709
|
+
fiscalYear: options.fiscalYear,
|
|
18710
|
+
from: options.from ?? "",
|
|
18711
|
+
to: options.to ?? "",
|
|
18712
|
+
limit: options.limit,
|
|
18713
|
+
page: options.page
|
|
18714
|
+
});
|
|
18715
|
+
logger45.log({
|
|
18716
|
+
level: "info",
|
|
18717
|
+
message: `Cache key for getTrialBalance: ${cacheKey}`
|
|
18718
|
+
});
|
|
18719
|
+
try {
|
|
18720
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18721
|
+
if (cachedData) {
|
|
18722
|
+
logger45.log({
|
|
18723
|
+
level: "info",
|
|
18724
|
+
message: `Cache hit for getTrialBalance: ${cacheKey}`
|
|
18725
|
+
});
|
|
18726
|
+
return cachedData;
|
|
18727
|
+
}
|
|
18728
|
+
const query = {
|
|
18729
|
+
org: options.org,
|
|
18730
|
+
status: "active",
|
|
18731
|
+
childrenCount: 0
|
|
18732
|
+
};
|
|
18733
|
+
const pipeline = [
|
|
18734
|
+
{ $eq: ["$account", "$$account"] },
|
|
18735
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18736
|
+
];
|
|
18737
|
+
if (options.from !== void 0) {
|
|
18738
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18739
|
+
}
|
|
18740
|
+
if (options.to !== void 0) {
|
|
18741
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18742
|
+
}
|
|
18743
|
+
const accounts = await repo.collection.aggregate([
|
|
18744
|
+
{
|
|
18745
|
+
$match: query
|
|
18746
|
+
},
|
|
18747
|
+
{ $sort: { path: 1 } },
|
|
18748
|
+
{
|
|
18749
|
+
$skip: options.page * options.limit
|
|
18750
|
+
},
|
|
18751
|
+
{
|
|
18752
|
+
$limit: options.limit
|
|
18753
|
+
},
|
|
18754
|
+
{
|
|
18755
|
+
$lookup: {
|
|
18756
|
+
from: "finance.account.balances",
|
|
18757
|
+
let: {
|
|
18758
|
+
account: "$_id"
|
|
18759
|
+
},
|
|
18760
|
+
pipeline: [
|
|
18761
|
+
{
|
|
18762
|
+
$match: {
|
|
18763
|
+
$expr: {
|
|
18764
|
+
$and: pipeline
|
|
18765
|
+
}
|
|
18766
|
+
}
|
|
18767
|
+
},
|
|
18768
|
+
{
|
|
18769
|
+
$group: {
|
|
18770
|
+
_id: "$account",
|
|
18771
|
+
debit: {
|
|
18772
|
+
$sum: "$closingDebit"
|
|
18773
|
+
},
|
|
18774
|
+
credit: {
|
|
18775
|
+
$sum: "$closingCredit"
|
|
18776
|
+
}
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18779
|
+
],
|
|
18780
|
+
as: "balance"
|
|
18781
|
+
}
|
|
18782
|
+
},
|
|
18783
|
+
{
|
|
18784
|
+
$unwind: {
|
|
18785
|
+
path: "$balance",
|
|
18786
|
+
preserveNullAndEmptyArrays: true
|
|
18787
|
+
}
|
|
18788
|
+
},
|
|
18789
|
+
{
|
|
18790
|
+
$project: {
|
|
18791
|
+
name: 1,
|
|
18792
|
+
code: 1,
|
|
18793
|
+
type: 1,
|
|
18794
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18795
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18796
|
+
}
|
|
18797
|
+
},
|
|
18798
|
+
{
|
|
18799
|
+
$match: {
|
|
18800
|
+
$or: [{ debit: { $ne: 0 } }, { credit: { $ne: 0 } }]
|
|
18801
|
+
}
|
|
18802
|
+
}
|
|
18803
|
+
]).toArray();
|
|
18804
|
+
const length = await repo.collection.countDocuments(query);
|
|
18805
|
+
const data = paginate23(accounts, options.page, options.limit, length);
|
|
18806
|
+
repo.setCache(cacheKey, data, 300).then(() => {
|
|
18807
|
+
logger45.log({
|
|
18808
|
+
level: "info",
|
|
18809
|
+
message: `Cache set for getTrialBalance: ${cacheKey}`
|
|
18810
|
+
});
|
|
18811
|
+
}).catch((err) => {
|
|
18812
|
+
logger45.log({
|
|
18813
|
+
level: "error",
|
|
18814
|
+
message: `Failed to set cache for getTrialBalance: ${err.message}`
|
|
18815
|
+
});
|
|
18816
|
+
});
|
|
18817
|
+
return data;
|
|
18818
|
+
} catch (error) {
|
|
18819
|
+
logger45.log({
|
|
18820
|
+
level: "error",
|
|
18821
|
+
message: `Error in getTrialBalance: ${error}`
|
|
18822
|
+
});
|
|
18823
|
+
throw new InternalServerError38("Failed to get trial balance.");
|
|
18824
|
+
}
|
|
18825
|
+
}
|
|
18826
|
+
async function getBalanceSheet(options) {
|
|
18827
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18828
|
+
options.limit = options.limit ?? 10;
|
|
18829
|
+
try {
|
|
18830
|
+
options.org = new ObjectId47(options.org);
|
|
18831
|
+
} catch (error) {
|
|
18832
|
+
throw new BadRequestError88("Invalid organization ID.");
|
|
18833
|
+
}
|
|
18834
|
+
const cacheKey = makeCacheKey27(namespace_collection, {
|
|
18835
|
+
type: "balance-sheet",
|
|
18836
|
+
org: String(options.org),
|
|
18837
|
+
fiscalYear: options.fiscalYear,
|
|
18838
|
+
from: options.from ?? "",
|
|
18839
|
+
to: options.to ?? "",
|
|
18840
|
+
limit: options.limit,
|
|
18841
|
+
page: options.page
|
|
18842
|
+
});
|
|
18843
|
+
try {
|
|
18844
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18845
|
+
if (cachedData) {
|
|
18846
|
+
return cachedData;
|
|
18847
|
+
}
|
|
18848
|
+
const query = {
|
|
18849
|
+
org: options.org,
|
|
18850
|
+
status: "active",
|
|
18851
|
+
childrenCount: 0
|
|
18852
|
+
};
|
|
18853
|
+
const pipeline = [
|
|
18854
|
+
{ $eq: ["$account", "$$account"] },
|
|
18855
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18856
|
+
];
|
|
18857
|
+
if (options.from !== void 0) {
|
|
18858
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18859
|
+
}
|
|
18860
|
+
if (options.to !== void 0) {
|
|
18861
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18862
|
+
}
|
|
18863
|
+
const accounts = await repo.collection.aggregate([
|
|
18864
|
+
{ $match: query },
|
|
18865
|
+
{ $sort: { path: 1 } },
|
|
18866
|
+
{ $skip: options.page * options.limit },
|
|
18867
|
+
{ $limit: options.limit },
|
|
18868
|
+
{
|
|
18869
|
+
$lookup: {
|
|
18870
|
+
from: "finance.account.balances",
|
|
18871
|
+
let: { account: "$_id" },
|
|
18872
|
+
pipeline: [
|
|
18873
|
+
{
|
|
18874
|
+
$match: {
|
|
18875
|
+
$expr: { $and: pipeline }
|
|
18876
|
+
}
|
|
18877
|
+
},
|
|
18878
|
+
{
|
|
18879
|
+
$group: {
|
|
18880
|
+
_id: "$account",
|
|
18881
|
+
debit: { $sum: "$closingDebit" },
|
|
18882
|
+
credit: { $sum: "$closingCredit" }
|
|
18883
|
+
}
|
|
18884
|
+
}
|
|
18885
|
+
],
|
|
18886
|
+
as: "balance"
|
|
18887
|
+
}
|
|
18888
|
+
},
|
|
18889
|
+
{
|
|
18890
|
+
$unwind: {
|
|
18891
|
+
path: "$balance",
|
|
18892
|
+
preserveNullAndEmptyArrays: true
|
|
18893
|
+
}
|
|
18894
|
+
},
|
|
18895
|
+
{
|
|
18896
|
+
$project: {
|
|
18897
|
+
name: 1,
|
|
18898
|
+
code: 1,
|
|
18899
|
+
type: 1,
|
|
18900
|
+
normalBalance: 1,
|
|
18901
|
+
isContra: 1,
|
|
18902
|
+
parent: 1,
|
|
18903
|
+
childrenCount: 1,
|
|
18904
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18905
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18906
|
+
}
|
|
18907
|
+
},
|
|
18908
|
+
{
|
|
18909
|
+
$match: {
|
|
18910
|
+
$or: [
|
|
18911
|
+
{ childrenCount: { $gt: 0 } },
|
|
18912
|
+
{ debit: { $ne: 0 } },
|
|
18913
|
+
{ credit: { $ne: 0 } }
|
|
18914
|
+
]
|
|
18915
|
+
}
|
|
18916
|
+
}
|
|
18917
|
+
]).toArray();
|
|
18918
|
+
const length = await repo.collection.countDocuments(query);
|
|
18919
|
+
const data = paginate23(accounts, options.page, options.limit, length);
|
|
18920
|
+
repo.setCache(cacheKey, data, 300).catch((err) => {
|
|
18921
|
+
logger45.log({
|
|
18922
|
+
level: "error",
|
|
18923
|
+
message: `Failed to set cache for getBalanceSheet: ${err.message}`
|
|
18924
|
+
});
|
|
18925
|
+
});
|
|
18926
|
+
return data;
|
|
18927
|
+
} catch (error) {
|
|
18928
|
+
logger45.log({
|
|
18929
|
+
level: "error",
|
|
18930
|
+
message: `Error in getBalanceSheet: ${error}`
|
|
18931
|
+
});
|
|
18932
|
+
throw new InternalServerError38("Failed to get balance sheet data.");
|
|
18933
|
+
}
|
|
18934
|
+
}
|
|
18704
18935
|
return {
|
|
18705
18936
|
createIndexes,
|
|
18706
18937
|
add,
|
|
@@ -18711,7 +18942,9 @@ function useChartOfAccountRepo() {
|
|
|
18711
18942
|
deleteById,
|
|
18712
18943
|
updateStatusById,
|
|
18713
18944
|
countByPath,
|
|
18714
|
-
updateChildrenCountById
|
|
18945
|
+
updateChildrenCountById,
|
|
18946
|
+
getTrialBalance,
|
|
18947
|
+
getBalanceSheet
|
|
18715
18948
|
};
|
|
18716
18949
|
}
|
|
18717
18950
|
|
|
@@ -18729,7 +18962,9 @@ function useChartOfAccountService() {
|
|
|
18729
18962
|
updateById: _updateById,
|
|
18730
18963
|
deleteById: _deleteById,
|
|
18731
18964
|
countByPath,
|
|
18732
|
-
updateChildrenCountById
|
|
18965
|
+
updateChildrenCountById,
|
|
18966
|
+
getTrialBalance: _getTrialBalance,
|
|
18967
|
+
getBalanceSheet: _getBalanceSheet
|
|
18733
18968
|
} = useChartOfAccountRepo();
|
|
18734
18969
|
async function add(value) {
|
|
18735
18970
|
const { error } = schemaChartOfAccountBase.validate(value);
|
|
@@ -18870,10 +19105,112 @@ function useChartOfAccountService() {
|
|
|
18870
19105
|
session.endSession();
|
|
18871
19106
|
}
|
|
18872
19107
|
}
|
|
19108
|
+
async function getTrialBalance(options) {
|
|
19109
|
+
const LIMIT = 100;
|
|
19110
|
+
const allAccounts = [];
|
|
19111
|
+
let page = 1;
|
|
19112
|
+
let totalPages = 1;
|
|
19113
|
+
do {
|
|
19114
|
+
const result = await _getTrialBalance({
|
|
19115
|
+
org: options.org,
|
|
19116
|
+
fiscalYear: options.fiscalYear,
|
|
19117
|
+
from: options.from,
|
|
19118
|
+
to: options.to,
|
|
19119
|
+
page,
|
|
19120
|
+
limit: LIMIT
|
|
19121
|
+
});
|
|
19122
|
+
allAccounts.push(...result.items);
|
|
19123
|
+
totalPages = result.pages;
|
|
19124
|
+
page++;
|
|
19125
|
+
} while (page <= totalPages);
|
|
19126
|
+
return allAccounts;
|
|
19127
|
+
}
|
|
19128
|
+
async function getBalanceSheet(options) {
|
|
19129
|
+
const LIMIT = 100;
|
|
19130
|
+
const allAccounts = [];
|
|
19131
|
+
let page = 1;
|
|
19132
|
+
let totalPages = 1;
|
|
19133
|
+
do {
|
|
19134
|
+
const result = await _getBalanceSheet({
|
|
19135
|
+
org: options.org,
|
|
19136
|
+
fiscalYear: options.fiscalYear,
|
|
19137
|
+
from: options.from,
|
|
19138
|
+
to: options.to,
|
|
19139
|
+
page,
|
|
19140
|
+
limit: LIMIT
|
|
19141
|
+
});
|
|
19142
|
+
allAccounts.push(...result.items);
|
|
19143
|
+
totalPages = result.pages;
|
|
19144
|
+
page++;
|
|
19145
|
+
} while (page <= totalPages);
|
|
19146
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19147
|
+
const section = (type) => {
|
|
19148
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19149
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19150
|
+
return { accounts, total };
|
|
19151
|
+
};
|
|
19152
|
+
const assets = section("asset");
|
|
19153
|
+
const liabilities = section("liability");
|
|
19154
|
+
const equity = section("equity");
|
|
19155
|
+
const incomeTotal = allAccounts.filter((a) => a.type === "income").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19156
|
+
const expenseTotal = allAccounts.filter((a) => a.type === "expense").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19157
|
+
const netIncome = incomeTotal - expenseTotal;
|
|
19158
|
+
const totalEquity = equity.total + netIncome;
|
|
19159
|
+
const totalLiabilitiesAndEquity = liabilities.total + totalEquity;
|
|
19160
|
+
return {
|
|
19161
|
+
assets: assets.accounts,
|
|
19162
|
+
liabilities: liabilities.accounts,
|
|
19163
|
+
equity: equity.accounts,
|
|
19164
|
+
netIncome,
|
|
19165
|
+
totalAssets: assets.total,
|
|
19166
|
+
totalLiabilities: liabilities.total,
|
|
19167
|
+
totalEquity,
|
|
19168
|
+
totalLiabilitiesAndEquity,
|
|
19169
|
+
isBalanced: assets.total === totalLiabilitiesAndEquity
|
|
19170
|
+
};
|
|
19171
|
+
}
|
|
19172
|
+
async function getIncomeStatement(options) {
|
|
19173
|
+
const LIMIT = 100;
|
|
19174
|
+
const allAccounts = [];
|
|
19175
|
+
let page = 1;
|
|
19176
|
+
let totalPages = 1;
|
|
19177
|
+
do {
|
|
19178
|
+
const result = await _getBalanceSheet({
|
|
19179
|
+
org: options.org,
|
|
19180
|
+
fiscalYear: options.fiscalYear,
|
|
19181
|
+
from: options.from,
|
|
19182
|
+
to: options.to,
|
|
19183
|
+
page,
|
|
19184
|
+
limit: LIMIT
|
|
19185
|
+
});
|
|
19186
|
+
allAccounts.push(...result.items);
|
|
19187
|
+
totalPages = result.pages;
|
|
19188
|
+
page++;
|
|
19189
|
+
} while (page <= totalPages);
|
|
19190
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19191
|
+
const section = (type) => {
|
|
19192
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19193
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19194
|
+
return { accounts, total };
|
|
19195
|
+
};
|
|
19196
|
+
const revenues = section("income");
|
|
19197
|
+
const expenses = section("expense");
|
|
19198
|
+
const netIncome = revenues.total - expenses.total;
|
|
19199
|
+
return {
|
|
19200
|
+
revenues: revenues.accounts,
|
|
19201
|
+
expenses: expenses.accounts,
|
|
19202
|
+
totalRevenues: revenues.total,
|
|
19203
|
+
totalExpenses: expenses.total,
|
|
19204
|
+
netIncome
|
|
19205
|
+
};
|
|
19206
|
+
}
|
|
18873
19207
|
return {
|
|
18874
19208
|
add,
|
|
18875
19209
|
updateById,
|
|
18876
|
-
deleteById
|
|
19210
|
+
deleteById,
|
|
19211
|
+
getTrialBalance,
|
|
19212
|
+
getBalanceSheet,
|
|
19213
|
+
getIncomeStatement
|
|
18877
19214
|
};
|
|
18878
19215
|
}
|
|
18879
19216
|
|
|
@@ -18888,7 +19225,10 @@ function useChartOfAccountController() {
|
|
|
18888
19225
|
const {
|
|
18889
19226
|
add: _add,
|
|
18890
19227
|
updateById: _updateById,
|
|
18891
|
-
deleteById: _deleteById
|
|
19228
|
+
deleteById: _deleteById,
|
|
19229
|
+
getTrialBalance: _getTrialBalance,
|
|
19230
|
+
getBalanceSheet: _getBalanceSheet,
|
|
19231
|
+
getIncomeStatement: _getIncomeStatement
|
|
18892
19232
|
} = useChartOfAccountService();
|
|
18893
19233
|
async function add(req, res, next) {
|
|
18894
19234
|
const value = req.body;
|
|
@@ -19044,6 +19384,75 @@ function useChartOfAccountController() {
|
|
|
19044
19384
|
next(error);
|
|
19045
19385
|
}
|
|
19046
19386
|
}
|
|
19387
|
+
async function getTrialBalance(req, res, next) {
|
|
19388
|
+
const org = req.params.org ?? "";
|
|
19389
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19390
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : NaN;
|
|
19391
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : NaN;
|
|
19392
|
+
const validation = Joi80.object({
|
|
19393
|
+
org: Joi80.string().hex().required(),
|
|
19394
|
+
fiscalYear: Joi80.number().required(),
|
|
19395
|
+
from: Joi80.number().optional().allow("", null),
|
|
19396
|
+
to: Joi80.number().optional().allow("", null)
|
|
19397
|
+
});
|
|
19398
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19399
|
+
if (error) {
|
|
19400
|
+
next(new BadRequestError90(error.message));
|
|
19401
|
+
return;
|
|
19402
|
+
}
|
|
19403
|
+
try {
|
|
19404
|
+
const accounts = await _getTrialBalance({ org, fiscalYear, from, to });
|
|
19405
|
+
res.json(accounts);
|
|
19406
|
+
} catch (error2) {
|
|
19407
|
+
next(error2);
|
|
19408
|
+
}
|
|
19409
|
+
}
|
|
19410
|
+
async function getBalanceSheet(req, res, next) {
|
|
19411
|
+
const org = req.params.org ?? "";
|
|
19412
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19413
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19414
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19415
|
+
const validation = Joi80.object({
|
|
19416
|
+
org: Joi80.string().hex().required(),
|
|
19417
|
+
fiscalYear: Joi80.number().required(),
|
|
19418
|
+
from: Joi80.number().optional().allow("", null),
|
|
19419
|
+
to: Joi80.number().optional().allow("", null)
|
|
19420
|
+
});
|
|
19421
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19422
|
+
if (error) {
|
|
19423
|
+
next(new BadRequestError90(error.message));
|
|
19424
|
+
return;
|
|
19425
|
+
}
|
|
19426
|
+
try {
|
|
19427
|
+
const data = await _getBalanceSheet({ org, fiscalYear, from, to });
|
|
19428
|
+
res.json(data);
|
|
19429
|
+
} catch (error2) {
|
|
19430
|
+
next(error2);
|
|
19431
|
+
}
|
|
19432
|
+
}
|
|
19433
|
+
async function getIncomeStatement(req, res, next) {
|
|
19434
|
+
const org = req.params.org ?? "";
|
|
19435
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19436
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19437
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19438
|
+
const validation = Joi80.object({
|
|
19439
|
+
org: Joi80.string().hex().required(),
|
|
19440
|
+
fiscalYear: Joi80.number().required(),
|
|
19441
|
+
from: Joi80.number().optional().allow("", null),
|
|
19442
|
+
to: Joi80.number().optional().allow("", null)
|
|
19443
|
+
});
|
|
19444
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19445
|
+
if (error) {
|
|
19446
|
+
next(new BadRequestError90(error.message));
|
|
19447
|
+
return;
|
|
19448
|
+
}
|
|
19449
|
+
try {
|
|
19450
|
+
const data = await _getIncomeStatement({ org, fiscalYear, from, to });
|
|
19451
|
+
res.json(data);
|
|
19452
|
+
} catch (error2) {
|
|
19453
|
+
next(error2);
|
|
19454
|
+
}
|
|
19455
|
+
}
|
|
19047
19456
|
async function updateStatusById(req, res, next) {
|
|
19048
19457
|
const id = req.params.id;
|
|
19049
19458
|
const status2 = req.params.status;
|
|
@@ -19071,7 +19480,10 @@ function useChartOfAccountController() {
|
|
|
19071
19480
|
getById,
|
|
19072
19481
|
updateById,
|
|
19073
19482
|
deleteById,
|
|
19074
|
-
updateStatusById
|
|
19483
|
+
updateStatusById,
|
|
19484
|
+
getTrialBalance,
|
|
19485
|
+
getBalanceSheet,
|
|
19486
|
+
getIncomeStatement
|
|
19075
19487
|
};
|
|
19076
19488
|
}
|
|
19077
19489
|
|
|
@@ -19085,7 +19497,9 @@ var schemaAccountBalance = Joi81.object({
|
|
|
19085
19497
|
accountType: Joi81.string().required(),
|
|
19086
19498
|
period: Joi81.object({
|
|
19087
19499
|
fiscalYear: Joi81.number().required(),
|
|
19088
|
-
|
|
19500
|
+
fiscalMonth: Joi81.number().min(1).max(12).required(),
|
|
19501
|
+
year: Joi81.number().required(),
|
|
19502
|
+
month: Joi81.number().min(1).max(12).required()
|
|
19089
19503
|
}).required(),
|
|
19090
19504
|
openingDebit: Joi81.number().required(),
|
|
19091
19505
|
openingCredit: Joi81.number().required(),
|
|
@@ -19150,10 +19564,18 @@ function useAccountBalanceRepo() {
|
|
|
19150
19564
|
org: 1,
|
|
19151
19565
|
account: 1,
|
|
19152
19566
|
"period.fiscalYear": 1,
|
|
19153
|
-
"period.
|
|
19567
|
+
"period.fiscalMonth": 1
|
|
19154
19568
|
},
|
|
19155
19569
|
unique: true,
|
|
19156
|
-
name: "
|
|
19570
|
+
name: "unique_balance_per_account_fiscal_month"
|
|
19571
|
+
},
|
|
19572
|
+
{
|
|
19573
|
+
key: {
|
|
19574
|
+
org: 1,
|
|
19575
|
+
"period.fiscalYear": 1,
|
|
19576
|
+
"period.fiscalMonth": 1
|
|
19577
|
+
},
|
|
19578
|
+
name: "balance_reporting_fiscal_month"
|
|
19157
19579
|
}
|
|
19158
19580
|
]);
|
|
19159
19581
|
} catch (error) {
|
|
@@ -19212,7 +19634,7 @@ function useAccountBalanceRepo() {
|
|
|
19212
19634
|
}
|
|
19213
19635
|
const items = await repo.collection.aggregate([
|
|
19214
19636
|
{ $match: query },
|
|
19215
|
-
{ $sort: { "period.fiscalYear": -1 } },
|
|
19637
|
+
{ $sort: { "period.fiscalYear": -1, "period.fiscalMonth": -1 } },
|
|
19216
19638
|
{ $skip: options.page * options.limit },
|
|
19217
19639
|
{ $limit: options.limit }
|
|
19218
19640
|
]).toArray();
|
|
@@ -19290,13 +19712,13 @@ function useAccountBalanceRepo() {
|
|
|
19290
19712
|
account,
|
|
19291
19713
|
org,
|
|
19292
19714
|
"period.fiscalYear": options.fiscalYear,
|
|
19293
|
-
"period.
|
|
19715
|
+
"period.fiscalMonth": options.fiscalMonth
|
|
19294
19716
|
};
|
|
19295
19717
|
const cacheKey = makeCacheKey28(namespace_collection, {
|
|
19296
19718
|
account: String(account),
|
|
19297
19719
|
org: String(org),
|
|
19298
19720
|
fiscalYear: options.fiscalYear,
|
|
19299
|
-
|
|
19721
|
+
fiscalMonth: options.fiscalMonth
|
|
19300
19722
|
});
|
|
19301
19723
|
try {
|
|
19302
19724
|
const cached = await repo.getCache(cacheKey);
|
|
@@ -19345,7 +19767,7 @@ function useAccountBalanceRepo() {
|
|
|
19345
19767
|
try {
|
|
19346
19768
|
return await repo.collection.find(
|
|
19347
19769
|
{ account, org, "period.fiscalYear": options.fiscalYear },
|
|
19348
|
-
{ sort: { "period.
|
|
19770
|
+
{ sort: { "period.fiscalMonth": 1 } }
|
|
19349
19771
|
).toArray();
|
|
19350
19772
|
} catch (error) {
|
|
19351
19773
|
if (error instanceof AppError43) {
|
|
@@ -19354,7 +19776,7 @@ function useAccountBalanceRepo() {
|
|
|
19354
19776
|
throw new InternalServerError39("Failed to get account balances by year.");
|
|
19355
19777
|
}
|
|
19356
19778
|
}
|
|
19357
|
-
async function updateById(account, org, fiscalYear,
|
|
19779
|
+
async function updateById(account, org, fiscalYear, fiscalMonth, options, session) {
|
|
19358
19780
|
const { error } = Joi82.object({
|
|
19359
19781
|
openingDebit: Joi82.number().min(0).optional(),
|
|
19360
19782
|
openingCredit: Joi82.number().min(0).optional(),
|
|
@@ -19385,7 +19807,7 @@ function useAccountBalanceRepo() {
|
|
|
19385
19807
|
account,
|
|
19386
19808
|
org,
|
|
19387
19809
|
"period.fiscalYear": fiscalYear,
|
|
19388
|
-
"period.
|
|
19810
|
+
"period.fiscalMonth": fiscalMonth
|
|
19389
19811
|
},
|
|
19390
19812
|
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } },
|
|
19391
19813
|
{ session, upsert: true }
|
|
@@ -21418,20 +21840,6 @@ function useJournalService() {
|
|
|
21418
21840
|
);
|
|
21419
21841
|
}
|
|
21420
21842
|
session.startTransaction();
|
|
21421
|
-
const MONTHS = [
|
|
21422
|
-
"January",
|
|
21423
|
-
"February",
|
|
21424
|
-
"March",
|
|
21425
|
-
"April",
|
|
21426
|
-
"May",
|
|
21427
|
-
"June",
|
|
21428
|
-
"July",
|
|
21429
|
-
"August",
|
|
21430
|
-
"September",
|
|
21431
|
-
"October",
|
|
21432
|
-
"November",
|
|
21433
|
-
"December"
|
|
21434
|
-
];
|
|
21435
21843
|
if (status2 === "posted") {
|
|
21436
21844
|
await updateStatusByJournal(_id, status2, session);
|
|
21437
21845
|
await _updateStatusById(_id, status2, session);
|
|
@@ -21446,13 +21854,30 @@ function useJournalService() {
|
|
|
21446
21854
|
const linesToPost = await getJournalLinesByEntry(_id);
|
|
21447
21855
|
const journalDate = new Date(journalEntry.date);
|
|
21448
21856
|
const fiscalYear = Number(businessProfile.currentFiscalYear);
|
|
21449
|
-
const
|
|
21857
|
+
const calendarYear = journalDate.getFullYear();
|
|
21858
|
+
const calendarMonth = journalDate.getMonth() + 1;
|
|
21859
|
+
const FISCAL_MONTHS = [
|
|
21860
|
+
"January",
|
|
21861
|
+
"February",
|
|
21862
|
+
"March",
|
|
21863
|
+
"April",
|
|
21864
|
+
"May",
|
|
21865
|
+
"June",
|
|
21866
|
+
"July",
|
|
21867
|
+
"August",
|
|
21868
|
+
"September",
|
|
21869
|
+
"October",
|
|
21870
|
+
"November",
|
|
21871
|
+
"December"
|
|
21872
|
+
];
|
|
21873
|
+
const fiscalStartIdx = FISCAL_MONTHS.indexOf(businessProfile.fiscalYearStart);
|
|
21874
|
+
const fiscalMonth = (calendarMonth - 1 - fiscalStartIdx + 12) % 12 + 1;
|
|
21450
21875
|
for (const line of linesToPost) {
|
|
21451
21876
|
const existingBalance = await getAccountBalance({
|
|
21452
21877
|
account: String(line.account),
|
|
21453
21878
|
org: String(journalEntry.org),
|
|
21454
21879
|
fiscalYear,
|
|
21455
|
-
|
|
21880
|
+
fiscalMonth
|
|
21456
21881
|
});
|
|
21457
21882
|
if (existingBalance) {
|
|
21458
21883
|
const movementDebit = existingBalance.movementDebit + (line.debit || 0);
|
|
@@ -21467,7 +21892,7 @@ function useJournalService() {
|
|
|
21467
21892
|
String(line.account),
|
|
21468
21893
|
String(journalEntry.org),
|
|
21469
21894
|
fiscalYear,
|
|
21470
|
-
|
|
21895
|
+
fiscalMonth,
|
|
21471
21896
|
{
|
|
21472
21897
|
movementDebit,
|
|
21473
21898
|
movementCredit,
|
|
@@ -21484,10 +21909,7 @@ function useJournalService() {
|
|
|
21484
21909
|
org: String(journalEntry.org),
|
|
21485
21910
|
fiscalYear
|
|
21486
21911
|
});
|
|
21487
|
-
const
|
|
21488
|
-
const previousRecord = allYearBalances.filter((r) => MONTHS.indexOf(r.period.month) < currentMonthIdx).sort(
|
|
21489
|
-
(a, b) => MONTHS.indexOf(b.period.month) - MONTHS.indexOf(a.period.month)
|
|
21490
|
-
)[0];
|
|
21912
|
+
const previousRecord = allYearBalances.filter((r) => r.period.fiscalMonth < fiscalMonth).sort((a, b) => b.period.fiscalMonth - a.period.fiscalMonth)[0];
|
|
21491
21913
|
const openingDebit = previousRecord?.closingDebit ?? 0;
|
|
21492
21914
|
const openingCredit = previousRecord?.closingCredit ?? 0;
|
|
21493
21915
|
const movementDebit = line.debit || 0;
|
|
@@ -21503,7 +21925,7 @@ function useJournalService() {
|
|
|
21503
21925
|
org: String(journalEntry.org),
|
|
21504
21926
|
account: String(line.account),
|
|
21505
21927
|
accountType: line.accountType || "",
|
|
21506
|
-
period: { fiscalYear, month },
|
|
21928
|
+
period: { fiscalYear, fiscalMonth, year: calendarYear, month: calendarMonth },
|
|
21507
21929
|
openingDebit,
|
|
21508
21930
|
openingCredit,
|
|
21509
21931
|
movementDebit,
|