@goweekdays/core 2.15.0 → 2.15.1

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/dist/index.mjs CHANGED
@@ -19145,7 +19145,12 @@ function useAccountBalanceRepo() {
19145
19145
  { key: { account: 1 } },
19146
19146
  { key: { "period.fiscalYear": 1 } },
19147
19147
  {
19148
- key: { org: 1, account: 1, "period.fiscalYear": 1, "period.month": 1 },
19148
+ key: {
19149
+ org: 1,
19150
+ account: 1,
19151
+ "period.fiscalYear": 1,
19152
+ "period.month": 1
19153
+ },
19149
19154
  unique: true,
19150
19155
  name: "unique_balance_per_account_month"
19151
19156
  }
@@ -19320,9 +19325,7 @@ function useAccountBalanceRepo() {
19320
19325
  if (error instanceof AppError43) {
19321
19326
  throw error;
19322
19327
  }
19323
- throw new InternalServerError39(
19324
- "Failed to get account balance."
19325
- );
19328
+ throw new InternalServerError39("Failed to get account balance.");
19326
19329
  }
19327
19330
  }
19328
19331
  async function getYearBalancesByAccount(options) {
@@ -19347,9 +19350,7 @@ function useAccountBalanceRepo() {
19347
19350
  if (error instanceof AppError43) {
19348
19351
  throw error;
19349
19352
  }
19350
- throw new InternalServerError39(
19351
- "Failed to get account balances by year."
19352
- );
19353
+ throw new InternalServerError39("Failed to get account balances by year.");
19353
19354
  }
19354
19355
  }
