geek-custom-api-core 0.0.71 → 0.0.73

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.
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "geek-custom-api-core",
3
+ "version": "0.0.72",
4
+ "description": "",
5
+ "author": "",
6
+ "license": "UNLICENSED",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "engines": {
10
+ "node": ">=22.0.0"
11
+ },
12
+ "scripts": {
13
+ "build": "nest build",
14
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
15
+ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
16
+ "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17
+ "start": "nest start",
18
+ "yalc": "npm run build && yalc publish"
19
+ },
20
+ "dependencies": {
21
+ "@aws-sdk/client-s3": "^3.400.0",
22
+ "@aws-sdk/client-secrets-manager": "^3.939.0",
23
+ "@nestjs/axios": "^3.0.2",
24
+ "@nestjs/common": "^10.3.9",
25
+ "@nestjs/config": "^3.2.2",
26
+ "@nestjs/core": "^10.3.9",
27
+ "@nestjs/event-emitter": "^2.1.1",
28
+ "@nestjs/jwt": "^10.1.0",
29
+ "@nestjs/mapped-types": "^2.0.2",
30
+ "@nestjs/passport": "^10.0.0",
31
+ "@nestjs/platform-express": "^10.3.9",
32
+ "@nestjs/schedule": "^6.1.1",
33
+ "@nestjs/swagger": "^7.4.2",
34
+ "@nestjs/typeorm": "^10.0.0",
35
+ "axios": "^1.4.0",
36
+ "bcrypt": "^5.1.0",
37
+ "class-transformer": "^0.5.1",
38
+ "class-validator": "^0.14.0",
39
+ "date-fns": "^2.30.0",
40
+ "dayjs": "^1.11.10",
41
+ "fast-xml-parser": "^4.3.6",
42
+ "ioredis": "^5.4.1",
43
+ "moment": "^2.29.4",
44
+ "moment-timezone": "^0.5.46",
45
+ "multer-s3": "^3.0.1",
46
+ "mysql2": "^3.6.0",
47
+ "passport-jwt": "^4.0.1",
48
+ "reflect-metadata": "^0.1.13",
49
+ "rxjs": "^7.8.1",
50
+ "typeorm": "^0.3.17",
51
+ "uuid": "^9.0.1",
52
+ "xlsx": "^0.18.5"
53
+ },
54
+ "devDependencies": {
55
+ "@nestjs/cli": "^10.0.0",
56
+ "@nestjs/schematics": "^9.0.0",
57
+ "@nestjs/testing": "^10.4.22",
58
+ "@types/bcrypt": "^5.0.0",
59
+ "@types/express": "^4.17.13",
60
+ "@types/jest": "^29.5.0",
61
+ "@types/multer": "^2.0.0",
62
+ "@types/node": "^22.0.0",
63
+ "@types/passport-jwt": "^3.0.9",
64
+ "@types/supertest": "^2.0.12",
65
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
66
+ "@typescript-eslint/parser": "^7.18.0",
67
+ "eslint": "^8.57.0",
68
+ "eslint-config-prettier": "^9.1.0",
69
+ "eslint-plugin-prettier": "^5.0.0",
70
+ "jest": "^29.7.0",
71
+ "prettier": "^3.2.5",
72
+ "source-map-support": "^0.5.21",
73
+ "supertest": "^7.1.3",
74
+ "ts-jest": "^29.1.2",
75
+ "ts-loader": "^9.5.1",
76
+ "ts-node": "^10.9.2",
77
+ "tsconfig-paths": "^4.2.0",
78
+ "typescript": "^5.3.3",
79
+ "webpack": "^5.90.0",
80
+ "webpack-cli": "^5.1.4",
81
+ "webpack-node-externals": "^3.0.0"
82
+ },
83
+ "jest": {
84
+ "moduleFileExtensions": [
85
+ "js",
86
+ "json",
87
+ "ts"
88
+ ],
89
+ "rootDir": "src",
90
+ "testRegex": ".*\\.spec\\.ts$",
91
+ "transform": {
92
+ "^.+\\.(t|j)s$": "ts-jest"
93
+ },
94
+ "moduleNameMapper": {
95
+ "^src/(.*)$": "<rootDir>/$1"
96
+ },
97
+ "collectCoverageFrom": [
98
+ "**/*.(t|j)s"
99
+ ],
100
+ "coverageDirectory": "../coverage",
101
+ "testEnvironment": "node"
102
+ }
103
+ }
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "geek-custom-api-core",
3
+ "version": "0.0.73",
4
+ "description": "",
5
+ "author": "",
6
+ "license": "UNLICENSED",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "engines": {
10
+ "node": ">=22.0.0"
11
+ },
12
+ "scripts": {
13
+ "build": "nest build",
14
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
15
+ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
16
+ "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17
+ "start": "nest start",
18
+ "yalc": "npm run build && yalc publish"
19
+ },
20
+ "dependencies": {
21
+ "@aws-sdk/client-s3": "^3.400.0",
22
+ "@aws-sdk/client-secrets-manager": "^3.939.0",
23
+ "@nestjs/axios": "^3.0.2",
24
+ "@nestjs/common": "^10.3.9",
25
+ "@nestjs/config": "^3.2.2",
26
+ "@nestjs/core": "^10.3.9",
27
+ "@nestjs/event-emitter": "^2.1.1",
28
+ "@nestjs/jwt": "^10.1.0",
29
+ "@nestjs/mapped-types": "^2.0.2",
30
+ "@nestjs/passport": "^10.0.0",
31
+ "@nestjs/platform-express": "^10.3.9",
32
+ "@nestjs/schedule": "^6.1.1",
33
+ "@nestjs/swagger": "^7.4.2",
34
+ "@nestjs/typeorm": "^10.0.0",
35
+ "axios": "^1.4.0",
36
+ "bcrypt": "^5.1.0",
37
+ "class-transformer": "^0.5.1",
38
+ "class-validator": "^0.14.0",
39
+ "date-fns": "^2.30.0",
40
+ "dayjs": "^1.11.10",
41
+ "fast-xml-parser": "^4.3.6",
42
+ "ioredis": "^5.4.1",
43
+ "moment": "^2.29.4",
44
+ "moment-timezone": "^0.5.46",
45
+ "multer-s3": "^3.0.1",
46
+ "mysql2": "^3.6.0",
47
+ "passport-jwt": "^4.0.1",
48
+ "reflect-metadata": "^0.1.13",
49
+ "rxjs": "^7.8.1",
50
+ "typeorm": "^0.3.17",
51
+ "uuid": "^9.0.1",
52
+ "xlsx": "^0.18.5"
53
+ },
54
+ "devDependencies": {
55
+ "@nestjs/cli": "^10.0.0",
56
+ "@nestjs/schematics": "^9.0.0",
57
+ "@nestjs/testing": "^10.4.22",
58
+ "@types/bcrypt": "^5.0.0",
59
+ "@types/express": "^4.17.13",
60
+ "@types/jest": "^29.5.0",
61
+ "@types/multer": "^2.0.0",
62
+ "@types/node": "^22.0.0",
63
+ "@types/passport-jwt": "^3.0.9",
64
+ "@types/supertest": "^2.0.12",
65
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
66
+ "@typescript-eslint/parser": "^7.18.0",
67
+ "eslint": "^8.57.0",
68
+ "eslint-config-prettier": "^9.1.0",
69
+ "eslint-plugin-prettier": "^5.0.0",
70
+ "jest": "^29.7.0",
71
+ "prettier": "^3.2.5",
72
+ "source-map-support": "^0.5.21",
73
+ "supertest": "^7.1.3",
74
+ "ts-jest": "^29.1.2",
75
+ "ts-loader": "^9.5.1",
76
+ "ts-node": "^10.9.2",
77
+ "tsconfig-paths": "^4.2.0",
78
+ "typescript": "^5.3.3",
79
+ "webpack": "^5.90.0",
80
+ "webpack-cli": "^5.1.4",
81
+ "webpack-node-externals": "^3.0.0"
82
+ },
83
+ "jest": {
84
+ "moduleFileExtensions": [
85
+ "js",
86
+ "json",
87
+ "ts"
88
+ ],
89
+ "rootDir": "src",
90
+ "testRegex": ".*\\.spec\\.ts$",
91
+ "transform": {
92
+ "^.+\\.(t|j)s$": "ts-jest"
93
+ },
94
+ "moduleNameMapper": {
95
+ "^src/(.*)$": "<rootDir>/$1"
96
+ },
97
+ "collectCoverageFrom": [
98
+ "**/*.(t|j)s"
99
+ ],
100
+ "coverageDirectory": "../coverage",
101
+ "testEnvironment": "node"
102
+ }
103
+ }
@@ -25,6 +25,7 @@ export declare class DepositService extends DefaultService {
25
25
  private resolveOrderNo;
26
26
  private resolveMemberId;
27
27
  private resolveMemberName;
28
+ private getClaimRefundInfo;
28
29
  private getNextCashReceiptIssueStatus;
29
30
  private updateDepositOrderPaymentState;
30
31
  private buildCashReceiptSummary;
@@ -59,7 +59,9 @@ const typeorm_1 = require("typeorm");
59
59
  const depositOrderDetail_entity_1 = require("./entity/depositOrderDetail.entity");
60
60
  const partner_service_1 = require("../../admin/partner/partner.service");
61
61
  const core_1 = require("@nestjs/core");
62
+ const date_fns_1 = require("date-fns");
62
63
  const depositOrder_entity_1 = require("./entity/depositOrder.entity");
64
+ const depositOrderClaimRefund_entity_1 = require("./entity/depositOrderClaimRefund.entity");
63
65
  let DepositService = DepositService_1 = class DepositService extends default_service_1.DefaultService {
64
66
  constructor(partnerService, moduleRef) {
65
67
  super(moduleRef);
@@ -98,6 +100,38 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
98
100
  var _a;
99
101
  return ((_a = orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.order) === null || _a === void 0 ? void 0 : _a.ordererName) || fallback;
100
102
  }
103
+ async getClaimRefundInfo(partnerSno, claimNo) {
104
+ var _a, _b, _c;
105
+ const partner = await this.partnerService.findOne(partnerSno);
106
+ if (!partner) {
107
+ throw new common_1.HttpException('유효하지 않은 파트너 정보입니다.', common_1.HttpStatus.BAD_REQUEST);
108
+ }
109
+ const today = new Date();
110
+ const startYmd = (0, date_fns_1.format)((0, date_fns_1.subDays)(today, 3), 'yyyy-MM-dd');
111
+ const endYmd = (0, date_fns_1.format)(today, 'yyyy-MM-dd');
112
+ const claimResult = await (0, gsUtil_1.shopByServerApi)(`/claims`, enum_1.HTTP_METHOD.GET, partner.systemKey, partner.longLivedToken, {
113
+ searchType: 'CLAIM_NO',
114
+ searchValues: String(claimNo),
115
+ endYmd,
116
+ page: 1,
117
+ searchDateType: 'COMPLETE_YMDT',
118
+ size: 10,
119
+ startYmd,
120
+ });
121
+ const claimContent = Array.isArray(claimResult === null || claimResult === void 0 ? void 0 : claimResult.contents)
122
+ ? claimResult.contents[0]
123
+ : null;
124
+ this.logger.log(`[getClaimExternalPayRefundAmount] claimNo=${claimNo} claimResult=${JSON.stringify(claimResult)}`);
125
+ const externalPayAmt = Number(((_c = (_b = (_a = claimContent === null || claimContent === void 0 ? void 0 : claimContent.claimData) === null || _a === void 0 ? void 0 : _a.amounts) === null || _b === void 0 ? void 0 : _b.adjustedAmounts) === null || _c === void 0 ? void 0 : _c.externalPayAmt) || 0);
126
+ const orderOptionNos = Array.isArray(claimContent === null || claimContent === void 0 ? void 0 : claimContent.orderOptionNos)
127
+ ? claimContent.orderOptionNos.map((optionNo) => String(optionNo))
128
+ : [];
129
+ this.logger.log(`[getClaimExternalPayRefundAmount] claimNo=${claimNo} externalPayAmt=${externalPayAmt}`);
130
+ return {
131
+ externalPayAmt,
132
+ orderOptionNos,
133
+ };
134
+ }
101
135
  getNextCashReceiptIssueStatus(depositOrder, orderInfo) {
102
136
  return depositOrder.usedAmount > 0 &&
103
137
  this.isPaymentDone(orderInfo) &&
@@ -175,7 +209,9 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
175
209
  })),
