@7365admin1/core 3.41.1 → 3.42.0

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @iservice365/core
2
2
 
3
+ ## 3.42.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ff7b915: release changes in payment api
8
+
3
9
  ## 3.41.1
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -6907,6 +6907,9 @@ declare function useRedDotPaymentController(): {
6907
6907
  redirectPaymentTransaction: (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
6908
6908
  enquirePaymentTransaction: (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
6909
6909
  createPayment: (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
6910
+ getPaymentByReference: (req: Request, res: Response, next: NextFunction) => Promise<void>;
6911
+ updateStatus: (req: Request, res: Response, next: NextFunction) => Promise<void>;
6912
+ getPaidBills: (req: Request, res: Response, next: NextFunction) => Promise<void>;
6910
6913
  };
6911
6914
 
6912
6915
  interface IDirectPayment extends IBaseModel {
@@ -6945,6 +6948,8 @@ declare const useRedDotPaymentSvc: () => {
6945
6948
  type TBillingItems = {
6946
6949
  _id: ObjectId | string;
6947
6950
  name: string;
6951
+ amount: number;
6952
+ referenceNumber: string;
6948
6953
  };
6949
6954
  type TBillingPayments = {
6950
6955
  _id?: ObjectId;
@@ -6967,11 +6972,27 @@ type TBillingPayments = {
6967
6972
 
6968
6973
  declare const useRedDotPaymentRepo: () => {
6969
6974
  paySingleUnitBill: (refId: string, payload: Partial<TUnitBilling>) => Promise<mongodb.WithId<bson.Document> | null>;
6970
- createPayment: (type: string, payload: Partial<TBillingPayments>, session?: ClientSession) => Promise<ObjectId | undefined>;
6975
+ createPayment: (type: string, payload: Partial<TBillingPayments>, session?: ClientSession) => Promise<string | undefined>;
6971
6976
  payMultipleUnitBill: (refId: string[], payload: Partial<TUnitBilling>) => Promise<{
6972
6977
  message: string;
6973
6978
  remainingBalance: number;
6974
6979
  }>;
6980
+ getPaidBills: ({ search, page, limit, sort, month, year, unitId, }: {
6981
+ search?: string | undefined;
6982
+ page?: number | undefined;
6983
+ limit?: number | undefined;
6984
+ sort?: Record<string, any> | undefined;
6985
+ month?: string | undefined;
6986
+ year?: string | undefined;
6987
+ unitId: string | ObjectId;
6988
+ }, session?: ClientSession) => Promise<{
6989
+ items: any[];
6990
+ pages: number;
6991
+ pageRange: string;
6992
+ }>;
6993
+ createIndexes: () => Promise<void>;
6994
+ getPaymentByReference: (referenceNumber: string, session?: ClientSession) => Promise<TBillingPayments>;
6995
+ updateStatus: (referenceNumber: string, status: string, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
6975
6996
  };
6976
6997
 
6977
6998
  declare enum VerificationType {
package/dist/index.js CHANGED
@@ -536,13 +536,13 @@ var require_logger = __commonJS({
536
536
  "use strict";
537
537
  exports.__esModule = true;
538
538
  var _utils = require_utils();
539
- var logger201 = {
539
+ var logger202 = {
540
540
  methodMap: ["debug", "info", "warn", "error"],
541
541
  level: "info",
542
542
  // Maps a given level value to the `methodMap` indexes above.
543
543
  lookupLevel: function lookupLevel(level) {
544
544
  if (typeof level === "string") {
545
- var levelMap = _utils.indexOf(logger201.methodMap, level.toLowerCase());
545
+ var levelMap = _utils.indexOf(logger202.methodMap, level.toLowerCase());
546
546
  if (levelMap >= 0) {
547
547
  level = levelMap;
548
548
  } else {
@@ -553,9 +553,9 @@ var require_logger = __commonJS({
553
553
  },
554
554
  // Can be overridden in the host environment
555
555
  log: function log(level) {
556
- level = logger201.lookupLevel(level);
557
- if (typeof console !== "undefined" && logger201.lookupLevel(logger201.level) <= level) {
558
- var method = logger201.methodMap[level];
556
+ level = logger202.lookupLevel(level);
557
+ if (typeof console !== "undefined" && logger202.lookupLevel(logger202.level) <= level) {
558
+ var method = logger202.methodMap[level];
559
559
  if (!console[method]) {
560
560
  method = "log";
561
561
  }
@@ -566,7 +566,7 @@ var require_logger = __commonJS({
566
566
  }
567
567
  }
568
568
  };
569
- exports["default"] = logger201;
569
+ exports["default"] = logger202;
570
570
  module2.exports = exports["default"];
571
571
  }
572
572
  });
@@ -64884,9 +64884,19 @@ var import_mongodb135 = require("mongodb");
64884
64884
  var import_node_server_utils223 = require("@7365admin1/node-server-utils");
64885
64885
  var import_mongodb134 = require("mongodb");
64886
64886
  var import_joi126 = __toESM(require("joi"));
64887
+ var BillingPaymentStatus = /* @__PURE__ */ ((BillingPaymentStatus2) => {
64888
+ BillingPaymentStatus2["PENDING"] = "pending";
64889
+ BillingPaymentStatus2["SUCCESS"] = "success";
64890
+ BillingPaymentStatus2["FAILED"] = "failed";
64891
+ BillingPaymentStatus2["PARTIAL"] = "partial";
64892
+ BillingPaymentStatus2["CANCELLED"] = "cancelled";
64893
+ return BillingPaymentStatus2;
64894
+ })(BillingPaymentStatus || {});
64887
64895
  var schemaBillingItems = import_joi126.default.object({
64888
64896
  _id: import_joi126.default.string().hex().optional(),
64889
- name: import_joi126.default.string().optional().allow(null, "")
64897
+ name: import_joi126.default.string().optional().allow(null, ""),
64898
+ amount: import_joi126.default.number().optional().allow(null, ""),
64899
+ referenceNumber: import_joi126.default.string().optional().allow(null, "")
64890
64900
  });
64891
64901
  var schemaBillingPayments = import_joi126.default.object({
64892
64902
  _id: import_joi126.default.string().hex().optional(),
@@ -64993,12 +65003,60 @@ var useRedDotPaymentRepo = () => {
64993
65003
  const redDotMerchantCollection = () => {
64994
65004
  return getDB2().collection("payment-gateways");
64995
65005
  };
65006
+ async function createIndexes() {
65007
+ try {
65008
+ await paymentCollection().createIndexes([
65009
+ // A referenceNumber-prefixed compound index serves both the lookup by
65010
+ // reference alone and the { referenceNumber, status } lookups used by
65011
+ // the pay single / pay multiple flows.
65012
+ {
65013
+ key: { referenceNumber: 1, status: 1 },
65014
+ name: "referenceNumber_1_status_1"
65015
+ }
65016
+ ]);
65017
+ } catch (error) {
65018
+ import_node_server_utils224.logger.log({
65019
+ level: "error",
65020
+ message: error.message
65021
+ });
65022
+ throw new import_node_server_utils224.InternalServerError(
65023
+ "Failed to create index on billing payments."
65024
+ );
65025
+ }
65026
+ }
65027
+ async function getPaymentByReference(referenceNumber, session) {
65028
+ const reference = typeof referenceNumber === "string" ? referenceNumber.trim() : "";
65029
+ if (!reference) {
65030
+ throw new import_node_server_utils224.BadRequestError("Reference number is required.");
65031
+ }
65032
+ try {
65033
+ const payment = await paymentCollection().findOne(
65034
+ {
65035
+ referenceNumber: reference
65036
+ },
65037
+ { session }
65038
+ );
65039
+ if (!payment) {
65040
+ throw new import_node_server_utils224.NotFoundError("Payment not found.");
65041
+ }
65042
+ return payment;
65043
+ } catch (error) {
65044
+ if (error instanceof import_node_server_utils224.AppError) {
65045
+ throw error;
65046
+ }
65047
+ import_node_server_utils224.logger.log({
65048
+ level: "error",
65049
+ message: error.message
65050
+ });
65051
+ throw new import_node_server_utils224.InternalServerError("Failed to get payment.");
65052
+ }
65053
+ }
64996
65054
  async function createPayment(type, payload, session) {
64997
65055
  if (type == "single") {
64998
65056
  try {
64999
65057
  payload = MBillingItems(payload);
65000
- const res = await paymentCollection().insertOne(payload, { session });
65001
- return res.insertedId;
65058
+ await paymentCollection().insertOne(payload, { session });
65059
+ return payload.referenceNumber;
65002
65060
  } catch (error) {
65003
65061
  import_node_server_utils224.logger.log({
65004
65062
  level: "error",
@@ -65027,7 +65085,7 @@ var useRedDotPaymentRepo = () => {
65027
65085
  { $set: { referenceNumber } },
65028
65086
  { session }
65029
65087
  );
65030
- return res.insertedId;
65088
+ return referenceNumber;
65031
65089
  } catch (error) {
65032
65090
  import_node_server_utils224.logger.log({
65033
65091
  level: "error",
@@ -65045,6 +65103,76 @@ var useRedDotPaymentRepo = () => {
65045
65103
  }
65046
65104
  }
65047
65105
  }
65106
+ async function getPaidBills({
65107
+ search = "",
65108
+ page = 1,
65109
+ limit = 10,
65110
+ sort = {},
65111
+ month,
65112
+ year,
65113
+ unitId
65114
+ }, session) {
65115
+ let _unitId;
65116
+ try {
65117
+ _unitId = new import_mongodb135.ObjectId(unitId);
65118
+ } catch {
65119
+ throw new import_node_server_utils224.BadRequestError("Invalid unit ID format.");
65120
+ }
65121
+ page = page > 0 ? page - 1 : 0;
65122
+ let dateExpr = {};
65123
+ const datePaidRange = buildDatePaidRange(month, year);
65124
+ if (datePaidRange) {
65125
+ dateExpr.datePaid = datePaidRange;
65126
+ }
65127
+ const query = {
65128
+ unitId: _unitId,
65129
+ status: "success",
65130
+ ...search && {
65131
+ $or: [
65132
+ { referenceNumber: { $regex: search, $options: "i" } },
65133
+ { unitOwner: { $regex: search, $options: "i" } },
65134
+ { method: { $regex: search, $options: "i" } },
65135
+ { transaction_id: { $regex: search, $options: "i" } },
65136
+ { "unitBillingItems.name": { $regex: search, $options: "i" } },
65137
+ {
65138
+ $expr: {
65139
+ $regexMatch: {
65140
+ input: { $toString: "$totalAmount" },
65141
+ regex: search,
65142
+ options: "i"
65143
+ }
65144
+ }
65145
+ }
65146
+ ]
65147
+ },
65148
+ ...dateExpr
65149
+ };
65150
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
65151
+ try {
65152
+ const basePipeline = [
65153
+ { $match: query },
65154
+ { $sort: sort },
65155
+ { $skip: page * limit },
65156
+ { $limit: limit }
65157
+ ];
65158
+ const [items, countResult] = await Promise.all([
65159
+ paymentCollection().aggregate(basePipeline, { session }).toArray(),
65160
+ paymentCollection().aggregate([{ $match: query }, { $count: "total" }], { session }).toArray()
65161
+ ]);
65162
+ const totalCount = countResult[0]?.total || 0;
65163
+ const data = (0, import_node_server_utils224.paginate)(items, page, limit, totalCount);
65164
+ return data;
65165
+ } catch (error) {
65166
+ if (error instanceof import_node_server_utils224.AppError) {
65167
+ throw error;
65168
+ }
65169
+ import_node_server_utils224.logger.log({
65170
+ level: "error",
65171
+ message: error.message
65172
+ });
65173
+ throw new import_node_server_utils224.InternalServerError("Failed to retrieve paid bills.");
65174
+ }
65175
+ }
65048
65176
  async function paySingleUnitBill(refId, payload) {
65049
65177
  const session = import_node_server_utils224.useAtlas.getClient()?.startSession();
65050
65178
  try {
@@ -65207,6 +65335,52 @@ var useRedDotPaymentRepo = () => {
65207
65335
  session?.endSession();
65208
65336
  }
65209
65337
  }
65338
+ function buildDatePaidRange(month, year) {
65339
+ if (!year)
65340
+ return null;
65341
+ const yearNum = Number(year);
65342
+ if (!Number.isInteger(yearNum) || yearNum < 1970 || yearNum > 9999) {
65343
+ throw new import_node_server_utils224.BadRequestError("Invalid year filter.");
65344
+ }
65345
+ if (month) {
65346
+ const monthNum = Number(month);
65347
+ if (!Number.isInteger(monthNum) || monthNum < 1 || monthNum > 12) {
65348
+ throw new import_node_server_utils224.BadRequestError("Invalid month filter.");
65349
+ }
65350
+ return {
65351
+ $gte: new Date(yearNum, monthNum - 1, 1),
65352
+ $lt: new Date(yearNum, monthNum, 1)
65353
+ };
65354
+ }
65355
+ return {
65356
+ $gte: new Date(yearNum, 0, 1),
65357
+ $lt: new Date(yearNum + 1, 0, 1)
65358
+ };
65359
+ }
65360
+ async function updateStatus(referenceNumber, status, session) {
65361
+ const reference = typeof referenceNumber === "string" ? referenceNumber.trim() : "";
65362
+ if (!reference) {
65363
+ throw new import_node_server_utils224.BadRequestError("Reference number is required.");
65364
+ }
65365
+ try {
65366
+ const res = await paymentCollection().updateOne(
65367
+ { referenceNumber: reference, status: "pending" },
65368
+ { $set: { status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
65369
+ { session }
65370
+ );
65371
+ if (res.matchedCount === 0) {
65372
+ throw new import_node_server_utils224.NotFoundError(
65373
+ "Payment not found or is no longer pending."
65374
+ );
65375
+ }
65376
+ return res;
65377
+ } catch (error) {
65378
+ if (error instanceof import_node_server_utils224.AppError) {
65379
+ throw error;
65380
+ }
65381
+ throw new import_node_server_utils224.InternalServerError("Failed to update payment status.");
65382
+ }
65383
+ }
65210
65384
  function formatDateString(today) {
65211
65385
  today = typeof today === "string" ? new Date(today) : today;
65212
65386
  let month = today.getMonth() + 1;
@@ -65215,7 +65389,15 @@ var useRedDotPaymentRepo = () => {
65215
65389
  const formattedDate = `${month.toString().padStart(2, "0")}${day.toString().padStart(2, "0")}${year}`;
65216
65390
  return formattedDate;
65217
65391
  }
65218
- return { paySingleUnitBill, createPayment, payMultipleUnitBill };
65392
+ return {
65393
+ paySingleUnitBill,
65394
+ createPayment,
65395
+ payMultipleUnitBill,
65396
+ getPaidBills,
65397
+ createIndexes,
65398
+ getPaymentByReference,
65399
+ updateStatus
65400
+ };
65219
65401
  };
65220
65402
 
65221
65403
  // src/services/reddot-payment.service.ts
@@ -65325,7 +65507,7 @@ var useRedDotPaymentSvc = () => {
65325
65507
  const success = {
65326
65508
  ...basePayload,
65327
65509
  paymentStatus: "paid" /* PAID */,
65328
- amountPaid: parseInt(amount)
65510
+ amountPaid: Number(amount)
65329
65511
  };
65330
65512
  if (isBulk) {
65331
65513
  await payMultipleUnitBill(refId, success);
@@ -65359,7 +65541,12 @@ var useRedDotPaymentSvc = () => {
65359
65541
  var import_joi127 = __toESM(require("joi"));
65360
65542
  var import_node_server_utils226 = require("@7365admin1/node-server-utils");
65361
65543
  function useRedDotPaymentController() {
65362
- const { createPayment: _createPayment } = useRedDotPaymentRepo();
65544
+ const {
65545
+ createPayment: _createPayment,
65546
+ updateStatus: _updateStatus,
65547
+ getPaymentByReference: _getPaymentByReference,
65548
+ getPaidBills: _getPaidBills
65549
+ } = useRedDotPaymentRepo();
65363
65550
  const redirectPaymentTransaction = async (req, res) => {
65364
65551
  try {
65365
65552
  const data = req.body;
@@ -65423,17 +65610,86 @@ function useRedDotPaymentController() {
65423
65610
  try {
65424
65611
  const payment = await _createPayment(type, value);
65425
65612
  res.status(201).json({
65426
- message: "Payment created successfully.",
65613
+ message: "success",
65427
65614
  data: payment
65428
65615
  });
65429
65616
  } catch (error) {
65430
- next(error);
65617
+ const status = error?.statusCode ?? 500;
65618
+ res.status(status).json({ message: "failed" });
65619
+ }
65620
+ }
65621
+ async function updateStatus(req, res, next) {
65622
+ const schema2 = import_joi127.default.object({
65623
+ referenceNumber: import_joi127.default.string().required(),
65624
+ status: import_joi127.default.string().valid(...Object.values(BillingPaymentStatus)).required()
65625
+ });
65626
+ const { error, value } = schema2.validate({
65627
+ referenceNumber: req.params.id,
65628
+ status: req.body.status
65629
+ });
65630
+ if (error) {
65631
+ import_node_server_utils226.logger.log({ level: "error", message: error.message });
65632
+ next(new import_node_server_utils226.BadRequestError(error.message));
65633
+ return;
65634
+ }
65635
+ try {
65636
+ const data = await _updateStatus(value.referenceNumber, value.status);
65637
+ res.status(200).json({ message: "success", data });
65638
+ return;
65639
+ } catch (error2) {
65640
+ import_node_server_utils226.logger.log({ level: "error", message: error2.message });
65641
+ next(error2);
65642
+ return;
65643
+ }
65644
+ }
65645
+ async function getPaymentByReference(req, res, next) {
65646
+ const schema2 = import_joi127.default.object({
65647
+ referenceNumber: import_joi127.default.string().required()
65648
+ });
65649
+ const { error, value } = schema2.validate(req.params);
65650
+ if (error) {
65651
+ next(new import_node_server_utils226.BadRequestError(error.message));
65652
+ return;
65653
+ }
65654
+ try {
65655
+ const payment = await _getPaymentByReference(value.referenceNumber);
65656
+ res.json({ data: payment });
65657
+ return;
65658
+ } catch (error2) {
65659
+ next(error2);
65660
+ return;
65661
+ }
65662
+ }
65663
+ async function getPaidBills(req, res, next) {
65664
+ const schema2 = import_joi127.default.object({
65665
+ unitId: import_joi127.default.string().hex().length(24).required(),
65666
+ page: import_joi127.default.number().integer().min(1).default(1),
65667
+ limit: import_joi127.default.number().integer().min(1).max(100).default(10),
65668
+ search: import_joi127.default.string().trim().allow("").default(""),
65669
+ month: import_joi127.default.string().pattern(/^(0?[1-9]|1[0-2])$/).allow("").optional(),
65670
+ year: import_joi127.default.string().pattern(/^\d{4}$/).allow("").optional()
65671
+ });
65672
+ const { error, value } = schema2.validate({ ...req.params, ...req.query });
65673
+ if (error) {
65674
+ next(new import_node_server_utils226.BadRequestError(error.message));
65675
+ return;
65676
+ }
65677
+ try {
65678
+ const bills = await _getPaidBills(value);
65679
+ res.json({ data: bills });
65680
+ return;
65681
+ } catch (error2) {
65682
+ next(error2);
65683
+ return;
65431
65684
  }
65432
65685
  }
65433
65686
  return {
65434
65687
  redirectPaymentTransaction,
65435
65688
  enquirePaymentTransaction,
65436
- createPayment
65689
+ createPayment,
65690
+ getPaymentByReference,
65691
+ updateStatus,
65692
+ getPaidBills
65437
65693
  };
65438
65694
  }
65439
65695