19355
19356
  async function updateById(account, org, fiscalYear, month, options, session) {
@@ -19435,7 +19436,7 @@ var journalTypes = [
19435
19436
  var schemaJournalBase = {
19436
19437
  date: Joi83.date().required(),
19437
19438
  type: Joi83.string().allow(...journalTypes).required(),
19438
- transaction: Joi83.string().required(),
19439
+ transaction: Joi83.string().hex().required(),
19439
19440
  customer: Joi83.string().hex().optional().allow("", null),
19440
19441
  description: Joi83.string().required(),
19441
19442
  invoiceNumber: Joi83.string().optional().allow("", null)
@@ -19452,6 +19453,7 @@ var schemaJournalRepo = Joi83.object({
19452
19453
  id: Joi83.string().required(),
19453
19454
  createdBy: Joi83.string().hex().required(),
19454
19455
  createdByName: Joi83.string().required(),
19456
+ transactionName: Joi83.string().required(),
19455
19457
  customerName: Joi83.string().optional().allow("", null),
19456
19458
  status: Joi83.string().valid(...JournalStatuses).required(),
19457
19459
  reversedEntry: Joi83.string().hex().optional().allow("", null),
@@ -19463,6 +19465,7 @@ var schemaJournalRepoUpdate = Joi83.object({
19463
19465
  date: Joi83.date().optional().allow("", null),
19464
19466
  type: Joi83.string().allow(...journalTypes).optional().allow("", null),
19465
19467
  transaction: Joi83.string().optional().allow("", null),
19468
+ transactionName: Joi83.string().optional().allow("", null),
19466
19469
  description: Joi83.string().optional().allow("", null),
19467
19470
  status: Joi83.string().valid(...JournalStatuses).optional().allow("", null),
19468
19471
  customerName: Joi83.string().optional().allow("", null),
@@ -19491,6 +19494,11 @@ function modelJournal(data) {
19491
19494
  } catch (error2) {
19492
19495
  throw new BadRequestError93(`Invalid org ID: ${data.org}`);
19493
19496
  }
19497
+ try {
19498
+ data.transaction = new ObjectId50(data.transaction);
19499
+ } catch (error2) {
19500
+ throw new BadRequestError93(`Invalid transaction ID: ${data.transaction}`);
19501
+ }
19494
19502
  try {
19495
19503
  data.createdBy = new ObjectId50(data.createdBy);
19496
19504
  } catch (error2) {
@@ -19535,6 +19543,7 @@ function modelJournal(data) {
19535
19543
  org: data.org,
19536
19544
  type: data.type,
19537
19545
  transaction: data.transaction,
19546
+ transactionName: data.transactionName ?? "",
19538
19547
  date,
19539
19548
  invoiceNumber: data.invoiceNumber ?? "",
19540
19549
  customer: data.customer ?? "",
@@ -19839,6 +19848,24 @@ function useJournalRepo() {
19839
19848
  throw new InternalServerError40("Failed to update journal status.");
19840
19849
  }
19841
19850
  }
19851
+ async function existsByTransactionId(org, transactionId) {
19852
+ try {
19853
+ org = new ObjectId51(org);
19854
+ } catch {
19855
+ throw new BadRequestError94("Invalid org ID.");
19856
+ }
19857
+ try {
19858
+ transactionId = new ObjectId51(transactionId);
19859
+ } catch {
19860
+ throw new BadRequestError94("Invalid transaction ID.");
19861
+ }
19862
+ const count = await repo.collection.countDocuments({
19863
+ org,
19864
+ transaction: transactionId,
19865
+ status: { $ne: "voided" }
19866
+ });
19867
+ return count > 0;
19868
+ }
19842
19869
  return {
19843
19870
  createIndexes,
19844
19871
  delCachedData: repo.delCachedData,
@@ -19847,12 +19874,13 @@ function useJournalRepo() {
19847
19874
  getById,
19848
19875
  updateById,
19849
19876
  deleteById,
19850
- updateStatusById
19877
+ updateStatusById,
19878
+ existsByTransactionId
19851
19879
  };
19852
19880
  }
19853
19881
 
19854
19882
  // src/resources/finance-journal/finance.journal.service.ts
19855
- import Joi90 from "joi";
19883
+ import Joi93 from "joi";
19856
19884
 
19857
19885
  // src/resources/finance-journal-line/finance.journal.line.model.ts
19858
19886
  import { BadRequestError as BadRequestError95 } from "@goweekdays/utils";
@@ -20192,6 +20220,23 @@ function useJournalLineRepo() {
20192
20220
  throw new InternalServerError41("Failed to delete journal line.");
20193
20221
  }
20194
20222
  }
20223
+ async function updateBalanceById(_id, balance, session) {
20224
+ try {
20225
+ _id = new ObjectId53(_id);
20226
+ } catch (error) {
20227
+ throw new BadRequestError96("Invalid Journal Line ID.");
20228
+ }
20229
+ try {
20230
+ await collection.updateOne(
20231
+ { _id },
20232
+ { $set: { balance, updatedAt: /* @__PURE__ */ new Date() } },
20233
+ { session }
20234
+ );
20235
+ delCachedData();
20236
+ } catch (error) {
20237
+ throw new InternalServerError41("Failed to update journal line balance.");
20238
+ }
20239
+ }
20195
20240
  async function updateStatusByJournal(journalEntry, status2, session) {
20196
20241
  const validation = Joi86.object({
20197
20242
  journalEntry: Joi86.string().hex().required(),
@@ -20232,6 +20277,7 @@ function useJournalLineRepo() {
20232
20277
  getById,
20233
20278
  getByEntry,
20234
20279
  updateById,
20280
+ updateBalanceById,
20235
20281
  deleteById,
20236
20282
  updateStatusByJournal
20237
20283
  };
@@ -20239,10 +20285,10 @@ function useJournalLineRepo() {
20239
20285
 
20240
20286
  // src/resources/finance-journal/finance.journal.service.ts
20241
20287
  import {
20242
- AppError as AppError47,
20243
- BadRequestError as BadRequestError101,
20244
- InternalServerError as InternalServerError43,
20245
- NotFoundError as NotFoundError6,
20288
+ AppError as AppError49,
20289
+ BadRequestError as BadRequestError105,
20290
+ InternalServerError as InternalServerError45,
20291
+ NotFoundError as NotFoundError7,
20246
20292
  useAtlas as useAtlas16
20247
20293
  } from "@goweekdays/utils";
20248
20294
 
@@ -20661,6 +20707,542 @@ function useJournalLogRepo() {
20661
20707
  import Joi89 from "joi";
20662
20708
  import { BadRequestError as BadRequestError100, logger as logger51 } from "@goweekdays/utils";
20663
20709
 
20710
+ // src/resources/finance-journal-transaction/finance.journal.transaction.model.ts
20711
+ import { BadRequestError as BadRequestError101 } from "@goweekdays/utils";
20712
+ import Joi90 from "joi";
20713
+ import { ObjectId as ObjectId56 } from "mongodb";
20714
+ var schemaJournalTransactionAccount = Joi90.object({
20715
+ title: Joi90.string().required(),
20716
+ value: Joi90.string().hex().required()
20717
+ });
20718
+ var schemaJournalTransactionBase = {
20719
+ type: Joi90.string().valid(...journalTypes).required(),
20720
+ code: Joi90.string().required(),
20721
+ title: Joi90.string().required(),
20722
+ debits: Joi90.array().items(schemaJournalTransactionAccount).min(1).required(),
20723
+ credits: Joi90.array().items(schemaJournalTransactionAccount).min(1).required(),
20724
+ template: Joi90.boolean().required(),
20725
+ description: Joi90.string().optional().allow("", null)
20726
+ };
20727
+ var schemaJournalTransactionCtrl = Joi90.object({
20728
+ ...schemaJournalTransactionBase,
20729
+ org: Joi90.string().hex().required(),
20730
+ createdBy: Joi90.string().hex().required()
20731
+ });
20732
+ var schemaJournalTransactionCtrlUpdate = Joi90.object({
20733
+ code: Joi90.string().optional(),
20734
+ title: Joi90.string().optional(),
20735
+ debits: Joi90.array().items(schemaJournalTransactionAccount).min(1).optional(),
20736
+ credits: Joi90.array().items(schemaJournalTransactionAccount).min(1).optional(),
20737
+ template: Joi90.boolean().optional(),
20738
+ description: Joi90.string().optional().allow("", null)
20739
+ });
20740
+ var schemaJournalTransactionRepo = Joi90.object({
20741
+ ...schemaJournalTransactionBase,
20742
+ org: Joi90.string().hex().required(),
20743
+ createdBy: Joi90.string().hex().required(),
20744
+ createdByName: Joi90.string().optional().allow("", null)
20745
+ });
20746
+ var schemaJournalTransactionGetAll = Joi90.object({
20747
+ org: Joi90.string().hex().required(),
20748
+ type: Joi90.string().optional().allow("", null),
20749
+ search: Joi90.string().optional().allow("", null),
20750
+ page: Joi90.number().optional().allow("", null),
20751
+ limit: Joi90.number().max(100).optional().allow("", null)
20752
+ });
20753
+ function modelJournalTransaction(data) {
20754
+ const { error } = schemaJournalTransactionRepo.validate(data);
20755
+ if (error) {
20756
+ throw new BadRequestError101(
20757
+ `Invalid journal transaction data: ${error.message}`
20758
+ );
20759
+ }
20760
+ try {
20761
+ data.org = new ObjectId56(data.org);
20762
+ } catch (error2) {
20763
+ throw new BadRequestError101(`Invalid org ID: ${data.org}`);
20764
+ }
20765
+ try {
20766
+ data.createdBy = new ObjectId56(data.createdBy);
20767
+ } catch (error2) {
20768
+ throw new BadRequestError101(`Invalid createdBy ID: ${data.createdBy}`);
20769
+ }
20770
+ for (let i = 0; i < data.debits.length; i++) {
20771
+ try {
20772
+ data.debits[i].value = new ObjectId56(data.debits[i].value);
20773
+ } catch (error2) {
20774
+ throw new BadRequestError101(`Invalid debit account ID at index ${i}`);
20775
+ }
20776
+ }
20777
+ for (let i = 0; i < data.credits.length; i++) {
20778
+ try {
20779
+ data.credits[i].value = new ObjectId56(data.credits[i].value);
20780
+ } catch (error2) {
20781
+ throw new BadRequestError101(`Invalid credit account ID at index ${i}`);
20782
+ }
20783
+ }
20784
+ const now = /* @__PURE__ */ new Date();
20785
+ return {
20786
+ _id: data._id,
20787
+ org: data.org,
20788
+ type: data.type,
20789
+ code: data.code,
20790
+ title: data.title,
20791
+ debits: data.debits,
20792
+ credits: data.credits,
20793
+ template: data.template ?? false,
20794
+ description: data.description ?? "",
20795
+ createdBy: data.createdBy,
20796
+ createdByName: data.createdByName ?? "",
20797
+ createdAt: data.createdAt ?? now,
20798
+ updatedAt: data.updatedAt ?? ""
20799
+ };
20800
+ }
20801
+
20802
+ // src/resources/finance-journal-transaction/finance.journal.transaction.repository.ts
20803
+ import {
20804
+ AppError as AppError47,
20805
+ BadRequestError as BadRequestError102,
20806
+ makeCacheKey as makeCacheKey32,
20807
+ paginate as paginate28,
20808
+ logger as logger52,
20809
+ InternalServerError as InternalServerError43,
20810
+ useRepo as useRepo31
20811
+ } from "@goweekdays/utils";
20812
+ import { ObjectId as ObjectId57 } from "mongodb";
20813
+ function useJournalTransactionRepo() {
20814
+ const namespace_collection = "finance.journal.transactions";
20815
+ const repo = useRepo31(namespace_collection);
20816
+ async function createIndexes() {
20817
+ try {
20818
+ await repo.collection.createIndexes([
20819
+ { key: { org: 1, type: 1, _id: 1 } },
20820
+ { key: { org: 1 } },
20821
+ { key: { type: 1 } },
20822
+ { key: { code: 1 } },
20823
+ { key: { org: 1, type: 1 } },
20824
+ {
20825
+ key: {
20826
+ title: "text",
20827
+ code: "text",
20828
+ description: "text"
20829
+ }
20830
+ },
20831
+ {
20832
+ key: { org: 1, type: 1, code: 1 },
20833
+ unique: true,
20834
+ name: "unique_org_type_code"
20835
+ }
20836
+ ]);
20837
+ } catch (error) {
20838
+ throw new Error("Failed to create index on journal transactions.");
20839
+ }
20840
+ }
20841
+ async function add(value, session) {
20842
+ try {
20843
+ value = modelJournalTransaction(value);
20844
+ const res = await repo.collection.insertOne(value, { session });
20845
+ repo.delCachedData();
20846
+ return res.insertedId;
20847
+ } catch (error) {
20848
+ logger52.log({ level: "error", message: error.message });
20849
+ throw new BadRequestError102(
20850
+ `Failed to create journal transaction: ${error.message}`
20851
+ );
20852
+ }
20853
+ }
20854
+ async function getAll(options) {
20855
+ options.page = options.page && options.page > 0 ? options.page - 1 : 0;
20856
+ options.limit = options.limit ?? 10;
20857
+ options.search = options.search ?? "";
20858
+ const { error } = schemaJournalTransactionGetAll.validate(options);
20859
+ if (error) {
20860
+ throw new BadRequestError102(`Invalid query parameters: ${error.message}`);
20861
+ }
20862
+ const query = {};
20863
+ const cacheKeyOptions = {
20864
+ page: options.page,
20865
+ limit: options.limit
20866
+ };
20867
+ try {
20868
+ query.org = new ObjectId57(options.org);
20869
+ cacheKeyOptions.org = String(options.org);
20870
+ } catch (error2) {
20871
+ throw new BadRequestError102("Invalid organization ID.");
20872
+ }
20873
+ if (options.type) {
20874
+ query.type = options.type;
20875
+ cacheKeyOptions.type = options.type;
20876
+ }
20877
+ if (options.search) {
20878
+ query.$text = { $search: options.search };
20879
+ cacheKeyOptions.search = options.search;
20880
+ }
20881
+ const cacheKey = makeCacheKey32(namespace_collection, cacheKeyOptions);
20882
+ logger52.log({
20883
+ level: "info",
20884
+ message: `Cache key for getAll journal transactions: ${cacheKey}`
20885
+ });
20886
+ try {
20887
+ const cached = await repo.getCache(cacheKey);
20888
+ if (cached) {
20889
+ logger52.log({
20890
+ level: "info",
20891
+ message: `Cache hit for getAll journal transactions: ${cacheKey}`
20892
+ });
20893
+ return cached;
20894
+ }
20895
+ const items = await repo.collection.aggregate([
20896
+ { $match: query },
20897
+ { $sort: { title: 1 } },
20898
+ { $skip: options.page * options.limit },
20899
+ { $limit: options.limit }
20900
+ ]).toArray();
20901
+ const length = await repo.collection.countDocuments(query);
20902
+ const data = paginate28(items, options.page, options.limit, length);
20903
+ repo.setCache(cacheKey, data, 600).then(() => {
20904
+ logger52.log({
20905
+ level: "info",
20906
+ message: `Cache set for getAll journal transactions: ${cacheKey}`
20907
+ });
20908
+ }).catch((err) => {
20909
+ logger52.log({
20910
+ level: "error",
20911
+ message: `Failed to set cache for getAll journal transactions: ${err.message}`
20912
+ });
20913
+ });
20914
+ return data;
20915
+ } catch (error2) {
20916
+ logger52.log({ level: "error", message: `${error2}` });
20917
+ throw error2;
20918
+ }
20919
+ }
20920
+ async function getByOrgTypeId(options) {
20921
+ try {
20922
+ options._id = new ObjectId57(options._id);
20923
+ } catch (error) {
20924
+ throw new BadRequestError102("Invalid ID.");
20925
+ }
20926
+ try {
20927
+ options.org = new ObjectId57(options.org);
20928
+ } catch (error) {
20929
+ throw new BadRequestError102("Invalid organization ID.");
20930
+ }
20931
+ const cacheKey = makeCacheKey32(namespace_collection, {
20932
+ org: String(options.org),
20933
+ type: options.type,
20934
+ _id: String(options._id),
20935
+ tag: "org_type_id"
20936
+ });
20937
+ try {
20938
+ const cached = await repo.getCache(cacheKey);
20939
+ if (cached) {
20940
+ logger52.log({
20941
+ level: "info",
20942
+ message: `Cache hit for get by org + type + id journal transaction: ${cacheKey}`
20943
+ });
20944
+ return cached;
20945
+ }
20946
+ const result = await repo.collection.findOne({
20947
+ _id: options._id,
20948
+ org: options.org,
20949
+ type: options.type
20950
+ });
20951
+ repo.setCache(cacheKey, result, 300).then(() => {
20952
+ logger52.log({
20953
+ level: "info",
20954
+ message: `Cache set for journal transaction by org + type + id: ${cacheKey}`
20955
+ });
20956
+ }).catch((err) => {
20957
+ logger52.log({
20958
+ level: "error",
20959
+ message: `Failed to set cache for journal transaction by org + type + id: ${err.message}`
20960
+ });
20961
+ });
20962
+ return result;
20963
+ } catch (error) {
20964
+ if (error instanceof AppError47) {
20965
+ throw error;
20966
+ } else {
20967
+ throw new InternalServerError43("Failed to get journal transaction.");
20968
+ }
20969
+ }
20970
+ }
20971
+ async function updateById(_id, options, session) {
20972
+ const { error } = schemaJournalTransactionCtrlUpdate.validate(options);
20973
+ if (error) {
20974
+ throw new BadRequestError102(
20975
+ `Invalid journal transaction update data: ${error.message}`
20976
+ );
20977
+ }
20978
+ try {
20979
+ _id = new ObjectId57(_id);
20980
+ } catch (error2) {
20981
+ throw new BadRequestError102("Invalid journal transaction ID.");
20982
+ }
20983
+ if (options.debits) {
20984
+ for (let i = 0; i < options.debits.length; i++) {
20985
+ try {
20986
+ options.debits[i].value = new ObjectId57(options.debits[i].value);
20987
+ } catch (error2) {
20988
+ throw new BadRequestError102(`Invalid debit account ID at index ${i}`);
20989
+ }
20990
+ }
20991
+ }
20992
+ if (options.credits) {
20993
+ for (let i = 0; i < options.credits.length; i++) {
20994
+ try {
20995
+ options.credits[i].value = new ObjectId57(options.credits[i].value);
20996
+ } catch (error2) {
20997
+ throw new BadRequestError102(`Invalid credit account ID at index ${i}`);
20998
+ }
20999
+ }
21000
+ }
21001
+ try {
21002
+ await repo.collection.updateOne(
21003
+ { _id },
21004
+ { $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } },
21005
+ { session }
21006
+ );
21007
+ repo.delCachedData();
21008
+ return "Successfully updated journal transaction.";
21009
+ } catch (error2) {
21010
+ throw new InternalServerError43("Failed to update journal transaction.");
21011
+ }
21012
+ }
21013
+ async function deleteById(_id, session) {
21014
+ try {
21015
+ _id = new ObjectId57(_id);
21016
+ } catch (error) {
21017
+ throw new BadRequestError102("Invalid ID.");
21018
+ }
21019
+ try {
21020
+ await repo.collection.deleteOne({ _id }, { session });
21021
+ repo.delCachedData();
21022
+ return "Successfully deleted journal transaction.";
21023
+ } catch (error) {
21024
+ throw new InternalServerError43("Failed to delete journal transaction.");
21025
+ }
21026
+ }
21027
+ return {
21028
+ createIndexes,
21029
+ add,
21030
+ getAll,
21031
+ getByOrgTypeId,
21032
+ updateById,
21033
+ deleteById
21034
+ };
21035
+ }
21036
+
21037
+ // src/resources/finance-journal-transaction/finance.journal.transaction.service.ts
21038
+ import {
21039
+ AppError as AppError48,
21040
+ BadRequestError as BadRequestError103,
21041
+ InternalServerError as InternalServerError44,
21042
+ NotFoundError as NotFoundError6
21043
+ } from "@goweekdays/utils";
21044
+ import Joi91 from "joi";
21045
+ function validateNoDuplicateAccounts(debits, credits) {
21046
+ const debitIds = debits.map((d) => String(d.value));
21047
+ const creditIds = credits.map((c) => String(c.value));
21048
+ const debitSet = new Set(debitIds);
21049
+ if (debitSet.size !== debitIds.length) {
21050
+ throw new BadRequestError103("Duplicate accounts found in debits.");
21051
+ }
21052
+ const creditSet = new Set(creditIds);
21053
+ if (creditSet.size !== creditIds.length) {
21054
+ throw new BadRequestError103("Duplicate accounts found in credits.");
21055
+ }
21056
+ }
21057
+ function useJournalTransactionService() {
21058
+ const {
21059
+ add: _add,
21060
+ updateById: _updateById,
21061
+ getByOrgTypeId
21062
+ } = useJournalTransactionRepo();
21063
+ const { getUserById } = useUserRepo();
21064
+ async function add(value) {
21065
+ const { error } = schemaJournalTransactionCtrl.validate(value);
21066
+ if (error) {
21067
+ throw new BadRequestError103(
21068
+ `Invalid journal transaction data: ${error.message}`
21069
+ );
21070
+ }
21071
+ validateNoDuplicateAccounts(value.debits, value.credits);
21072
+ const user = await getUserById(value.createdBy);
21073
+ if (!user) {
21074
+ throw new NotFoundError6("User not found.");
21075
+ }
21076
+ value.createdByName = `${user.firstName} ${user.lastName}`;
21077
+ try {
21078
+ const id = await _add(value);
21079
+ return id;
21080
+ } catch (error2) {
21081
+ if (error2 instanceof AppError48) {
21082
+ throw error2;
21083
+ }
21084
+ throw new InternalServerError44(
21085
+ `Failed to create journal transaction: ${error2.message}`
21086
+ );
21087
+ }
21088
+ }
21089
+ async function updateById(org, type, _id, options) {
21090
+ const { error: idError } = Joi91.string().hex().required().validate(_id);
21091
+ if (idError) {
21092
+ throw new BadRequestError103("Invalid journal transaction ID.");
21093
+ }
21094
+ const { error } = schemaJournalTransactionCtrlUpdate.validate(options);
21095
+ if (error) {
21096
+ throw new BadRequestError103(`Invalid update data: ${error.message}`);
21097
+ }
21098
+ const existing = await getByOrgTypeId({ org, type, _id });
21099
+ if (!existing) {
21100
+ throw new NotFoundError6("Journal transaction not found.");
21101
+ }
21102
+ const debits = options.debits ?? existing.debits;
21103
+ const credits = options.credits ?? existing.credits;
21104
+ validateNoDuplicateAccounts(debits, credits);
21105
+ try {
21106
+ return await _updateById(_id, options);
21107
+ } catch (error2) {
21108
+ if (error2 instanceof AppError48) {
21109
+ throw error2;
21110
+ }
21111
+ throw new InternalServerError44(
21112
+ `Failed to update journal transaction: ${error2.message}`
21113
+ );
21114
+ }
21115
+ }
21116
+ return {
21117
+ add,
21118
+ updateById
21119
+ };
21120
+ }
21121
+
21122
+ // src/resources/finance-journal-transaction/finance.journal.transaction.controller.ts
21123
+ import Joi92 from "joi";
21124
+ import { BadRequestError as BadRequestError104 } from "@goweekdays/utils";
21125
+ function useJournalTransactionController() {
21126
+ const {
21127
+ getAll: _getAll,
21128
+ getByOrgTypeId: _getByOrgTypeId,
21129
+ deleteById: _deleteById
21130
+ } = useJournalTransactionRepo();
21131
+ const { add: _add, updateById: _updateById } = useJournalTransactionService();
21132
+ async function add(req, res, next) {
21133
+ const value = req.body;
21134
+ const { error } = schemaJournalTransactionCtrl.validate(value);
21135
+ if (error) {
21136
+ next(new BadRequestError104(error.message));
21137
+ return;
21138
+ }
21139
+ try {
21140
+ const id = await _add(value);
21141
+ res.json({ message: "Journal transaction created successfully.", id });
21142
+ return;
21143
+ } catch (error2) {
21144
+ next(error2);
21145
+ }
21146
+ }
21147
+ async function getAll(req, res, next) {
21148
+ const org = req.params.org ?? "";
21149
+ const type = req.params.type ?? "";
21150
+ const search = req.query.search ?? "";
21151
+ const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
21152
+ const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
21153
+ const { error } = schemaJournalTransactionGetAll.validate({
21154
+ ...req.params,
21155
+ ...req.query
21156
+ });
21157
+ if (!isFinite(page)) {
21158
+ next(new BadRequestError104("Invalid page number."));
21159
+ return;
21160
+ }
21161
+ if (!isFinite(limit)) {
21162
+ next(new BadRequestError104("Invalid limit number."));
21163
+ return;
21164
+ }
21165
+ if (error) {
21166
+ next(new BadRequestError104(error.message));
21167
+ return;
21168
+ }
21169
+ try {
21170
+ const data = await _getAll({ org, type, search, page, limit });
21171
+ res.json(data);
21172
+ return;
21173
+ } catch (error2) {
21174
+ next(error2);
21175
+ }
21176
+ }
21177
+ async function getByOrgTypeId(req, res, next) {
21178
+ const { error } = Joi92.object({
21179
+ org: Joi92.string().hex().required(),
21180
+ type: Joi92.string().required(),
21181
+ id: Joi92.string().hex().required()
21182
+ }).validate(req.params);
21183
+ if (error) {
21184
+ next(new BadRequestError104(error.message));
21185
+ return;
21186
+ }
21187
+ const _id = req.params.id;
21188
+ const org = req.params.org;
21189
+ const type = req.params.type;
21190
+ try {
21191
+ const data = await _getByOrgTypeId({ org, type, _id });
21192
+ res.json(data);
21193
+ return;
21194
+ } catch (error2) {
21195
+ next(error2);
21196
+ }
21197
+ }
21198
+ async function updateById(req, res, next) {
21199
+ const value = req.body;
21200
+ const { error } = Joi92.object({
21201
+ id: Joi92.string().hex().required(),
21202
+ org: Joi92.string().hex().required(),
21203
+ type: Joi92.string().allow(...journalTypes).required()
21204
+ }).concat(schemaJournalTransactionCtrlUpdate).validate({ ...req.params, ...value });
21205
+ if (error) {
21206
+ next(new BadRequestError104(error.message));
21207
+ return;
21208
+ }
21209
+ const id = req.params.id ?? "";
21210
+ const org = req.params.org ?? "";
21211
+ const type = req.params.type ?? "";
21212
+ try {
21213
+ const message = await _updateById(org, type, id, value);
21214
+ res.json({ message });
21215
+ return;
21216
+ } catch (error2) {
21217
+ next(error2);
21218
+ }
21219
+ }
21220
+ async function deleteById(req, res, next) {
21221
+ const id = req.params.id;
21222
+ const { error } = Joi92.object({
21223
+ id: Joi92.string().hex().required()
21224
+ }).validate({ id });
21225
+ if (error) {
21226
+ next(new BadRequestError104(error.message));
21227
+ return;
21228
+ }
21229
+ try {
21230
+ const message = await _deleteById(id);
21231
+ res.json({ message });
21232
+ return;
21233
+ } catch (error2) {
21234
+ next(error2);
21235
+ }
21236
+ }
21237
+ return {
21238
+ add,
21239
+ getAll,
21240
+ getByOrgTypeId,
21241
+ updateById,
21242
+ deleteById
21243
+ };
21244
+ }
21245
+
20664
21246
  // src/resources/finance-journal/finance.journal.service.ts
20665
21247
  function useJournalService() {
20666
21248
  const {
@@ -20670,10 +21252,12 @@ function useJournalService() {
20670
21252
  updateById: _updateById,
20671
21253
  delCachedData: delJournalCache
20672
21254
  } = useJournalRepo();
21255
+ const { getByOrgTypeId: getJournalTransaction } = useJournalTransactionRepo();
20673
21256
  const {
20674
21257
  add: addLine,
20675
21258
  getByEntry: getJournalLinesByEntry,
20676
21259
  updateById: updateJournalLineById,
21260
+ updateBalanceById: updateJournalLineBalance,
20677
21261
  deleteById: deleteJournalLineById
20678
21262
  } = useJournalLineRepo();
20679
21263
  const { getUserById } = useUserRepo();
@@ -20687,21 +21271,21 @@ function useJournalService() {
20687
21271
  const { add: addJournalLog } = useJournalLogRepo();
20688
21272
  const { getById: getCustomerById } = useCustomerRepo();
20689
21273
  async function add(entry, lines) {
20690
- const { error } = Joi90.object({
21274
+ const { error } = Joi93.object({
20691
21275
  journalEntry: schemaJournalCtrl.required(),
20692
- journalLines: Joi90.array().items(schemaJournalLineCtrl).min(1).required()
21276
+ journalLines: Joi93.array().items(schemaJournalLineCtrl).min(1).required()
20693
21277
  }).validate({
20694
21278
  journalEntry: entry,
20695
21279
  journalLines: lines
20696
21280
  });
20697
21281
  if (error) {
20698
- throw new BadRequestError101(
21282
+ throw new BadRequestError105(
20699
21283
  `Invalid general journal data: ${error.message}`
20700
21284
  );
20701
21285
  }
20702
21286
  const session = useAtlas16.getClient()?.startSession();
20703
21287
  if (!session) {
20704
- throw new BadRequestError101("Unable to start database session.");
21288
+ throw new BadRequestError105("Unable to start database session.");
20705
21289
  }
20706
21290
  try {
20707
21291
  session.startTransaction();
@@ -20716,16 +21300,25 @@ function useJournalService() {
20716
21300
  await validateJournalLines(lines);
20717
21301
  const user = await getUserById(entry.createdBy);
20718
21302
  if (!user) {
20719
- throw new NotFoundError6("User not found.");
21303
+ throw new NotFoundError7("User not found.");
20720
21304
  }
20721
21305
  entry.createdByName = `${user.firstName} ${user.lastName}`;
20722
21306
  if (entry.customer) {
20723
21307
  const customer = await getCustomerById(String(entry.customer));
20724
21308
  if (!customer) {
20725
- throw new NotFoundError6("Customer not found.");
21309
+ throw new NotFoundError7("Customer not found.");
20726
21310
  }
20727
21311
  entry.customerName = `${customer.firstName} ${customer.lastName}`;
20728
21312
  }
21313
+ const journalTx = await getJournalTransaction({
21314
+ org: String(entry.org),
21315
+ type: entry.type,
21316
+ _id: String(entry.transaction)
21317
+ });
21318
+ if (!journalTx) {
21319
+ throw new NotFoundError7("Transaction not found.");
21320
+ }
21321
+ entry.transactionName = journalTx.title;
20729
21322
  entry.status = "draft";
20730
21323
  const entryId = await _add(entry, session);
20731
21324
  for (const line of lines) {
@@ -20733,7 +21326,7 @@ function useJournalService() {
20733
21326
  line.journalEntry = entryId.toString();
20734
21327
  const account = await getAccountById(String(line.account));
20735
21328
  if (!account) {
20736
- throw new NotFoundError6(`Account not found: ${line.account}`);
21329
+ throw new NotFoundError7(`Account not found: ${line.account}`);
20737
21330
  }
20738
21331
  line.accountName = account.name;
20739
21332
  line.accountCode = account.code;
@@ -20765,10 +21358,10 @@ function useJournalService() {
20765
21358
  return "Journal entry created successfully.";
20766
21359
  } catch (error2) {
20767
21360
  await session.abortTransaction();
20768
- if (error2 instanceof AppError47) {
21361
+ if (error2 instanceof AppError49) {
20769
21362
  throw error2;
20770
21363
  }
20771
- throw new InternalServerError43(
21364
+ throw new InternalServerError45(
20772
21365
  `Failed to create general journal: ${error2.message}`
20773
21366
  );
20774
21367
  } finally {
@@ -20782,18 +21375,19 @@ function useJournalService() {
20782
21375
  getYearBalancesByAccount,
20783
21376
  updateById: updateAccountBalance
20784
21377
  } = useAccountBalanceRepo();
21378
+ const { getByOrg: getBusinessProfileByOrg } = useBusinessProfileRepo();
20785
21379
  async function updateStatusById(_id, status2, user) {
20786
- const validation = Joi90.object({
20787
- _id: Joi90.string().hex().required(),
20788
- status: Joi90.string().valid("posted", "voided").required()
21380
+ const validation = Joi93.object({
21381
+ _id: Joi93.string().hex().required(),
21382
+ status: Joi93.string().valid("posted", "voided").required()
20789
21383
  });
20790
21384
  const { error } = validation.validate({ _id, status: status2 });
20791
21385
  if (error) {
20792
- throw new BadRequestError101(`Invalid input: ${error.message}`);
21386
+ throw new BadRequestError105(`Invalid input: ${error.message}`);
20793
21387
  }
20794
21388
  const session = useAtlas16.getClient()?.startSession();
20795
21389
  if (!session) {
20796
- throw new BadRequestError101("Unable to start database session.");
21390
+ throw new BadRequestError105("Unable to start database session.");
20797
21391
  }
20798
21392
  try {
20799
21393
  let computeClosingBalance2 = function(openingDebit, openingCredit, movementDebit, movementCredit) {
@@ -20807,18 +21401,18 @@ function useJournalService() {
20807
21401
  var computeClosingBalance = computeClosingBalance2;
20808
21402
  const journalEntry = await getJournalById(_id);
20809
21403
  if (!journalEntry) {
20810
- throw new NotFoundError6("Journal entry not found.");
21404
+ throw new NotFoundError7("Journal entry not found.");
20811
21405
  }
20812
21406
  if (journalEntry.status === "voided") {
20813
- throw new BadRequestError101("Cannot update a voided general journal.");
21407
+ throw new BadRequestError105("Cannot update a voided general journal.");
20814
21408
  }
20815
21409
  if (journalEntry.status === "posted" && status2 === "draft") {
20816
- throw new BadRequestError101(
21410
+ throw new BadRequestError105(
20817
21411
  "Cannot revert a posted general journal to draft."
20818
21412
  );
20819
21413
  }
20820
21414
  if (status2 === "voided" && journalEntry.reversalDraft) {
20821
- throw new BadRequestError101(
21415
+ throw new BadRequestError105(
20822
21416
  "Cannot void a general journal with an existing reversal draft."
20823
21417
  );
20824
21418
  }
@@ -20840,9 +21434,17 @@ function useJournalService() {
20840
21434
  if (status2 === "posted") {
20841
21435
  await updateStatusByJournal(_id, status2, session);
20842
21436
  await _updateStatusById(_id, status2, session);
21437
+ const businessProfile = await getBusinessProfileByOrg(
21438
+ String(journalEntry.org)
21439
+ );
21440
+ if (!businessProfile) {
21441
+ throw new NotFoundError7(
21442
+ "Business profile not found for organization."
21443
+ );
21444
+ }
20843
21445
  const linesToPost = await getJournalLinesByEntry(_id);
20844
21446
  const journalDate = new Date(journalEntry.date);
20845
- const fiscalYear = journalDate.getFullYear();
21447
+ const fiscalYear = Number(businessProfile.currentFiscalYear);
20846
21448
  const month = journalDate.toLocaleString("en-US", { month: "long" });
20847
21449
  for (const line of linesToPost) {
20848
21450
  const existingBalance = await getAccountBalance({
@@ -20865,9 +21467,16 @@ function useJournalService() {
20865
21467
  String(journalEntry.org),
20866
21468
  fiscalYear,
20867
21469
  month,
20868
- { movementDebit, movementCredit, closingDebit, closingCredit, netBalance },
21470
+ {
21471
+ movementDebit,
21472
+ movementCredit,
21473
+ closingDebit,
21474
+ closingCredit,
21475
+ netBalance
21476
+ },
20869
21477
  session
20870
21478
  );
21479
+ await updateJournalLineBalance(String(line._id), netBalance, session);
20871
21480
  } else {
20872
21481
  const allYearBalances = await getYearBalancesByAccount({
20873
21482
  account: String(line.account),
@@ -20875,7 +21484,9 @@ function useJournalService() {
20875
21484
  fiscalYear
20876
21485
  });
20877
21486
  const currentMonthIdx = MONTHS.indexOf(month);
20878
- const previousRecord = allYearBalances.filter((r) => MONTHS.indexOf(r.period.month) < currentMonthIdx).sort((a, b) => MONTHS.indexOf(b.period.month) - MONTHS.indexOf(a.period.month))[0];
21487
+ const previousRecord = allYearBalances.filter((r) => MONTHS.indexOf(r.period.month) < currentMonthIdx).sort(
21488
+ (a, b) => MONTHS.indexOf(b.period.month) - MONTHS.indexOf(a.period.month)
21489
+ )[0];
20879
21490
  const openingDebit = previousRecord?.closingDebit ?? 0;
20880
21491
  const openingCredit = previousRecord?.closingCredit ?? 0;
20881
21492
  const movementDebit = line.debit || 0;
@@ -20904,6 +21515,7 @@ function useJournalService() {
20904
21515
  },
20905
21516
  session
20906
21517
  );
21518
+ await updateJournalLineBalance(String(line._id), netBalance, session);
20907
21519
  }
20908
21520
  }
20909
21521
  await addJournalLog(
@@ -20918,7 +21530,7 @@ function useJournalService() {
20918
21530
  if (journalEntry.reversedEntry) {
20919
21531
  const userData = await getUserById(user);
20920
21532
  if (!userData) {
20921
- throw new NotFoundError6("User not found.");
21533
+ throw new NotFoundError7("User not found.");
20922
21534
  }
20923
21535
  await _updateById(
20924
21536
  journalEntry.reversedEntry,
@@ -20930,6 +21542,7 @@ function useJournalService() {
20930
21542
  },
20931
21543
  session
20932
21544
  );
21545
+ await updateStatusByJournal(String(journalEntry.reversedEntry), "voided", session);
20933
21546
  await addJournalLog(
20934
21547
  {
20935
21548
  journalId: String(journalEntry._id),
@@ -20946,7 +21559,7 @@ function useJournalService() {
20946
21559
  const counterName = `${journalEntry.org.toString()}-general-journal`;
20947
21560
  const counter = await getCounterByType(counterName);
20948
21561
  if (!counter) {
20949
- throw new NotFoundError6("Counter not found for general journal.");
21562
+ throw new NotFoundError7("Counter not found for general journal.");
20950
21563
  }
20951
21564
  const date = /* @__PURE__ */ new Date();
20952
21565
  const entryNumber = counter ? counter.count + 1 : 1;
@@ -20955,7 +21568,8 @@ function useJournalService() {
20955
21568
  org: String(journalEntry.org),
20956
21569
  id: entryNumber.toString().padStart(6, "0"),
20957
21570
  type: journalEntry.type,
20958
- transaction: journalEntry.transaction,
21571
+ transaction: String(journalEntry.transaction),
21572
+ transactionName: journalEntry.transactionName,
20959
21573
  date,
20960
21574
  description: `Reversal of ${getPrefixByType(journalEntry.type)}-${journalEntry.id}`,
20961
21575
  createdBy: String(journalEntry.createdBy),
@@ -20974,7 +21588,7 @@ function useJournalService() {
20974
21588
  );
20975
21589
  const lines = await getJournalLinesByEntry(String(journalEntry._id));
20976
21590
  if (lines && lines.length === 0) {
20977
- throw new NotFoundError6("Journal lines not found for reversal.");
21591
+ throw new NotFoundError7("Journal lines not found for reversal.");
20978
21592
  }
20979
21593
  const reversedLines = [];
20980
21594
  for (const line of lines) {
@@ -21019,10 +21633,10 @@ function useJournalService() {
21019
21633
  return "Journal entry status updated successfully.";
21020
21634
  } catch (error2) {
21021
21635
  await session.abortTransaction();
21022
- if (error2 instanceof AppError47) {
21636
+ if (error2 instanceof AppError49) {
21023
21637
  throw error2;
21024
21638
  }
21025
- throw new InternalServerError43(
21639
+ throw new InternalServerError45(
21026
21640
  `Failed to update general journal status: ${error2.message}`
21027
21641
  );
21028
21642
  } finally {
@@ -21030,11 +21644,11 @@ function useJournalService() {
21030
21644
  }
21031
21645
  }
21032
21646
  async function updateById(id, entry, lines, user) {
21033
- const { error } = Joi90.object({
21034
- id: Joi90.string().hex().required(),
21647
+ const { error } = Joi93.object({
21648
+ id: Joi93.string().hex().required(),
21035
21649
  journalEntry: schemaJournalCtrlUpdate.required(),
21036
- journalLines: Joi90.array().items(schemaJournalLineCtrlUpdate).min(1).required(),
21037
- user: Joi90.string().hex().required()
21650
+ journalLines: Joi93.array().items(schemaJournalLineCtrlUpdate).min(1).required(),
21651
+ user: Joi93.string().hex().required()
21038
21652
  }).validate({
21039
21653
  id,
21040
21654
  journalEntry: entry,
@@ -21042,13 +21656,13 @@ function useJournalService() {
21042
21656
  user
21043
21657
  });
21044
21658
  if (error) {
21045
- throw new BadRequestError101(
21659
+ throw new BadRequestError105(
21046
21660
  `Invalid general journal data: ${error.message}`
21047
21661
  );
21048
21662
  }
21049
21663
  const session = useAtlas16.getClient()?.startSession();
21050
21664
  if (!session) {
21051
- throw new BadRequestError101("Unable to start database session.");
21665
+ throw new BadRequestError105("Unable to start database session.");
21052
21666
  }
21053
21667
  try {
21054
21668
  let hasLineChanged2 = function(existing, incoming) {
@@ -21058,24 +21672,37 @@ function useJournalService() {
21058
21672
  session.startTransaction();
21059
21673
  const existingEntry = await getJournalById(id);
21060
21674
  if (!existingEntry) {
21061
- throw new NotFoundError6("Journal entry not found.");
21675
+ throw new NotFoundError7("Journal entry not found.");
21062
21676
  }
21063
21677
  if (existingEntry.status !== "draft") {
21064
- throw new BadRequestError101("Only draft journal entries can be updated.");
21678
+ throw new BadRequestError105("Only draft journal entries can be updated.");
21065
21679
  }
21066
21680
  const updatedBy = await getUserById(user);
21067
21681
  if (!updatedBy) {
21068
- throw new NotFoundError6("User not found.");
21682
+ throw new NotFoundError7("User not found.");
21069
21683
  }
21070
21684
  await validateJournalLines(lines);
21071
- const headerChanged = new Date(existingEntry.date).getTime() !== new Date(entry.date).getTime() || existingEntry.description !== entry.description || String(existingEntry.customer || "") !== String(entry.customer || "") || existingEntry.transaction !== entry.transaction;
21685
+ const headerChanged = new Date(existingEntry.date).getTime() !== new Date(entry.date).getTime() || existingEntry.description !== entry.description || String(existingEntry.customer || "") !== String(entry.customer || "") || String(existingEntry.transaction) !== String(entry.transaction);
21072
21686
  if (entry.customer && String(entry.customer) !== String(existingEntry.customer)) {
21073
21687
  const customer = await getCustomerById(String(entry.customer));
21074
21688
  if (!customer) {
21075
- throw new NotFoundError6("Customer not found.");
21689
+ throw new NotFoundError7("Customer not found.");
21076
21690
  }
21077
21691
  entry.customerName = `${customer.firstName} ${customer.lastName}`;
21078
21692
  }
21693
+ if (String(existingEntry.transaction) !== String(entry.transaction)) {
21694
+ const journalTx = await getJournalTransaction({
21695
+ org: String(existingEntry.org),
21696
+ type: entry.type,
21697
+ _id: String(entry.transaction)
21698
+ });
21699
+ if (!journalTx) {
21700
+ throw new NotFoundError7("Transaction not found.");
21701
+ }
21702
+ entry.transactionName = journalTx.title;
21703
+ } else {
21704
+ entry.transactionName = existingEntry.transactionName;
21705
+ }
21079
21706
  const existingLines = await getJournalLinesByEntry(id);
21080
21707
  const existingLineMap = new Map(
21081
21708
  existingLines.map((line) => [String(line._id), line])
@@ -21090,7 +21717,7 @@ function useJournalService() {
21090
21717
  (existingId) => !incomingIds.has(existingId)
21091
21718
  );
21092
21719
  if (existingLines.length > 0 && removedLineIds.length === existingLines.length && lines.length > 0) {
21093
- throw new BadRequestError101(
21720
+ throw new BadRequestError105(
21094
21721
  "All journal lines marked for deletion. Identity mismatch suspected."
21095
21722
  );
21096
21723
  }
@@ -21108,7 +21735,7 @@ function useJournalService() {
21108
21735
  const newLines = lines.filter((line) => !line._id);
21109
21736
  const nothingChanged = !headerChanged && removedLineIds.length === 0 && updatedLines.length === 0 && newLines.length === 0;
21110
21737
  if (nothingChanged) {
21111
- throw new BadRequestError101("No changes detected.");
21738
+ throw new BadRequestError105("No changes detected.");
21112
21739
  }
21113
21740
  for (const lineId of removedLineIds) {
21114
21741
  await deleteJournalLineById(lineId, session);
@@ -21123,7 +21750,7 @@ function useJournalService() {
21123
21750
  if (existing && String(existing.account) !== String(line.account)) {
21124
21751
  const account = await getAccountById(String(line.account));
21125
21752
  if (!account) {
21126
- throw new NotFoundError6(`Account not found: ${line.account}`);
21753
+ throw new NotFoundError7(`Account not found: ${line.account}`);
21127
21754
  }
21128
21755
  updatePayload.accountName = account.name;
21129
21756
  updatePayload.accountCode = account.code;
@@ -21133,7 +21760,7 @@ function useJournalService() {
21133
21760
  for (const line of newLines) {
21134
21761
  const account = await getAccountById(String(line.account));
21135
21762
  if (!account) {
21136
- throw new NotFoundError6(`Account not found: ${line.account}`);
21763
+ throw new NotFoundError7(`Account not found: ${line.account}`);
21137
21764
  }
21138
21765
  await addLine(
21139
21766
  {
@@ -21218,10 +21845,10 @@ function useJournalService() {
21218
21845
  return "Journal entry updated successfully.";
21219
21846
  } catch (error2) {
21220
21847
  await session.abortTransaction();
21221
- if (error2 instanceof AppError47) {
21848
+ if (error2 instanceof AppError49) {
21222
21849
  throw error2;
21223
21850
  }
21224
- throw new InternalServerError43(
21851
+ throw new InternalServerError45(
21225
21852
  `Failed to update general journal: ${error2.message}`
21226
21853
  );
21227
21854
  } finally {
@@ -21236,8 +21863,8 @@ function useJournalService() {
21236
21863
  }
21237
21864
 
21238
21865
  // src/resources/finance-journal/finance.journal.controller.ts
21239
- import Joi91 from "joi";
21240
- import { BadRequestError as BadRequestError102, logger as logger52 } from "@goweekdays/utils";
21866
+ import Joi94 from "joi";
21867
+ import { BadRequestError as BadRequestError106, logger as logger53 } from "@goweekdays/utils";
21241
21868
  function useJournalController() {
21242
21869
  const {
21243
21870
  getAll: _getAll,
@@ -21251,13 +21878,13 @@ function useJournalController() {
21251
21878
  } = useJournalService();
21252
21879
  async function add(req, res, next) {
21253
21880
  const value = req.body;
21254
- const { error } = Joi91.object({
21881
+ const { error } = Joi94.object({
21255
21882
  journalEntry: schemaJournalCtrl.required(),
21256
- journalLines: Joi91.array().items(schemaJournalLineCtrl).min(1).required()
21883
+ journalLines: Joi94.array().items(schemaJournalLineCtrl).min(1).required()
21257
21884
  }).validate(value);
21258
21885
  if (error) {
21259
- next(new BadRequestError102(error.message));
21260
- logger52.info(`Controller: ${error.message}`);
21886
+ next(new BadRequestError106(error.message));
21887
+ logger53.info(`Controller: ${error.message}`);
21261
21888
  return;
21262
21889
  }
21263
21890
  try {
@@ -21278,15 +21905,15 @@ function useJournalController() {
21278
21905
  const search = req.query.search ?? "";
21279
21906
  const status2 = req.query.status ?? "all";
21280
21907
  if (!isFinite(page)) {
21281
- next(new BadRequestError102("Invalid page number."));
21908
+ next(new BadRequestError106("Invalid page number."));
21282
21909
  return;
21283
21910
  }
21284
21911
  if (!isFinite(limit)) {
21285
- next(new BadRequestError102("Invalid limit number."));
21912
+ next(new BadRequestError106("Invalid limit number."));
21286
21913
  return;
21287
21914
  }
21288
21915
  if (error) {
21289
- next(new BadRequestError102(error.message));
21916
+ next(new BadRequestError106(error.message));
21290
21917
  return;
21291
21918
  }
21292
21919
  try {
@@ -21306,12 +21933,12 @@ function useJournalController() {
21306
21933
  }
21307
21934
  async function getById(req, res, next) {
21308
21935
  const id = req.params.id;
21309
- const validation = Joi91.object({
21310
- id: Joi91.string().hex().required()
21936
+ const validation = Joi94.object({
21937
+ id: Joi94.string().hex().required()
21311
21938
  });
21312
21939
  const { error } = validation.validate({ id });
21313
21940
  if (error) {
21314
- next(new BadRequestError102(error.message));
21941
+ next(new BadRequestError106(error.message));
21315
21942
  return;
21316
21943
  }
21317
21944
  try {
@@ -21326,15 +21953,15 @@ function useJournalController() {
21326
21953
  const value = req.body;
21327
21954
  const id = req.params.id ?? "";
21328
21955
  const user = req.cookies.user;
21329
- const { error } = Joi91.object({
21330
- id: Joi91.string().hex().required(),
21956
+ const { error } = Joi94.object({
21957
+ id: Joi94.string().hex().required(),
21331
21958
  journalEntry: schemaJournalCtrlUpdate.required(),
21332
- journalLines: Joi91.array().items(schemaJournalLineCtrlUpdate).min(1).required(),
21333
- user: Joi91.string().hex().required()
21959
+ journalLines: Joi94.array().items(schemaJournalLineCtrlUpdate).min(1).required(),
21960
+ user: Joi94.string().hex().required()
21334
21961
  }).validate({ id, user, ...value });
21335
21962
  if (error) {
21336
- next(new BadRequestError102(error.message));
21337
- logger52.info(`Controller: ${error.message}`);
21963
+ next(new BadRequestError106(error.message));
21964
+ logger53.info(`Controller: ${error.message}`);
21338
21965
  return;
21339
21966
  }
21340
21967
  try {
@@ -21353,7 +21980,7 @@ function useJournalController() {
21353
21980
  async function deleteById(req, res, next) {
21354
21981
  const id = req.params.id;
21355
21982
  if (!id) {
21356
- next(new BadRequestError102("Journal Entry ID is required."));
21983
+ next(new BadRequestError106("Journal Entry ID is required."));
21357
21984
  return;
21358
21985
  }
21359
21986
  try {
@@ -21368,14 +21995,14 @@ function useJournalController() {
21368
21995
  const id = req.params.id;
21369
21996
  const status2 = req.params.status;
21370
21997
  const user = req.cookies.user;
21371
- const validation = Joi91.object({
21372
- id: Joi91.string().hex().required(),
21373
- status: Joi91.string().required(),
21374
- user: Joi91.string().hex().required()
21998
+ const validation = Joi94.object({
21999
+ id: Joi94.string().hex().required(),
22000
+ status: Joi94.string().required(),
22001
+ user: Joi94.string().hex().required()
21375
22002
  });
21376
22003
  const { error } = validation.validate({ id, status: status2, user });
21377
22004
  if (error) {
21378
- next(new BadRequestError102(error.message));
22005
+ next(new BadRequestError106(error.message));
21379
22006
  return;
21380
22007
  }
21381
22008
  try {
@@ -21397,8 +22024,8 @@ function useJournalController() {
21397
22024
  }
21398
22025
 
21399
22026
  // src/resources/finance-journal-line/finance.journal.line.controller.ts
21400
- import Joi92 from "joi";
21401
- import { BadRequestError as BadRequestError103 } from "@goweekdays/utils";
22027
+ import Joi95 from "joi";
22028
+ import { BadRequestError as BadRequestError107 } from "@goweekdays/utils";
21402
22029
  function useJournalLineController() {
21403
22030
  const {
21404
22031
  getAll: _getAll,
@@ -21409,14 +22036,14 @@ function useJournalLineController() {
21409
22036
  } = useJournalLineRepo();
21410
22037
  async function getAll(req, res, next) {
21411
22038
  const query = req.query;
21412
- const validation = Joi92.object({
21413
- org: Joi92.string().hex().required(),
21414
- JournalGeneral: Joi92.string().hex().optional(),
21415
- page: Joi92.number().min(1).optional().allow("", null),
21416
- limit: Joi92.number().min(1).optional().allow("", null),
21417
- account: Joi92.string().hex().optional().allow("", null),
21418
- search: Joi92.string().optional().allow("", null),
21419
- status: Joi92.string().valid("draft", "posted").optional().allow("", null)
22039
+ const validation = Joi95.object({
22040
+ org: Joi95.string().hex().required(),
22041
+ JournalGeneral: Joi95.string().hex().optional(),
22042
+ page: Joi95.number().min(1).optional().allow("", null),
22043
+ limit: Joi95.number().min(1).optional().allow("", null),
22044
+ account: Joi95.string().hex().optional().allow("", null),
22045
+ search: Joi95.string().optional().allow("", null),
22046
+ status: Joi95.string().valid("draft", "posted").optional().allow("", null)
21420
22047
  });
21421
22048
  const org = req.params.org ?? "";
21422
22049
  const JournalGeneral = req.query.JournalGeneral;
@@ -21432,15 +22059,15 @@ function useJournalLineController() {
21432
22059
  account
21433
22060
  });
21434
22061
  if (!isFinite(page)) {
21435
- next(new BadRequestError103("Invalid page number."));
22062
+ next(new BadRequestError107("Invalid page number."));
21436
22063
  return;
21437
22064
  }
21438
22065
  if (!isFinite(limit)) {
21439
- next(new BadRequestError103("Invalid limit number."));
22066
+ next(new BadRequestError107("Invalid limit number."));
21440
22067
  return;
21441
22068
  }
21442
22069
  if (error) {
21443
- next(new BadRequestError103(error.message));
22070
+ next(new BadRequestError107(error.message));
21444
22071
  return;
21445
22072
  }
21446
22073
  try {
@@ -21461,12 +22088,12 @@ function useJournalLineController() {
21461
22088
  }
21462
22089
  async function getById(req, res, next) {
21463
22090
  const id = req.params.id;
21464
- const validation = Joi92.object({
21465
- id: Joi92.string().hex().required()
22091
+ const validation = Joi95.object({
22092
+ id: Joi95.string().hex().required()
21466
22093
  });
21467
22094
  const { error } = validation.validate({ id });
21468
22095
  if (error) {
21469
- next(new BadRequestError103(error.message));
22096
+ next(new BadRequestError107(error.message));
21470
22097
  return;
21471
22098
  }
21472
22099
  try {
@@ -21555,6 +22182,7 @@ export {
21555
22182
  modelJobSummary,
21556
22183
  modelJournal,
21557
22184
  modelJournalLine,
22185
+ modelJournalTransaction,
21558
22186
  modelLedgerBill,
21559
22187
  modelMember,
21560
22188
  modelOption,
@@ -21624,6 +22252,11 @@ export {
21624
22252
  schemaJournalLineRepo,
21625
22253
  schemaJournalRepo,
21626
22254
  schemaJournalRepoUpdate,
22255
+ schemaJournalTransactionAccount,
22256
+ schemaJournalTransactionCtrl,
22257
+ schemaJournalTransactionCtrlUpdate,
22258
+ schemaJournalTransactionGetAll,
22259
+ schemaJournalTransactionRepo,
21627
22260
  schemaLanguage,
21628
22261
  schemaLedgerBill,
21629
22262
  schemaLedgerBillingSummary,
@@ -21705,6 +22338,9 @@ export {
21705
22338
  useJournalLineRepo,
21706
22339
  useJournalRepo,
21707
22340
  useJournalService,
22341
+ useJournalTransactionController,
22342
+ useJournalTransactionRepo,
22343
+ useJournalTransactionService,
21708
22344
  useLedgerBillingController,
21709
22345
  useLedgerBillingRepo,
21710
22346
  useMemberController,