176
210
  ].sort((a, b) => {
177
211
  const left = (a === null || a === void 0 ? void 0 : a.requestedAt) ? new Date(a.requestedAt).getTime() : 0;
178
- const right = (b === null || b === void 0 ? void 0 : b.requestedAt) ? new Date(b.requestedAt).getTime() : 0;
212
+ const right = (b === null || b === void 0 ? void 0 : b.requestedAt)
213
+ ? new Date(b.requestedAt).getTime()
214
+ : 0;
179
215
  return right - left;
180
216
  });
181
217
  return {
@@ -238,7 +274,9 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
238
274
  const receiptIds = Array.from(new Set(Array.from(receiptByOrderNo.values()).map((receipt) => Number(receipt.sno))));
239
275
  const cancellationsByReceiptId = new Map();
240
276
  if (receiptIds.length) {
241
- const cancellationPlaceholders = receiptIds.map(() => '?').join(', ');
277
+ const cancellationPlaceholders = receiptIds
278
+ .map(() => '?')
279
+ .join(', ');
242
280
  const cancellations = await entityManager.query(`
243
281
  SELECT *
244
282
  FROM gs_cash_receipt_cancellations
@@ -1185,8 +1223,7 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
1185
1223
  });
1186
1224
  });
1187
1225
  });
1188
- const totalBaseAmount = orderInfo.order.lastStandardAmt ||
1189
- flattenedOptions.reduce((sum, opt) => sum + opt.price, 0);
1226
+ const totalBaseAmount = flattenedOptions.reduce((sum, opt) => sum + Number(opt.price || 0), 0);
1190
1227
  let remainToDeductMaster = depositOrder.usedAmount;
1191
1228
  let issueIndex = 0;
1192
1229
  const orderDetails = [];
@@ -1260,40 +1297,66 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
1260
1297
  async refundDepositOrder(targetItems) {
1261
1298
  const entityManager = await this.getEntityManager();
1262
1299
  return await entityManager.transaction(async (manager) => {
1300
+ var _a;
1301
+ const groupedClaims = new Map();
1263
1302
  for (const item of targetItems) {
1303
+ const claimKey = String(item.claimNo || `${item.orderNo}-no-claim`);
1304
+ const group = (_a = groupedClaims.get(claimKey)) !== null && _a !== void 0 ? _a : [];
1305
+ group.push(item);
1306
+ groupedClaims.set(claimKey, group);
1307
+ }
1308
+ for (const groupedItems of groupedClaims.values()) {
1309
+ const item = groupedItems[0];
1264
1310
  const orderNo = item.orderNo;
1265
- const productNo = String(item.mallProductNo);
1266
- const optionNo = String(item.mallOptionNo);
1267
- const cancelQty = Number(item.orderCnt || 0);
1311
+ const claimNo = Number(item.claimNo || 0);
1268
1312
  const depositOrder = await manager.findOne(depositOrder_entity_1.DepositOrder, {
1269
1313
  where: { orderNo },
1270
1314
  });
1271
1315
  if (!depositOrder)
1272
1316
  continue;
1273
- const usedDetails = await manager.find(depositOrderDetail_entity_1.DepositOrderDetail, {
1317
+ if (Number(depositOrder.usedAmount || 0) <= 0)
1318
+ continue;
1319
+ if (!claimNo)
1320
+ continue;
1321
+ const alreadyRefundedByClaim = await manager.findOne(depositOrderClaimRefund_entity_1.DepositOrderClaimRefund, {
1322
+ where: {
1323
+ orderSno: depositOrder.sno,
1324
+ claimNo,
1325
+ },
1326
+ });
1327
+ if (alreadyRefundedByClaim)
1328
+ continue;
1329
+ const claimRefundInfo = await this.getClaimRefundInfo(depositOrder.partnerSno, claimNo);
1330
+ const requestedRefundAmt = claimRefundInfo.externalPayAmt;
1331
+ const orderDetails = await manager.find(depositOrderDetail_entity_1.DepositOrderDetail, {
1274
1332
  where: {
1275
1333
  orderSno: depositOrder.sno,
1276
- mallProductNo: productNo,
1277
- mallOptionNo: Number(optionNo),
1278
1334
  },
1279
1335
  order: { sno: 'ASC' },
1280
1336
  });
1337
+ const targetOptionNos = new Set(claimRefundInfo.orderOptionNos);
1338
+ const usedDetails = targetOptionNos.size
1339
+ ? orderDetails.filter((detail) => targetOptionNos.has(String(detail.orderProductOptionNo)))
1340
+ : orderDetails;
1281
1341
  if (!usedDetails.length)
1282
1342
  continue;
1283
- const totalRemainQty = Number(usedDetails[0].orderCnt) -
1284
- Number(usedDetails[0].refundCnt);
1343
+ if (requestedRefundAmt <= 0) {
1344
+ await manager.save(depositOrderClaimRefund_entity_1.DepositOrderClaimRefund, {
1345
+ orderSno: depositOrder.sno,
1346
+ partnerSno: depositOrder.partnerSno,
1347
+ memberNo: depositOrder.memberNo,
1348
+ claimNo,
1349
+ orderProductOptionNos: claimRefundInfo.orderOptionNos.join(','),
1350
+ refundAmount: 0,
1351
+ refundDt: new Date(),
1352
+ });
1353
+ continue;
1354
+ }
1285
1355
  const totalRemainAmt = usedDetails.reduce((sum, d) => sum +
1286
1356
  (Number(d.usedDepositAmount) - Number(d.refundAmount)), 0);
1287
- if (totalRemainAmt <= 0 || totalRemainQty <= 0)
1357
+ if (totalRemainAmt <= 0)
1288
1358
  continue;
1289
- const isFullCancel = Number(item.orderCnt) === Number(item.originalOrderCnt);
1290
- const unitPrice = totalRemainAmt / totalRemainQty;
1291
- const actualTakeQty = Math.min(cancelQty, totalRemainQty);
1292
- let totalRefundAmt = isFullCancel
1293
- ? totalRemainAmt
1294
- : Math.round(unitPrice * actualTakeQty);
1295
- if (totalRefundAmt > totalRemainAmt)
1296
- totalRefundAmt = totalRemainAmt;
1359
+ const totalRefundAmt = Math.min(requestedRefundAmt, totalRemainAmt);
1297
1360
  let remainRefundAmt = totalRefundAmt;
1298
1361
  for (const detail of usedDetails) {
1299
1362
  if (remainRefundAmt <= 0)
@@ -1310,6 +1373,9 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
1310
1373
  await manager.update(depositOrderDetail_entity_1.DepositOrderDetail, detail.sno, {
1311
1374
  refundAmount: newRefundAmount,
1312
1375
  refundYn: isRecordDone ? enum_1.YN.Y : enum_1.YN.N,
1376
+ refundCnt: isRecordDone
1377
+ ? Number(detail.orderCnt || 0)
1378
+ : Number(detail.refundCnt || 0),
1313
1379
  refundDt: new Date(),
1314
1380
  cashReceiptCancelStatus: newRefundAmount > 0 &&
1315
1381
  shouldRequestCashReceiptCancel
@@ -1318,17 +1384,6 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
1318
1384
  });
1319
1385
  remainRefundAmt -= takeAmt;
1320
1386
  }
1321
- const updatedRefundCnt = Math.min(Number(usedDetails[0].refundCnt) + actualTakeQty, Number(usedDetails[0].orderCnt));
1322
- const firstDetailRefundGain = Math.min(Number(usedDetails[0].usedDepositAmount) -
1323
- Number(usedDetails[0].refundAmount), totalRefundAmt);
1324
- const updatedFirstDetailRefundAmount = Number(usedDetails[0].refundAmount) + firstDetailRefundGain;
1325
- const isFullyRefunded = updatedRefundCnt >= Number(usedDetails[0].orderCnt) &&
1326
- updatedFirstDetailRefundAmount >=
1327
- Number(usedDetails[0].usedDepositAmount);
1328
- await manager.update(depositOrderDetail_entity_1.DepositOrderDetail, usedDetails[0].sno, {
1329
- refundCnt: updatedRefundCnt,
1330
- refundYn: isFullyRefunded ? enum_1.YN.Y : usedDetails[0].refundYn,
1331
- });
1332
1387
  if (totalRefundAmt > 0) {
1333
1388
  const [lastLedger] = await manager.query(`SELECT balanceAfter FROM gs_depositManager WHERE partnerSno = ? AND memberNo = ? ORDER BY sno DESC LIMIT 1 FOR UPDATE`, [depositOrder.partnerSno, depositOrder.memberNo]);
1334
1389
  const prevBalance = Number((lastLedger === null || lastLedger === void 0 ? void 0 : lastLedger.balanceAfter) || 0);
@@ -1343,9 +1398,18 @@ let DepositService = DepositService_1 = class DepositService extends default_ser
1343
1398
  refSno: depositOrder.sno,
1344
1399
  depositAmount: totalRefundAmt,
1345
1400
  balanceAfter: prevBalance + totalRefundAmt,
1346
- reason: `주문 환불 (상품:${(item.productName || productNo).substring(0, 15)}, 수량:${actualTakeQty})`,
1401
+ reason: `주문 환불 (claimNo:${claimNo})`,
1347
1402
  });
1348
1403
  }
1404
+ await manager.save(depositOrderClaimRefund_entity_1.DepositOrderClaimRefund, {
1405
+ orderSno: depositOrder.sno,
1406
+ partnerSno: depositOrder.partnerSno,
1407
+ memberNo: depositOrder.memberNo,
1408
+ claimNo,
1409
+ orderProductOptionNos: claimRefundInfo.orderOptionNos.join(','),
1410
+ refundAmount: totalRefundAmt,
1411
+ refundDt: new Date(),
1412
+ });
1349
1413
  }
1350
1414
  return { rescode: '0000', message: 'SUCCESS' };
1351
1415
  });