@goweekdays/core 2.15.1 → 2.15.3
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +27 -4
- package/dist/index.js +465 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +465 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18356,7 +18356,8 @@ function useChartOfAccountRepo() {
|
|
|
18356
18356
|
{ key: { code: 1 } },
|
|
18357
18357
|
{ key: { path: 1 } },
|
|
18358
18358
|
{ key: { name: 1, org: 1 }, unique: true, name: "unique_name_per_org" },
|
|
18359
|
-
{ key: { code: 1, org: 1 }, unique: true, name: "unique_code_per_org" }
|
|
18359
|
+
{ key: { code: 1, org: 1 }, unique: true, name: "unique_code_per_org" },
|
|
18360
|
+
{ key: { name: "text", code: "text" }, name: "text_search" }
|
|
18360
18361
|
]);
|
|
18361
18362
|
} catch (error) {
|
|
18362
18363
|
throw new Error("Failed to create index on chart of account.");
|
|
@@ -18717,6 +18718,242 @@ function useChartOfAccountRepo() {
|
|
|
18717
18718
|
throw new import_utils95.InternalServerError("Failed to update children count.");
|
|
18718
18719
|
}
|
|
18719
18720
|
}
|
|
18721
|
+
async function getTrialBalance(options) {
|
|
18722
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18723
|
+
options.limit = options.limit ?? 10;
|
|
18724
|
+
try {
|
|
18725
|
+
options.org = new import_mongodb47.ObjectId(options.org);
|
|
18726
|
+
} catch (error) {
|
|
18727
|
+
throw new import_utils95.BadRequestError("Invalid organization ID.");
|
|
18728
|
+
}
|
|
18729
|
+
const cacheKey = (0, import_utils95.makeCacheKey)(namespace_collection, {
|
|
18730
|
+
org: String(options.org),
|
|
18731
|
+
fiscalYear: options.fiscalYear,
|
|
18732
|
+
from: options.from ?? "",
|
|
18733
|
+
to: options.to ?? "",
|
|
18734
|
+
limit: options.limit,
|
|
18735
|
+
page: options.page
|
|
18736
|
+
});
|
|
18737
|
+
import_utils95.logger.log({
|
|
18738
|
+
level: "info",
|
|
18739
|
+
message: `Cache key for getTrialBalance: ${cacheKey}`
|
|
18740
|
+
});
|
|
18741
|
+
try {
|
|
18742
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18743
|
+
if (cachedData) {
|
|
18744
|
+
import_utils95.logger.log({
|
|
18745
|
+
level: "info",
|
|
18746
|
+
message: `Cache hit for getTrialBalance: ${cacheKey}`
|
|
18747
|
+
});
|
|
18748
|
+
return cachedData;
|
|
18749
|
+
}
|
|
18750
|
+
const query = {
|
|
18751
|
+
org: options.org,
|
|
18752
|
+
status: "active",
|
|
18753
|
+
childrenCount: 0
|
|
18754
|
+
};
|
|
18755
|
+
const pipeline = [
|
|
18756
|
+
{ $eq: ["$account", "$$account"] },
|
|
18757
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18758
|
+
];
|
|
18759
|
+
if (options.from !== void 0) {
|
|
18760
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18761
|
+
}
|
|
18762
|
+
if (options.to !== void 0) {
|
|
18763
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18764
|
+
}
|
|
18765
|
+
const accounts = await repo.collection.aggregate([
|
|
18766
|
+
{
|
|
18767
|
+
$match: query
|
|
18768
|
+
},
|
|
18769
|
+
{ $sort: { path: 1 } },
|
|
18770
|
+
{
|
|
18771
|
+
$skip: options.page * options.limit
|
|
18772
|
+
},
|
|
18773
|
+
{
|
|
18774
|
+
$limit: options.limit
|
|
18775
|
+
},
|
|
18776
|
+
{
|
|
18777
|
+
$lookup: {
|
|
18778
|
+
from: "finance.account.balances",
|
|
18779
|
+
let: {
|
|
18780
|
+
account: "$_id"
|
|
18781
|
+
},
|
|
18782
|
+
pipeline: [
|
|
18783
|
+
{
|
|
18784
|
+
$match: {
|
|
18785
|
+
$expr: {
|
|
18786
|
+
$and: pipeline
|
|
18787
|
+
}
|
|
18788
|
+
}
|
|
18789
|
+
},
|
|
18790
|
+
{
|
|
18791
|
+
$group: {
|
|
18792
|
+
_id: "$account",
|
|
18793
|
+
debit: {
|
|
18794
|
+
$sum: "$closingDebit"
|
|
18795
|
+
},
|
|
18796
|
+
credit: {
|
|
18797
|
+
$sum: "$closingCredit"
|
|
18798
|
+
}
|
|
18799
|
+
}
|
|
18800
|
+
}
|
|
18801
|
+
],
|
|
18802
|
+
as: "balance"
|
|
18803
|
+
}
|
|
18804
|
+
},
|
|
18805
|
+
{
|
|
18806
|
+
$unwind: {
|
|
18807
|
+
path: "$balance",
|
|
18808
|
+
preserveNullAndEmptyArrays: true
|
|
18809
|
+
}
|
|
18810
|
+
},
|
|
18811
|
+
{
|
|
18812
|
+
$project: {
|
|
18813
|
+
name: 1,
|
|
18814
|
+
code: 1,
|
|
18815
|
+
type: 1,
|
|
18816
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18817
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18818
|
+
}
|
|
18819
|
+
},
|
|
18820
|
+
{
|
|
18821
|
+
$match: {
|
|
18822
|
+
$or: [{ debit: { $ne: 0 } }, { credit: { $ne: 0 } }]
|
|
18823
|
+
}
|
|
18824
|
+
}
|
|
18825
|
+
]).toArray();
|
|
18826
|
+
const length = await repo.collection.countDocuments(query);
|
|
18827
|
+
const data = (0, import_utils95.paginate)(accounts, options.page, options.limit, length);
|
|
18828
|
+
repo.setCache(cacheKey, data, 300).then(() => {
|
|
18829
|
+
import_utils95.logger.log({
|
|
18830
|
+
level: "info",
|
|
18831
|
+
message: `Cache set for getTrialBalance: ${cacheKey}`
|
|
18832
|
+
});
|
|
18833
|
+
}).catch((err) => {
|
|
18834
|
+
import_utils95.logger.log({
|
|
18835
|
+
level: "error",
|
|
18836
|
+
message: `Failed to set cache for getTrialBalance: ${err.message}`
|
|
18837
|
+
});
|
|
18838
|
+
});
|
|
18839
|
+
return data;
|
|
18840
|
+
} catch (error) {
|
|
18841
|
+
import_utils95.logger.log({
|
|
18842
|
+
level: "error",
|
|
18843
|
+
message: `Error in getTrialBalance: ${error}`
|
|
18844
|
+
});
|
|
18845
|
+
throw new import_utils95.InternalServerError("Failed to get trial balance.");
|
|
18846
|
+
}
|
|
18847
|
+
}
|
|
18848
|
+
async function getBalanceSheet(options) {
|
|
18849
|
+
options.page = options.page && options.page > 0 ? options.page - 1 : 0;
|
|
18850
|
+
options.limit = options.limit ?? 10;
|
|
18851
|
+
try {
|
|
18852
|
+
options.org = new import_mongodb47.ObjectId(options.org);
|
|
18853
|
+
} catch (error) {
|
|
18854
|
+
throw new import_utils95.BadRequestError("Invalid organization ID.");
|
|
18855
|
+
}
|
|
18856
|
+
const cacheKey = (0, import_utils95.makeCacheKey)(namespace_collection, {
|
|
18857
|
+
type: "balance-sheet",
|
|
18858
|
+
org: String(options.org),
|
|
18859
|
+
fiscalYear: options.fiscalYear,
|
|
18860
|
+
from: options.from ?? "",
|
|
18861
|
+
to: options.to ?? "",
|
|
18862
|
+
limit: options.limit,
|
|
18863
|
+
page: options.page
|
|
18864
|
+
});
|
|
18865
|
+
try {
|
|
18866
|
+
const cachedData = await repo.getCache(cacheKey);
|
|
18867
|
+
if (cachedData) {
|
|
18868
|
+
return cachedData;
|
|
18869
|
+
}
|
|
18870
|
+
const query = {
|
|
18871
|
+
org: options.org,
|
|
18872
|
+
status: "active",
|
|
18873
|
+
childrenCount: 0
|
|
18874
|
+
};
|
|
18875
|
+
const pipeline = [
|
|
18876
|
+
{ $eq: ["$account", "$$account"] },
|
|
18877
|
+
{ $eq: ["$period.fiscalYear", options.fiscalYear] }
|
|
18878
|
+
];
|
|
18879
|
+
if (options.from !== void 0) {
|
|
18880
|
+
pipeline.push({ $gte: ["$period.fiscalMonth", options.from] });
|
|
18881
|
+
}
|
|
18882
|
+
if (options.to !== void 0) {
|
|
18883
|
+
pipeline.push({ $lte: ["$period.fiscalMonth", options.to] });
|
|
18884
|
+
}
|
|
18885
|
+
const accounts = await repo.collection.aggregate([
|
|
18886
|
+
{ $match: query },
|
|
18887
|
+
{ $sort: { path: 1 } },
|
|
18888
|
+
{ $skip: options.page * options.limit },
|
|
18889
|
+
{ $limit: options.limit },
|
|
18890
|
+
{
|
|
18891
|
+
$lookup: {
|
|
18892
|
+
from: "finance.account.balances",
|
|
18893
|
+
let: { account: "$_id" },
|
|
18894
|
+
pipeline: [
|
|
18895
|
+
{
|
|
18896
|
+
$match: {
|
|
18897
|
+
$expr: { $and: pipeline }
|
|
18898
|
+
}
|
|
18899
|
+
},
|
|
18900
|
+
{
|
|
18901
|
+
$group: {
|
|
18902
|
+
_id: "$account",
|
|
18903
|
+
debit: { $sum: "$closingDebit" },
|
|
18904
|
+
credit: { $sum: "$closingCredit" }
|
|
18905
|
+
}
|
|
18906
|
+
}
|
|
18907
|
+
],
|
|
18908
|
+
as: "balance"
|
|
18909
|
+
}
|
|
18910
|
+
},
|
|
18911
|
+
{
|
|
18912
|
+
$unwind: {
|
|
18913
|
+
path: "$balance",
|
|
18914
|
+
preserveNullAndEmptyArrays: true
|
|
18915
|
+
}
|
|
18916
|
+
},
|
|
18917
|
+
{
|
|
18918
|
+
$project: {
|
|
18919
|
+
name: 1,
|
|
18920
|
+
code: 1,
|
|
18921
|
+
type: 1,
|
|
18922
|
+
normalBalance: 1,
|
|
18923
|
+
isContra: 1,
|
|
18924
|
+
parent: 1,
|
|
18925
|
+
childrenCount: 1,
|
|
18926
|
+
debit: { $ifNull: ["$balance.debit", 0] },
|
|
18927
|
+
credit: { $ifNull: ["$balance.credit", 0] }
|
|
18928
|
+
}
|
|
18929
|
+
},
|
|
18930
|
+
{
|
|
18931
|
+
$match: {
|
|
18932
|
+
$or: [
|
|
18933
|
+
{ childrenCount: { $gt: 0 } },
|
|
18934
|
+
{ debit: { $ne: 0 } },
|
|
18935
|
+
{ credit: { $ne: 0 } }
|
|
18936
|
+
]
|
|
18937
|
+
}
|
|
18938
|
+
}
|
|
18939
|
+
]).toArray();
|
|
18940
|
+
const length = await repo.collection.countDocuments(query);
|
|
18941
|
+
const data = (0, import_utils95.paginate)(accounts, options.page, options.limit, length);
|
|
18942
|
+
repo.setCache(cacheKey, data, 300).catch((err) => {
|
|
18943
|
+
import_utils95.logger.log({
|
|
18944
|
+
level: "error",
|
|
18945
|
+
message: `Failed to set cache for getBalanceSheet: ${err.message}`
|
|
18946
|
+
});
|
|
18947
|
+
});
|
|
18948
|
+
return data;
|
|
18949
|
+
} catch (error) {
|
|
18950
|
+
import_utils95.logger.log({
|
|
18951
|
+
level: "error",
|
|
18952
|
+
message: `Error in getBalanceSheet: ${error}`
|
|
18953
|
+
});
|
|
18954
|
+
throw new import_utils95.InternalServerError("Failed to get balance sheet data.");
|
|
18955
|
+
}
|
|
18956
|
+
}
|
|
18720
18957
|
return {
|
|
18721
18958
|
createIndexes,
|
|
18722
18959
|
add,
|
|
@@ -18727,7 +18964,9 @@ function useChartOfAccountRepo() {
|
|
|
18727
18964
|
deleteById,
|
|
18728
18965
|
updateStatusById,
|
|
18729
18966
|
countByPath,
|
|
18730
|
-
updateChildrenCountById
|
|
18967
|
+
updateChildrenCountById,
|
|
18968
|
+
getTrialBalance,
|
|
18969
|
+
getBalanceSheet
|
|
18731
18970
|
};
|
|
18732
18971
|
}
|
|
18733
18972
|
|
|
@@ -18745,7 +18984,9 @@ function useChartOfAccountService() {
|
|
|
18745
18984
|
updateById: _updateById,
|
|
18746
18985
|
deleteById: _deleteById,
|
|
18747
18986
|
countByPath,
|
|
18748
|
-
updateChildrenCountById
|
|
18987
|
+
updateChildrenCountById,
|
|
18988
|
+
getTrialBalance: _getTrialBalance,
|
|
18989
|
+
getBalanceSheet: _getBalanceSheet
|
|
18749
18990
|
} = useChartOfAccountRepo();
|
|
18750
18991
|
async function add(value) {
|
|
18751
18992
|
const { error } = schemaChartOfAccountBase.validate(value);
|
|
@@ -18886,10 +19127,112 @@ function useChartOfAccountService() {
|
|
|
18886
19127
|
session.endSession();
|
|
18887
19128
|
}
|
|
18888
19129
|
}
|
|
19130
|
+
async function getTrialBalance(options) {
|
|
19131
|
+
const LIMIT = 100;
|
|
19132
|
+
const allAccounts = [];
|
|
19133
|
+
let page = 1;
|
|
19134
|
+
let totalPages = 1;
|
|
19135
|
+
do {
|
|
19136
|
+
const result = await _getTrialBalance({
|
|
19137
|
+
org: options.org,
|
|
19138
|
+
fiscalYear: options.fiscalYear,
|
|
19139
|
+
from: options.from,
|
|
19140
|
+
to: options.to,
|
|
19141
|
+
page,
|
|
19142
|
+
limit: LIMIT
|
|
19143
|
+
});
|
|
19144
|
+
allAccounts.push(...result.items);
|
|
19145
|
+
totalPages = result.pages;
|
|
19146
|
+
page++;
|
|
19147
|
+
} while (page <= totalPages);
|
|
19148
|
+
return allAccounts;
|
|
19149
|
+
}
|
|
19150
|
+
async function getBalanceSheet(options) {
|
|
19151
|
+
const LIMIT = 100;
|
|
19152
|
+
const allAccounts = [];
|
|
19153
|
+
let page = 1;
|
|
19154
|
+
let totalPages = 1;
|
|
19155
|
+
do {
|
|
19156
|
+
const result = await _getBalanceSheet({
|
|
19157
|
+
org: options.org,
|
|
19158
|
+
fiscalYear: options.fiscalYear,
|
|
19159
|
+
from: options.from,
|
|
19160
|
+
to: options.to,
|
|
19161
|
+
page,
|
|
19162
|
+
limit: LIMIT
|
|
19163
|
+
});
|
|
19164
|
+
allAccounts.push(...result.items);
|
|
19165
|
+
totalPages = result.pages;
|
|
19166
|
+
page++;
|
|
19167
|
+
} while (page <= totalPages);
|
|
19168
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19169
|
+
const section = (type) => {
|
|
19170
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19171
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19172
|
+
return { accounts, total };
|
|
19173
|
+
};
|
|
19174
|
+
const assets = section("asset");
|
|
19175
|
+
const liabilities = section("liability");
|
|
19176
|
+
const equity = section("equity");
|
|
19177
|
+
const incomeTotal = allAccounts.filter((a) => a.type === "income").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19178
|
+
const expenseTotal = allAccounts.filter((a) => a.type === "expense").reduce((sum, a) => sum + netBalance(a), 0);
|
|
19179
|
+
const netIncome = incomeTotal - expenseTotal;
|
|
19180
|
+
const totalEquity = equity.total + netIncome;
|
|
19181
|
+
const totalLiabilitiesAndEquity = liabilities.total + totalEquity;
|
|
19182
|
+
return {
|
|
19183
|
+
assets: assets.accounts,
|
|
19184
|
+
liabilities: liabilities.accounts,
|
|
19185
|
+
equity: equity.accounts,
|
|
19186
|
+
netIncome,
|
|
19187
|
+
totalAssets: assets.total,
|
|
19188
|
+
totalLiabilities: liabilities.total,
|
|
19189
|
+
totalEquity,
|
|
19190
|
+
totalLiabilitiesAndEquity,
|
|
19191
|
+
isBalanced: assets.total === totalLiabilitiesAndEquity
|
|
19192
|
+
};
|
|
19193
|
+
}
|
|
19194
|
+
async function getIncomeStatement(options) {
|
|
19195
|
+
const LIMIT = 100;
|
|
19196
|
+
const allAccounts = [];
|
|
19197
|
+
let page = 1;
|
|
19198
|
+
let totalPages = 1;
|
|
19199
|
+
do {
|
|
19200
|
+
const result = await _getBalanceSheet({
|
|
19201
|
+
org: options.org,
|
|
19202
|
+
fiscalYear: options.fiscalYear,
|
|
19203
|
+
from: options.from,
|
|
19204
|
+
to: options.to,
|
|
19205
|
+
page,
|
|
19206
|
+
limit: LIMIT
|
|
19207
|
+
});
|
|
19208
|
+
allAccounts.push(...result.items);
|
|
19209
|
+
totalPages = result.pages;
|
|
19210
|
+
page++;
|
|
19211
|
+
} while (page <= totalPages);
|
|
19212
|
+
const netBalance = (a) => a.normalBalance === "debit" ? a.debit - a.credit : a.credit - a.debit;
|
|
19213
|
+
const section = (type) => {
|
|
19214
|
+
const accounts = allAccounts.filter((a) => a.type === type).map((a) => ({ ...a, balance: netBalance(a) }));
|
|
19215
|
+
const total = accounts.reduce((sum, a) => sum + a.balance, 0);
|
|
19216
|
+
return { accounts, total };
|
|
19217
|
+
};
|
|
19218
|
+
const revenues = section("income");
|
|
19219
|
+
const expenses = section("expense");
|
|
19220
|
+
const netIncome = revenues.total - expenses.total;
|
|
19221
|
+
return {
|
|
19222
|
+
revenues: revenues.accounts,
|
|
19223
|
+
expenses: expenses.accounts,
|
|
19224
|
+
totalRevenues: revenues.total,
|
|
19225
|
+
totalExpenses: expenses.total,
|
|
19226
|
+
netIncome
|
|
19227
|
+
};
|
|
19228
|
+
}
|
|
18889
19229
|
return {
|
|
18890
19230
|
add,
|
|
18891
19231
|
updateById,
|
|
18892
|
-
deleteById
|
|
19232
|
+
deleteById,
|
|
19233
|
+
getTrialBalance,
|
|
19234
|
+
getBalanceSheet,
|
|
19235
|
+
getIncomeStatement
|
|
18893
19236
|
};
|
|
18894
19237
|
}
|
|
18895
19238
|
|
|
@@ -18904,7 +19247,10 @@ function useChartOfAccountController() {
|
|
|
18904
19247
|
const {
|
|
18905
19248
|
add: _add,
|
|
18906
19249
|
updateById: _updateById,
|
|
18907
|
-
deleteById: _deleteById
|
|
19250
|
+
deleteById: _deleteById,
|
|
19251
|
+
getTrialBalance: _getTrialBalance,
|
|
19252
|
+
getBalanceSheet: _getBalanceSheet,
|
|
19253
|
+
getIncomeStatement: _getIncomeStatement
|
|
18908
19254
|
} = useChartOfAccountService();
|
|
18909
19255
|
async function add(req, res, next) {
|
|
18910
19256
|
const value = req.body;
|
|
@@ -19060,6 +19406,75 @@ function useChartOfAccountController() {
|
|
|
19060
19406
|
next(error);
|
|
19061
19407
|
}
|
|
19062
19408
|
}
|
|
19409
|
+
async function getTrialBalance(req, res, next) {
|
|
19410
|
+
const org = req.params.org ?? "";
|
|
19411
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19412
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : NaN;
|
|
19413
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : NaN;
|
|
19414
|
+
const validation = import_joi80.default.object({
|
|
19415
|
+
org: import_joi80.default.string().hex().required(),
|
|
19416
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19417
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19418
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19419
|
+
});
|
|
19420
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19421
|
+
if (error) {
|
|
19422
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19423
|
+
return;
|
|
19424
|
+
}
|
|
19425
|
+
try {
|
|
19426
|
+
const accounts = await _getTrialBalance({ org, fiscalYear, from, to });
|
|
19427
|
+
res.json(accounts);
|
|
19428
|
+
} catch (error2) {
|
|
19429
|
+
next(error2);
|
|
19430
|
+
}
|
|
19431
|
+
}
|
|
19432
|
+
async function getBalanceSheet(req, res, next) {
|
|
19433
|
+
const org = req.params.org ?? "";
|
|
19434
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19435
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19436
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19437
|
+
const validation = import_joi80.default.object({
|
|
19438
|
+
org: import_joi80.default.string().hex().required(),
|
|
19439
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19440
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19441
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19442
|
+
});
|
|
19443
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19444
|
+
if (error) {
|
|
19445
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19446
|
+
return;
|
|
19447
|
+
}
|
|
19448
|
+
try {
|
|
19449
|
+
const data = await _getBalanceSheet({ org, fiscalYear, from, to });
|
|
19450
|
+
res.json(data);
|
|
19451
|
+
} catch (error2) {
|
|
19452
|
+
next(error2);
|
|
19453
|
+
}
|
|
19454
|
+
}
|
|
19455
|
+
async function getIncomeStatement(req, res, next) {
|
|
19456
|
+
const org = req.params.org ?? "";
|
|
19457
|
+
const fiscalYear = typeof req.params.fiscalYear === "string" ? Number(req.params.fiscalYear) : NaN;
|
|
19458
|
+
const from = typeof req.query.from === "string" ? Number(req.query.from) : void 0;
|
|
19459
|
+
const to = typeof req.query.to === "string" ? Number(req.query.to) : void 0;
|
|
19460
|
+
const validation = import_joi80.default.object({
|
|
19461
|
+
org: import_joi80.default.string().hex().required(),
|
|
19462
|
+
fiscalYear: import_joi80.default.number().required(),
|
|
19463
|
+
from: import_joi80.default.number().optional().allow("", null),
|
|
19464
|
+
to: import_joi80.default.number().optional().allow("", null)
|
|
19465
|
+
});
|
|
19466
|
+
const { error } = validation.validate({ ...req.params, ...req.query });
|
|
19467
|
+
if (error) {
|
|
19468
|
+
next(new import_utils97.BadRequestError(error.message));
|
|
19469
|
+
return;
|
|
19470
|
+
}
|
|
19471
|
+
try {
|
|
19472
|
+
const data = await _getIncomeStatement({ org, fiscalYear, from, to });
|
|
19473
|
+
res.json(data);
|
|
19474
|
+
} catch (error2) {
|
|
19475
|
+
next(error2);
|
|
19476
|
+
}
|
|
19477
|
+
}
|
|
19063
19478
|
async function updateStatusById(req, res, next) {
|
|
19064
19479
|
const id = req.params.id;
|
|
19065
19480
|
const status2 = req.params.status;
|
|
@@ -19087,7 +19502,10 @@ function useChartOfAccountController() {
|
|
|
19087
19502
|
getById,
|
|
19088
19503
|
updateById,
|
|
19089
19504
|
deleteById,
|
|
19090
|
-
updateStatusById
|
|
19505
|
+
updateStatusById,
|
|
19506
|
+
getTrialBalance,
|
|
19507
|
+
getBalanceSheet,
|
|
19508
|
+
getIncomeStatement
|
|
19091
19509
|
};
|
|
19092
19510
|
}
|
|
19093
19511
|
|
|
@@ -19101,7 +19519,9 @@ var schemaAccountBalance = import_joi81.default.object({
|
|
|
19101
19519
|
accountType: import_joi81.default.string().required(),
|
|
19102
19520
|
period: import_joi81.default.object({
|
|
19103
19521
|
fiscalYear: import_joi81.default.number().required(),
|
|
19104
|
-
|
|
19522
|
+
fiscalMonth: import_joi81.default.number().min(1).max(12).required(),
|
|
19523
|
+
year: import_joi81.default.number().required(),
|
|
19524
|
+
month: import_joi81.default.number().min(1).max(12).required()
|
|
19105
19525
|
}).required(),
|
|
19106
19526
|
openingDebit: import_joi81.default.number().required(),
|
|
19107
19527
|
openingCredit: import_joi81.default.number().required(),
|
|
@@ -19158,10 +19578,18 @@ function useAccountBalanceRepo() {
|
|
|
19158
19578
|
org: 1,
|
|
19159
19579
|
account: 1,
|
|
19160
19580
|
"period.fiscalYear": 1,
|
|
19161
|
-
"period.
|
|
19581
|
+
"period.fiscalMonth": 1
|
|
19162
19582
|
},
|
|
19163
19583
|
unique: true,
|
|
19164
|
-
name: "
|
|
19584
|
+
name: "unique_balance_per_account_fiscal_month"
|
|
19585
|
+
},
|
|
19586
|
+
{
|
|
19587
|
+
key: {
|
|
19588
|
+
org: 1,
|
|
19589
|
+
"period.fiscalYear": 1,
|
|
19590
|
+
"period.fiscalMonth": 1
|
|
19591
|
+
},
|
|
19592
|
+
name: "balance_reporting_fiscal_month"
|
|
19165
19593
|
}
|
|
19166
19594
|
]);
|
|
19167
19595
|
} catch (error) {
|
|
@@ -19220,7 +19648,7 @@ function useAccountBalanceRepo() {
|
|
|
19220
19648
|
}
|
|
19221
19649
|
const items = await repo.collection.aggregate([
|
|
19222
19650
|
{ $match: query },
|
|
19223
|
-
{ $sort: { "period.fiscalYear": -1 } },
|
|
19651
|
+
{ $sort: { "period.fiscalYear": -1, "period.fiscalMonth": -1 } },
|
|
19224
19652
|
{ $skip: options.page * options.limit },
|
|
19225
19653
|
{ $limit: options.limit }
|
|
19226
19654
|
]).toArray();
|
|
@@ -19298,13 +19726,13 @@ function useAccountBalanceRepo() {
|
|
|
19298
19726
|
account,
|
|
19299
19727
|
org,
|
|
19300
19728
|
"period.fiscalYear": options.fiscalYear,
|
|
19301
|
-
"period.
|
|
19729
|
+
"period.fiscalMonth": options.fiscalMonth
|
|
19302
19730
|
};
|
|
19303
19731
|
const cacheKey = (0, import_utils99.makeCacheKey)(namespace_collection, {
|
|
19304
19732
|
account: String(account),
|
|
19305
19733
|
org: String(org),
|
|
19306
19734
|
fiscalYear: options.fiscalYear,
|
|
19307
|
-
|
|
19735
|
+
fiscalMonth: options.fiscalMonth
|
|
19308
19736
|
});
|
|
19309
19737
|
try {
|
|
19310
19738
|
const cached = await repo.getCache(cacheKey);
|
|
@@ -19353,7 +19781,7 @@ function useAccountBalanceRepo() {
|
|
|
19353
19781
|
try {
|
|
19354
19782
|
return await repo.collection.find(
|
|
19355
19783
|
{ account, org, "period.fiscalYear": options.fiscalYear },
|
|
19356
|
-
{ sort: { "period.
|
|
19784
|
+
{ sort: { "period.fiscalMonth": 1 } }
|
|
19357
19785
|
).toArray();
|
|
19358
19786
|
} catch (error) {
|
|
19359
19787
|
if (error instanceof import_utils99.AppError) {
|
|
@@ -19362,7 +19790,7 @@ function useAccountBalanceRepo() {
|
|
|
19362
19790
|
throw new import_utils99.InternalServerError("Failed to get account balances by year.");
|
|
19363
19791
|
}
|
|
19364
19792
|
}
|
|
19365
|
-
async function updateById(account, org, fiscalYear,
|
|
19793
|
+
async function updateById(account, org, fiscalYear, fiscalMonth, options, session) {
|
|
19366
19794
|
const { error } = import_joi82.default.object({
|
|
19367
19795
|
openingDebit: import_joi82.default.number().min(0).optional(),
|
|
19368
19796
|
openingCredit: import_joi82.default.number().min(0).optional(),
|
|
@@ -19393,7 +19821,7 @@ function useAccountBalanceRepo() {
|
|
|
19393
19821
|
account,
|
|
19394
19822
|
org,
|
|
19395
19823
|
"period.fiscalYear": fiscalYear,
|
|
19396
|
-
"period.
|
|
19824
|
+
"period.fiscalMonth": fiscalMonth
|
|
19397
19825
|
},
|
|
19398
19826
|
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } },
|
|
19399
19827
|
{ session, upsert: true }
|
|
@@ -21381,20 +21809,6 @@ function useJournalService() {
|
|
|
21381
21809
|
);
|
|
21382
21810
|
}
|
|
21383
21811
|
session.startTransaction();
|
|
21384
|
-
const MONTHS = [
|
|
21385
|
-
"January",
|
|
21386
|
-
"February",
|
|
21387
|
-
"March",
|
|
21388
|
-
"April",
|
|
21389
|
-
"May",
|
|
21390
|
-
"June",
|
|
21391
|
-
"July",
|
|
21392
|
-
"August",
|
|
21393
|
-
"September",
|
|
21394
|
-
"October",
|
|
21395
|
-
"November",
|
|
21396
|
-
"December"
|
|
21397
|
-
];
|
|
21398
21812
|
if (status2 === "posted") {
|
|
21399
21813
|
await updateStatusByJournal(_id, status2, session);
|
|
21400
21814
|
await _updateStatusById(_id, status2, session);
|
|
@@ -21409,13 +21823,30 @@ function useJournalService() {
|
|
|
21409
21823
|
const linesToPost = await getJournalLinesByEntry(_id);
|
|
21410
21824
|
const journalDate = new Date(journalEntry.date);
|
|
21411
21825
|
const fiscalYear = Number(businessProfile.currentFiscalYear);
|
|
21412
|
-
const
|
|
21826
|
+
const calendarYear = journalDate.getFullYear();
|
|
21827
|
+
const calendarMonth = journalDate.getMonth() + 1;
|
|
21828
|
+
const FISCAL_MONTHS = [
|
|
21829
|
+
"January",
|
|
21830
|
+
"February",
|
|
21831
|
+
"March",
|
|
21832
|
+
"April",
|
|
21833
|
+
"May",
|
|
21834
|
+
"June",
|
|
21835
|
+
"July",
|
|
21836
|
+
"August",
|
|
21837
|
+
"September",
|
|
21838
|
+
"October",
|
|
21839
|
+
"November",
|
|
21840
|
+
"December"
|
|
21841
|
+
];
|
|
21842
|
+
const fiscalStartIdx = FISCAL_MONTHS.indexOf(businessProfile.fiscalYearStart);
|
|
21843
|
+
const fiscalMonth = (calendarMonth - 1 - fiscalStartIdx + 12) % 12 + 1;
|
|
21413
21844
|
for (const line of linesToPost) {
|
|
21414
21845
|
const existingBalance = await getAccountBalance({
|
|
21415
21846
|
account: String(line.account),
|
|
21416
21847
|
org: String(journalEntry.org),
|
|
21417
21848
|
fiscalYear,
|
|
21418
|
-
|
|
21849
|
+
fiscalMonth
|
|
21419
21850
|
});
|
|
21420
21851
|
if (existingBalance) {
|
|
21421
21852
|
const movementDebit = existingBalance.movementDebit + (line.debit || 0);
|
|
@@ -21430,7 +21861,7 @@ function useJournalService() {
|
|
|
21430
21861
|
String(line.account),
|
|
21431
21862
|
String(journalEntry.org),
|
|
21432
21863
|
fiscalYear,
|
|
21433
|
-
|
|
21864
|
+
fiscalMonth,
|
|
21434
21865
|
{
|
|
21435
21866
|
movementDebit,
|
|
21436
21867
|
movementCredit,
|
|
@@ -21447,10 +21878,7 @@ function useJournalService() {
|
|
|
21447
21878
|
org: String(journalEntry.org),
|
|
21448
21879
|
fiscalYear
|
|
21449
21880
|
});
|
|
21450
|
-
const
|
|
21451
|
-
const previousRecord = allYearBalances.filter((r) => MONTHS.indexOf(r.period.month) < currentMonthIdx).sort(
|
|
21452
|
-
(a, b) => MONTHS.indexOf(b.period.month) - MONTHS.indexOf(a.period.month)
|
|
21453
|
-
)[0];
|
|
21881
|
+
const previousRecord = allYearBalances.filter((r) => r.period.fiscalMonth < fiscalMonth).sort((a, b) => b.period.fiscalMonth - a.period.fiscalMonth)[0];
|
|
21454
21882
|
const openingDebit = previousRecord?.closingDebit ?? 0;
|
|
21455
21883
|
const openingCredit = previousRecord?.closingCredit ?? 0;
|
|
21456
21884
|
const movementDebit = line.debit || 0;
|
|
@@ -21466,7 +21894,7 @@ function useJournalService() {
|
|
|
21466
21894
|
org: String(journalEntry.org),
|
|
21467
21895
|
account: String(line.account),
|
|
21468
21896
|
accountType: line.accountType || "",
|
|
21469
|
-
period: { fiscalYear, month },
|
|
21897
|
+
period: { fiscalYear, fiscalMonth, year: calendarYear, month: calendarMonth },
|
|
21470
21898
|
openingDebit,
|
|
21471
21899
|
openingCredit,
|
|
21472
21900
|
movementDebit,
|