@chevre/domain 22.10.0-alpha.8 → 22.10.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.
Files changed (108) hide show
  1. package/example/src/chevre/adminIdentities.ts +8 -8
  2. package/example/src/chevre/assetTransaction/processReserve.ts +4 -1
  3. package/example/src/chevre/concurrentLock/lockOfferRateLimit.ts +64 -0
  4. package/example/src/chevre/concurrentLock/lockTransactionProcess.ts +44 -0
  5. package/example/src/chevre/createTaskIfNotExistByAlternateName.ts +1 -1
  6. package/example/src/chevre/findOneAvailableHours.ts +39 -0
  7. package/example/src/chevre/identity/getCommonClients.ts +126 -0
  8. package/example/src/chevre/identity/migrateClients2oauth.ts +200 -0
  9. package/example/src/chevre/issuer/adminMemberProgramTiers.ts +55 -0
  10. package/example/src/chevre/maintenance/checkTransactionStatuses.ts +105 -0
  11. package/example/src/chevre/migrateIdentities.ts +24 -37
  12. package/example/src/chevre/reIndex.ts +1 -1
  13. package/example/src/chevre/roles/addPermissionIfNotExists.ts +27 -0
  14. package/example/src/chevre/roles/addRoleMembers.ts +75 -0
  15. package/example/src/chevre/saveWebSite.ts +14 -17
  16. package/example/src/chevre/stockHolder/checkRedisKeyCount.ts +43 -22
  17. package/example/src/chevre/transactionNumber/publishConfimationNumber.ts +37 -0
  18. package/example/src/chevre/transactionNumber/publishOrderNumber.ts +40 -0
  19. package/example/src/chevre/transactionNumber/setUseMongo4confirmationNumberFrom.ts +45 -0
  20. package/example/src/chevre/transactionNumber/setUseMongo4orderNumberFrom.ts +41 -0
  21. package/example/src/chevre/transactionNumber/setUseMongo4transactionNumberFrom.ts +41 -0
  22. package/example/src/redisMulti.ts +63 -0
  23. package/example/src/signPayload.ts +1 -1
  24. package/lib/chevre/eventEmitter/task.d.ts +36 -6
  25. package/lib/chevre/eventEmitter/task.js +5 -4
  26. package/lib/chevre/eventEmitter.d.ts +2 -2
  27. package/lib/chevre/eventEmitter.js +2 -2
  28. package/lib/chevre/repo/concurrentLock.d.ts +14 -0
  29. package/lib/chevre/repo/concurrentLock.js +48 -0
  30. package/lib/chevre/repo/concurrentLockAbstract.d.ts +42 -0
  31. package/lib/chevre/repo/concurrentLockAbstract.js +9 -0
  32. package/lib/chevre/repo/confirmationNumber.d.ts +17 -4
  33. package/lib/chevre/repo/confirmationNumber.js +89 -32
  34. package/lib/chevre/repo/identity.d.ts +42 -5
  35. package/lib/chevre/repo/identity.js +35 -4
  36. package/lib/chevre/repo/issuer.d.ts +10 -2
  37. package/lib/chevre/repo/member.js +2 -2
  38. package/lib/chevre/repo/memberProgram.d.ts +43 -2
  39. package/lib/chevre/repo/memberProgram.js +79 -8
  40. package/lib/chevre/repo/mongoose/schemas/issuer.d.ts +3 -1
  41. package/lib/chevre/repo/mongoose/schemas/issuer.js +10 -0
  42. package/lib/chevre/repo/mongoose/schemas/offer/event.js +30 -2
  43. package/lib/chevre/repo/mongoose/schemas/role.d.ts +2 -3
  44. package/lib/chevre/repo/mongoose/schemas/role.js +11 -1
  45. package/lib/chevre/repo/mongoose/schemas/service/availableHour.d.ts +18 -0
  46. package/lib/chevre/repo/mongoose/schemas/service/availableHour.js +65 -0
  47. package/lib/chevre/repo/mongoose/schemas/setting.d.ts +3 -0
  48. package/lib/chevre/repo/mongoose/schemas/setting.js +4 -1
  49. package/lib/chevre/repo/mongoose/schemas/transactionNumber.d.ts +39 -0
  50. package/lib/chevre/repo/mongoose/schemas/transactionNumber.js +101 -0
  51. package/lib/chevre/repo/orderNumber.d.ts +15 -4
  52. package/lib/chevre/repo/orderNumber.js +71 -24
  53. package/lib/chevre/repo/passport.d.ts +1 -1
  54. package/lib/chevre/repo/passport.js +31 -13
  55. package/lib/chevre/repo/rateLimit/offer.d.ts +7 -2
  56. package/lib/chevre/repo/rateLimit/offer.js +41 -40
  57. package/lib/chevre/repo/role.d.ts +18 -4
  58. package/lib/chevre/repo/role.js +53 -4
  59. package/lib/chevre/repo/service/availableHour.d.ts +15 -0
  60. package/lib/chevre/repo/service/availableHour.js +53 -0
  61. package/lib/chevre/repo/serviceOutputIdentifier.d.ts +8 -4
  62. package/lib/chevre/repo/serviceOutputIdentifier.js +54 -22
  63. package/lib/chevre/repo/stockHolder.d.ts +0 -2
  64. package/lib/chevre/repo/stockHolder.js +24 -31
  65. package/lib/chevre/repo/task.d.ts +10 -25
  66. package/lib/chevre/repo/task.js +65 -36
  67. package/lib/chevre/repo/transactionNumber.d.ts +15 -4
  68. package/lib/chevre/repo/transactionNumber.js +67 -22
  69. package/lib/chevre/repo/transactionNumberCounter.d.ts +28 -0
  70. package/lib/chevre/repo/transactionNumberCounter.js +128 -0
  71. package/lib/chevre/repo/transactionProcess.d.ts +7 -4
  72. package/lib/chevre/repo/transactionProcess.js +34 -13
  73. package/lib/chevre/repository.d.ts +5 -0
  74. package/lib/chevre/repository.js +14 -1
  75. package/lib/chevre/service/aggregation/event/aggregateOffers.js +1 -0
  76. package/lib/chevre/service/assetTransaction/reserve/start.js +9 -1
  77. package/lib/chevre/service/assetTransaction/reserve/validateStartRequest.js +1 -1
  78. package/lib/chevre/service/code.js +1 -1
  79. package/lib/chevre/service/offer/event/checkAvailability.d.ts +1 -1
  80. package/lib/chevre/service/offer/event/checkAvailability.js +1 -0
  81. package/lib/chevre/service/offer/product.js +0 -40
  82. package/lib/chevre/service/payment/any.d.ts +0 -2
  83. package/lib/chevre/service/payment/any.js +1 -0
  84. package/lib/chevre/service/reserve/cancelReservation.d.ts +3 -0
  85. package/lib/chevre/service/reserve/cancelReservation.js +5 -1
  86. package/lib/chevre/service/task/acceptCOAOffer.js +2 -2
  87. package/lib/chevre/service/task/authorizePayment.js +4 -4
  88. package/lib/chevre/service/task/givePointAward.js +1 -1
  89. package/lib/chevre/service/task/moneyTransfer.js +1 -1
  90. package/lib/chevre/service/task/publishPaymentUrl.js +2 -2
  91. package/lib/chevre/service/task/refund.js +1 -1
  92. package/lib/chevre/service/task/returnMoneyTransfer.js +1 -1
  93. package/lib/chevre/service/task/returnPayTransaction.js +1 -1
  94. package/lib/chevre/service/task/returnPointAward.js +1 -1
  95. package/lib/chevre/service/task/returnReserveTransaction.js +1 -1
  96. package/lib/chevre/service/task.d.ts +8 -17
  97. package/lib/chevre/service/task.js +14 -5
  98. package/lib/chevre/service/transaction/placeOrder/start/validateStartRequest.js +2 -2
  99. package/lib/chevre/service/transaction/returnOrder/preStart/factory.d.ts +20 -0
  100. package/lib/chevre/service/transaction/returnOrder/preStart/factory.js +2 -0
  101. package/lib/chevre/service/transaction/returnOrder/preStart/findApplicableReturnPolicy.d.ts +23 -0
  102. package/lib/chevre/service/transaction/returnOrder/preStart/findApplicableReturnPolicy.js +323 -0
  103. package/lib/chevre/service/transaction/returnOrder/preStart/getReturnPolicyByProject.d.ts +13 -0
  104. package/lib/chevre/service/transaction/returnOrder/preStart/getReturnPolicyByProject.js +132 -0
  105. package/lib/chevre/service/transaction/returnOrder/preStart.js +2 -391
  106. package/package.json +3 -3
  107. package/example/src/chevre/migrateMembers2identities.ts +0 -109
  108. package/example/src/chevre/publishConfimationNumber.ts +0 -27
@@ -1,6 +1,5 @@
1
- import type { Connection } from 'mongoose';
2
- import type { RedisClientType } from 'redis';
3
1
  import { SendGridCredentials } from '../credentials/sendGrid';
2
+ import type { IExecuteSettings as IMinimumExecuteSettings, INextFunction, IReadyTask, IRunningTask } from '../eventEmitter/task';
4
3
  import * as factory from '../factory';
5
4
  import type { IExecutableTask, IExecutableTaskKeys, TaskRepo } from '../repo/task';
6
5
  import { Settings } from '../settings';
@@ -8,15 +7,7 @@ import { AggregationSettings } from '../settings/aggregation';
8
7
  interface ICredentialSettings {
9
8
  sendGrid: SendGridCredentials;
10
9
  }
11
- interface IExecuteSettings {
12
- /**
13
- * MongoDBコネクション
14
- */
15
- connection: Connection;
16
- /**
17
- * Redisクライアント
18
- */
19
- redisClient?: RedisClientType;
10
+ interface IExecuteSettings extends IMinimumExecuteSettings {
20
11
  credentials: ICredentialSettings;
21
12
  settings: Settings;
22
13
  aggregationSettings?: AggregationSettings;
@@ -29,17 +20,17 @@ type IOperation<T> = (settings: IExecuteSettings) => Promise<T>;
29
20
  type IOperationExecute<T> = (settings: IExecuteSettings, options: IExecuteOptions) => Promise<T>;
30
21
  type ICallResult = void | Pick<factory.task.IExecutionResult, 'error'>;
31
22
  export type ICallableTaskOperation = (task: IExecutableTask<factory.taskName>) => IOperationExecute<ICallResult>;
32
- declare function executeById(params: {
33
- id: string;
34
- status: factory.taskStatus.Ready | factory.taskStatus.Running;
23
+ /**
24
+ * タスク変更イベントを受けて実行する
25
+ */
26
+ declare function executeById(params: (IReadyTask | IRunningTask) & {
35
27
  executor: {
36
28
  /**
37
29
  * タスク実行者名称
38
30
  */
39
31
  name: string;
40
32
  };
41
- expires?: Date;
42
- }): IOperation<void>;
33
+ }, next?: INextFunction): IOperation<void>;
43
34
  /**
44
35
  * support no name(2025-03-04~)
45
36
  */
@@ -61,7 +52,7 @@ declare function executeOneIfExists(params: {
61
52
  /**
62
53
  * タスクを実行する
63
54
  */
64
- declare function execute(task: IExecutableTask<factory.taskName>): IOperationExecute<void>;
55
+ declare function execute(task: IExecutableTask<factory.taskName>, next?: INextFunction): IOperationExecute<void>;
65
56
  /**
66
57
  * add(2025-03-13~)
67
58
  */
@@ -21,7 +21,10 @@ const moment = require("moment");
21
21
  const factory = require("../factory");
22
22
  const factory_1 = require("./notification/factory");
23
23
  const debug = createDebug('chevre-domain:service:task');
24
- function executeById(params) {
24
+ /**
25
+ * タスク変更イベントを受けて実行する
26
+ */
27
+ function executeById(params, next) {
25
28
  return (settings) => __awaiter(this, void 0, void 0, function* () {
26
29
  const taskRepo = new (yield Promise.resolve().then(() => require('../repo/task'))).TaskRepo(settings.connection);
27
30
  const { id, status, executor, expires } = params;
@@ -39,7 +42,7 @@ function executeById(params) {
39
42
  }
40
43
  // タスクがなければ終了
41
44
  if (task !== null) {
42
- yield execute(task)(settings, {
45
+ yield execute(task, (typeof next === 'function') ? next : undefined)(settings, {
43
46
  executeById: true,
44
47
  executeByName: false
45
48
  });
@@ -77,7 +80,7 @@ function executeOneIfExists(params) {
77
80
  /**
78
81
  * タスクを実行する
79
82
  */
80
- function execute(task) {
83
+ function execute(task, next) {
81
84
  const now = new Date();
82
85
  debug('executing an executableTask...', task, now);
83
86
  return (settings, options) => __awaiter(this, void 0, void 0, function* () {
@@ -129,7 +132,10 @@ function execute(task) {
129
132
  error: ((callResult === null || callResult === void 0 ? void 0 : callResult.error) instanceof Error)
130
133
  ? Object.assign(Object.assign({}, callResult.error), { message: callResult.error.message }) : ''
131
134
  };
132
- yield taskRepo.pushExecutionResultById(task.id, factory.taskStatus.Executed, result);
135
+ yield taskRepo.pushExecutionResultById({
136
+ id: task.id,
137
+ status: factory.taskStatus.Executed
138
+ }, result, (typeof next === 'function') ? next : undefined);
133
139
  }
134
140
  catch (error) {
135
141
  debug('service.task.execute throwed an error. task:', task.name, task.id, 'error:', error === null || error === void 0 ? void 0 : error.name, error === null || error === void 0 ? void 0 : error.message);
@@ -143,7 +149,10 @@ function execute(task) {
143
149
  error: Object.assign(Object.assign({}, error), { code: error.code, message: error.message, name: error.name, stack: error.stack })
144
150
  };
145
151
  // 失敗してもここではステータスを戻さない(Runningのまま待機)
146
- yield taskRepo.pushExecutionResultById(task.id, task.status, result);
152
+ yield taskRepo.pushExecutionResultById({
153
+ id: task.id,
154
+ status: task.status
155
+ }, result, (typeof next === 'function') ? next : undefined);
147
156
  }
148
157
  });
149
158
  }
@@ -116,7 +116,7 @@ function validateStartRequest(params) {
116
116
  }
117
117
  })).shift();
118
118
  if (iamMember === undefined) {
119
- throw new factory.errors.NotFound(factory.iam.RoleType.OrganizationRole);
119
+ throw new factory.errors.NotFound(factory.role.RoleType.OrganizationRole);
120
120
  }
121
121
  // メンバーシップトークン検証(2024-01-31~)
122
122
  let memeberOfPayload;
@@ -124,7 +124,7 @@ function validateStartRequest(params) {
124
124
  const validMemberProgramIdentifier = (_c = projectMakesOffer.validForMemberTier) === null || _c === void 0 ? void 0 : _c.isTierOf.identifier;
125
125
  if (typeof validMemberProgramIdentifier === 'string') {
126
126
  // メンバープログラムと発行者を参照(2025-01-16~)
127
- const memberProgram = (yield repos.memberProgram.search({
127
+ const memberProgram = (yield repos.memberProgram.projectMemberPrograms({
128
128
  limit: 1,
129
129
  page: 1,
130
130
  project: { id: { $eq: params.project.id } },
@@ -0,0 +1,20 @@
1
+ import * as factory from '../../../../factory';
2
+ /**
3
+ * 販売者に設定された利用可能な販売者返品ポリシー
4
+ */
5
+ type IAvailableSellerReturnPolicy = Pick<factory.sellerReturnPolicy.ISellerReturnPolicy, 'applicablePaymentMethod' | 'identifier' | 'itemCondition' | 'merchantReturnDays' | 'restockingFee' | 'typeOf'>;
6
+ /**
7
+ * プロジェクトのカスタム返品ポリシー
8
+ * リモートから取得
9
+ */
10
+ type ICustomSellerReturnPolicy = Pick<factory.sellerReturnPolicy.ISellerReturnPolicy, 'identifier' | 'restockingFee' | 'typeOf'> & {
11
+ /**
12
+ * support itemCondition(2025-05-17~)
13
+ */
14
+ itemCondition?: factory.offerItemCondition.OfferItemCondition;
15
+ applicablePaymentMethod?: never;
16
+ merchantReturnDays?: never;
17
+ };
18
+ type IFixedAcceptedOffer = Pick<factory.order.IAcceptedOffer<factory.order.IItemOffered>, 'id' | 'priceSpecification' | 'itemOffered'>;
19
+ type IFixedOrder = Pick<factory.order.IOrder, 'confirmationNumber' | 'dateReturned' | 'orderDate' | 'orderNumber' | 'orderStatus' | 'paymentMethods' | 'price' | 'project' | 'seller' | 'typeOf'>;
20
+ export { IAvailableSellerReturnPolicy, ICustomSellerReturnPolicy, IFixedAcceptedOffer, IFixedOrder };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,23 @@
1
+ import * as factory from '../../../../factory';
2
+ import { IAvailableSellerReturnPolicy, IFixedAcceptedOffer, IFixedOrder } from './factory';
3
+ /**
4
+ * 採用可能な販売者の返品ポリシーをひとつ選択する
5
+ * restockingFeeが最低のポリシーを自動選択
6
+ */
7
+ declare function findApplicableReturnPolicy(params: {
8
+ acceptedOffers: IFixedAcceptedOffer[];
9
+ events: {
10
+ id: string;
11
+ startDate: Date;
12
+ }[];
13
+ offerItemConditions: Pick<factory.offerItemCondition.IOfferItemCondition, 'id' | 'identifier' | 'itemOffered' | 'typeOf'>[];
14
+ orders: IFixedOrder[];
15
+ returningDate: Date;
16
+ reason: factory.transaction.returnOrder.Reason;
17
+ returnPolicies: IAvailableSellerReturnPolicy[];
18
+ returnPolicySettingsByProject?: factory.project.IHasMerchantReturnPolicy;
19
+ offers: factory.unitPriceOffer.IUnitPriceOffer[];
20
+ policiesByOffer: factory.unitPriceOffer.IOfferMerchantReturnPolicy[];
21
+ usedReservationExists: boolean;
22
+ }): Promise<factory.action.transfer.returnAction.order.IReturnPolicy>;
23
+ export { findApplicableReturnPolicy };
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.findApplicableReturnPolicy = findApplicableReturnPolicy;
13
+ const createDebug = require("debug");
14
+ const moment = require("moment-timezone");
15
+ const factory = require("../../../../factory");
16
+ const getReturnPolicyByProject_1 = require("./getReturnPolicyByProject");
17
+ const debug = createDebug('chevre-domain:service');
18
+ /**
19
+ * 採用可能な販売者の返品ポリシーをひとつ選択する
20
+ * restockingFeeが最低のポリシーを自動選択
21
+ */
22
+ // tslint:disable-next-line:max-func-body-length
23
+ function findApplicableReturnPolicy(params) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ var _a, _b, _c;
26
+ if (params.reason === factory.transaction.returnOrder.Reason.Seller) {
27
+ // 販売者都合の場合、手数料なしの返金返品ポリシーを適用
28
+ return {
29
+ typeOf: 'MerchantReturnPolicy',
30
+ returnFees: factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn
31
+ // no identifier in this case
32
+ };
33
+ }
34
+ const returnPolicies = params.returnPolicies;
35
+ let applicalbleReturnPolicies = [];
36
+ if (params.reason === factory.transaction.returnOrder.Reason.Customer) {
37
+ // プロジェクトの返品ポリシー設定を考慮(2023-11-14~)
38
+ const returnPolicySameAsByPoject = (_a = params.returnPolicySettingsByProject) === null || _a === void 0 ? void 0 : _a.sameAs;
39
+ if (typeof returnPolicySameAsByPoject === 'string' && returnPolicySameAsByPoject.length > 0) {
40
+ const returnPolicyByProject = yield (0, getReturnPolicyByProject_1.getReturnPolicyByProject)({
41
+ identifier: String((_b = params.returnPolicySettingsByProject) === null || _b === void 0 ? void 0 : _b.identifier),
42
+ sameAs: returnPolicySameAsByPoject,
43
+ order: Object.assign(Object.assign({}, params.orders[0]), { acceptedOffers: params.acceptedOffers })
44
+ });
45
+ applicalbleReturnPolicies.push(returnPolicyByProject);
46
+ }
47
+ else {
48
+ applicalbleReturnPolicies = returnPolicies;
49
+ }
50
+ }
51
+ // 適用可能なポリシーにフィルター
52
+ applicalbleReturnPolicies = applicalbleReturnPolicies.filter((returnPolicy) => {
53
+ return isSellerReturnPolicyApplicable({
54
+ returnPolicy,
55
+ events: params.events,
56
+ offerItemConditions: params.offerItemConditions,
57
+ orders: params.orders,
58
+ returningDate: params.returningDate,
59
+ usedReservationExists: params.usedReservationExists
60
+ });
61
+ });
62
+ // 販売者にポリシーが存在しなければ返品不可
63
+ if (applicalbleReturnPolicies.length === 0) {
64
+ throw new factory.errors.Argument('Seller', 'has no applicable return policies');
65
+ }
66
+ // オファーの返品ポリシーから返品手数料タイプを決定する
67
+ const { returnFees, returnFeesMovieTicket } = validateOffersReturnPolicy({
68
+ acceptedOffers: params.acceptedOffers,
69
+ offers: params.offers,
70
+ policiesByOffer: params.policiesByOffer
71
+ });
72
+ // restockingFeeが最低のポリシーを自動選択
73
+ let appliedReturnPolicy = applicalbleReturnPolicies[0];
74
+ applicalbleReturnPolicies.forEach((returnPolicy) => {
75
+ var _a, _b;
76
+ const appliedReturnPolicyRestockingFeeValue = (_a = appliedReturnPolicy.restockingFee) === null || _a === void 0 ? void 0 : _a.value;
77
+ const restockingFeeValue = (_b = returnPolicy.restockingFee) === null || _b === void 0 ? void 0 : _b.value;
78
+ const appliedReturnPolicyRestockingFee = (typeof appliedReturnPolicyRestockingFeeValue === 'number')
79
+ ? appliedReturnPolicyRestockingFeeValue
80
+ : 0;
81
+ const restockingFeeAsNumber = (typeof restockingFeeValue === 'number') ? restockingFeeValue : 0;
82
+ if (restockingFeeAsNumber < appliedReturnPolicyRestockingFee) {
83
+ appliedReturnPolicy = returnPolicy;
84
+ }
85
+ });
86
+ let appliedItemConditionAsStr;
87
+ let appliedItemCondition;
88
+ let appliedItemConditionId;
89
+ if (typeof appliedReturnPolicy.itemCondition === 'string') {
90
+ appliedItemConditionAsStr = appliedReturnPolicy.itemCondition;
91
+ }
92
+ else {
93
+ appliedItemConditionId = (_c = appliedReturnPolicy.itemCondition) === null || _c === void 0 ? void 0 : _c.id;
94
+ }
95
+ if (typeof appliedItemConditionId === 'string') {
96
+ const appliedItemConditionFromDB = params.offerItemConditions.find((o) => o.id === appliedItemConditionId);
97
+ if (appliedItemConditionFromDB === undefined) {
98
+ throw new factory.errors.NotFound('OfferItemCondition');
99
+ }
100
+ appliedItemCondition = Object.assign({ identifier: appliedItemConditionFromDB.identifier, itemOffered: appliedItemConditionFromDB.itemOffered, typeOf: appliedItemConditionFromDB.typeOf }, (typeof appliedItemConditionFromDB.id === 'string') ? { id: appliedItemConditionFromDB.id } : undefined);
101
+ }
102
+ const { restockingFee, typeOf, identifier, merchantReturnDays } = appliedReturnPolicy;
103
+ return Object.assign(Object.assign(Object.assign(Object.assign({ restockingFee,
104
+ returnFees, // offerのreturnPolicyから決定する
105
+ returnFeesMovieTicket,
106
+ typeOf }, (typeof identifier === 'string') ? { identifier } : undefined), (typeof merchantReturnDays === 'number') ? { merchantReturnDays } : undefined), (typeof (appliedItemCondition === null || appliedItemCondition === void 0 ? void 0 : appliedItemCondition.typeOf) === 'string') ? { itemCondition: appliedItemCondition } : undefined), (typeof appliedItemConditionAsStr === 'string') ? { itemCondition: appliedItemConditionAsStr } : undefined);
107
+ });
108
+ }
109
+ /**
110
+ * 販売者返品ポリシーが採用可能かどうか検証する
111
+ * アイテムコンディションも含めて検証する
112
+ */
113
+ // tslint:disable-next-line:cyclomatic-complexity max-func-body-length
114
+ function isSellerReturnPolicyApplicable(params) {
115
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
116
+ const returnPolicy = params.returnPolicy;
117
+ const returningDate = moment(params.returningDate);
118
+ let satisfyMerchantReturnDays = false;
119
+ let satisfyApplicablePaymentMethod = false;
120
+ let offerItemConditionAsStr;
121
+ let offerItemCondition;
122
+ if (typeof returnPolicy.itemCondition === 'string') {
123
+ offerItemConditionAsStr = returnPolicy.itemCondition;
124
+ }
125
+ else {
126
+ const itemConditionId = (_a = returnPolicy.itemCondition) === null || _a === void 0 ? void 0 : _a.id;
127
+ if (typeof itemConditionId === 'string') {
128
+ offerItemCondition = params.offerItemConditions.find((o) => o.id === itemConditionId);
129
+ if (offerItemCondition === undefined) {
130
+ throw new factory.errors.NotFound('OfferItemCondition');
131
+ }
132
+ }
133
+ }
134
+ const merchantReturnDays = returnPolicy.merchantReturnDays;
135
+ if (typeof merchantReturnDays === 'number') {
136
+ // 返品適用日数を確認する
137
+ const everyOrderApplicable = params.orders.every((order) => {
138
+ const mustBeReturnedUntil = moment(order.orderDate)
139
+ .add(merchantReturnDays, 'days');
140
+ return mustBeReturnedUntil.isSameOrAfter(returningDate);
141
+ });
142
+ // 全注文について日数の確認ができれば適用
143
+ if (everyOrderApplicable) {
144
+ satisfyMerchantReturnDays = true;
145
+ }
146
+ }
147
+ else {
148
+ // 日数制限なし
149
+ satisfyMerchantReturnDays = true;
150
+ }
151
+ // 適用決済方法検証(2023-08-08~)
152
+ const applicablePaymentMethod = returnPolicy.applicablePaymentMethod;
153
+ if (Array.isArray(applicablePaymentMethod)) {
154
+ const everyOrderApplicable = params.orders.every((order) => {
155
+ // 全決済方法区分がapplicablePaymentMethodに含まれれば適用
156
+ return order.paymentMethods.every((invoice) => {
157
+ var _a;
158
+ return typeof ((_a = invoice.paymentMethod) === null || _a === void 0 ? void 0 : _a.identifier) === 'string'
159
+ && applicablePaymentMethod.includes(invoice.paymentMethod.identifier);
160
+ });
161
+ });
162
+ // 全注文について確認ができれば適用
163
+ if (everyOrderApplicable) {
164
+ satisfyApplicablePaymentMethod = true;
165
+ }
166
+ }
167
+ else {
168
+ satisfyApplicablePaymentMethod = true;
169
+ }
170
+ // アイテムコンディション検証
171
+ let satisfyItemCondition = true;
172
+ if (typeof offerItemConditionAsStr === 'string') {
173
+ if (offerItemConditionAsStr === factory.offerItemCondition.OfferItemCondition.NewCondition) {
174
+ let satisfyOnlyUnused = true;
175
+ if (params.usedReservationExists) {
176
+ satisfyOnlyUnused = false;
177
+ }
178
+ debug('usedReservationExists:', params.usedReservationExists, 'satisfyOnlyUnused:', satisfyOnlyUnused, 'itemCondition:', offerItemConditionAsStr);
179
+ satisfyItemCondition = satisfyOnlyUnused;
180
+ }
181
+ }
182
+ else {
183
+ if (offerItemCondition !== undefined) {
184
+ let satisfyGracePeriodMaxValue = true;
185
+ let satisfyGracePeriodMinValue = true;
186
+ // 全イベントについて猶予の確認ができれば適用
187
+ const gracePeriodMaxValue = (_c = (_b = offerItemCondition.itemOffered.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservationFor.gracePeriodBeforeStart) === null || _c === void 0 ? void 0 : _c.maxValue;
188
+ const gracePeriodMinValue = (_e = (_d = offerItemCondition.itemOffered.serviceOutput) === null || _d === void 0 ? void 0 : _d.reservationFor.gracePeriodBeforeStart) === null || _e === void 0 ? void 0 : _e.minValue;
189
+ if (typeof gracePeriodMaxValue === 'number') {
190
+ satisfyGracePeriodMaxValue = params.events.every((event) => {
191
+ return moment(event.startDate)
192
+ .isSameOrBefore(moment(params.returningDate)
193
+ .add(gracePeriodMaxValue, 'seconds'));
194
+ });
195
+ }
196
+ if (typeof gracePeriodMinValue === 'number') {
197
+ satisfyGracePeriodMinValue = params.events.every((event) => {
198
+ debug('isSellerReturnPolicyApplicable: comparing by gracePeriodMinValue...', 'gracePeriodMinValue:', gracePeriodMinValue, event.startDate, '>', moment(params.returningDate)
199
+ .add(gracePeriodMinValue, 'seconds'), '?');
200
+ return moment(event.startDate)
201
+ .isAfter(moment(params.returningDate)
202
+ .add(gracePeriodMinValue, 'seconds'));
203
+ });
204
+ }
205
+ let satisfyGracePeriodInDaysMax = true;
206
+ let satisfyGracePeriodInDaysMin = true;
207
+ const gracePeriodBeforeStartInDaysMax = (_g = (_f = offerItemCondition.itemOffered.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservationFor.gracePeriodBeforeStartInDays) === null || _g === void 0 ? void 0 : _g.max;
208
+ if (typeof (gracePeriodBeforeStartInDaysMax === null || gracePeriodBeforeStartInDaysMax === void 0 ? void 0 : gracePeriodBeforeStartInDaysMax.period.value) === 'number'
209
+ && typeof gracePeriodBeforeStartInDaysMax.time === 'string') {
210
+ satisfyGracePeriodInDaysMax = params.events.every((event) => {
211
+ const maxDate = moment(event.startDate)
212
+ .tz(gracePeriodBeforeStartInDaysMax.timezone)
213
+ .startOf('days')
214
+ .subtract(gracePeriodBeforeStartInDaysMax.period.value, 'days')
215
+ .format('YYYY-MM-DD');
216
+ const returnMinDate = moment.tz(`${maxDate}T${gracePeriodBeforeStartInDaysMax.time}`, gracePeriodBeforeStartInDaysMax.timezone);
217
+ debug('returnMinDate:', returnMinDate, 'returningDate:', returningDate);
218
+ return returnMinDate.isSameOrBefore(moment(returningDate));
219
+ });
220
+ }
221
+ debug('gracePeriodBeforeStartInDaysMax:', gracePeriodBeforeStartInDaysMax);
222
+ const gracePeriodBeforeStartInDaysMin = (_j = (_h = offerItemCondition.itemOffered.serviceOutput) === null || _h === void 0 ? void 0 : _h.reservationFor.gracePeriodBeforeStartInDays) === null || _j === void 0 ? void 0 : _j.min;
223
+ if (typeof (gracePeriodBeforeStartInDaysMin === null || gracePeriodBeforeStartInDaysMin === void 0 ? void 0 : gracePeriodBeforeStartInDaysMin.period.value) === 'number'
224
+ && typeof gracePeriodBeforeStartInDaysMin.time === 'string') {
225
+ satisfyGracePeriodInDaysMin = params.events.every((event) => {
226
+ const minDate = moment(event.startDate)
227
+ .tz(gracePeriodBeforeStartInDaysMin.timezone)
228
+ .startOf('days')
229
+ .subtract(gracePeriodBeforeStartInDaysMin.period.value, 'days')
230
+ .format('YYYY-MM-DD');
231
+ const returnMaxDate = moment.tz(`${minDate}T${gracePeriodBeforeStartInDaysMin.time}`, gracePeriodBeforeStartInDaysMin.timezone);
232
+ debug('returnMaxDate:', returnMaxDate, 'returningDate:', returningDate);
233
+ return returnMaxDate.isAfter(moment(returningDate));
234
+ });
235
+ }
236
+ debug('satisfyGracePeriodInDaysMin:', satisfyGracePeriodInDaysMin);
237
+ let satisfyOnlyUnused = true;
238
+ if (((_k = offerItemCondition.itemOffered.serviceOutput) === null || _k === void 0 ? void 0 : _k.onlyUnused) === true) {
239
+ if (params.usedReservationExists) {
240
+ satisfyOnlyUnused = false;
241
+ }
242
+ }
243
+ debug('usedReservationExists:', params.usedReservationExists, 'satisfyOnlyUnused:', satisfyOnlyUnused);
244
+ satisfyItemCondition = satisfyGracePeriodMaxValue && satisfyGracePeriodMinValue
245
+ && satisfyGracePeriodInDaysMax && satisfyGracePeriodInDaysMin && satisfyOnlyUnused;
246
+ }
247
+ }
248
+ return satisfyMerchantReturnDays && satisfyApplicablePaymentMethod && satisfyItemCondition;
249
+ }
250
+ /**
251
+ * 注文中のオファーの返品ポリシーを検証
252
+ */
253
+ function validateOffersReturnPolicy(params) {
254
+ // オファーに返品ポリシーが設定されているか?
255
+ const everyOffersHaveReturnPolicy = params.offers.every((offer) => {
256
+ return Array.isArray(offer.hasMerchantReturnPolicy) && offer.hasMerchantReturnPolicy.length > 0;
257
+ });
258
+ if (!everyOffersHaveReturnPolicy) {
259
+ throw new factory.errors.NotFound('offer.hasMerchantReturnPolicy');
260
+ }
261
+ let returnFees;
262
+ // 返品手数料設定はどうか?
263
+ const somePolicyWithReturnFeesCustomerResponsibility = params.policiesByOffer.some((policy) => {
264
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
265
+ });
266
+ const somePolicyWithRestockingFees = params.policiesByOffer.some((policy) => {
267
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
268
+ });
269
+ const everyPolicyWithFreeReturn = params.policiesByOffer.every((policy) => {
270
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
271
+ });
272
+ if (somePolicyWithReturnFeesCustomerResponsibility) {
273
+ // ひとつでも返金なしがあれば返金なし
274
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
275
+ }
276
+ else if (somePolicyWithRestockingFees) {
277
+ // ひとつでも手数料あり返金があれば手数料あり返金
278
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
279
+ }
280
+ else if (everyPolicyWithFreeReturn) {
281
+ // 全ポリシーが手数料なしであれば手数料なし返金
282
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
283
+ }
284
+ else {
285
+ throw new factory.errors.NotImplemented('returnFees not defined');
286
+ }
287
+ // 決済カード取消ポリシーを確定(2023-05-23~)
288
+ const returnFeesMovieTicket = [];
289
+ params.acceptedOffers.forEach((acceptedOffer) => {
290
+ var _a, _b;
291
+ const unitPriceOffer = params.offers.find((offer) => offer.id === acceptedOffer.id);
292
+ if (unitPriceOffer === undefined) {
293
+ throw new factory.errors.NotFound(`UnitPriceOffer ${acceptedOffer.id}`);
294
+ }
295
+ if (!Array.isArray(unitPriceOffer.hasMerchantReturnPolicy) || unitPriceOffer.hasMerchantReturnPolicy.length === 0) {
296
+ throw new factory.errors.NotFound(`offer.hasMerchantReturnPolicy ${acceptedOffer.id}`);
297
+ }
298
+ const hasMerchantReturnPolicy = unitPriceOffer.hasMerchantReturnPolicy[0];
299
+ const policyByOffer = params.policiesByOffer.find((policy) => policy.id === hasMerchantReturnPolicy.id);
300
+ if (policyByOffer === undefined) {
301
+ throw new factory.errors.NotFound(`MerchantReturnPolicy acceptedOffer:${acceptedOffer.id}`);
302
+ }
303
+ const movieTicketTypeChargeSpecExists = (_a = acceptedOffer.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent.some((component) => {
304
+ return component.typeOf === factory.priceSpecificationType.MovieTicketTypeChargeSpecification;
305
+ });
306
+ if (movieTicketTypeChargeSpecExists === true) {
307
+ (_b = acceptedOffer.priceSpecification) === null || _b === void 0 ? void 0 : _b.priceComponent.forEach((component) => {
308
+ if (component.typeOf === factory.priceSpecificationType.UnitPriceSpecification) {
309
+ if (Array.isArray(component.appliesToMovieTicket)) {
310
+ component.appliesToMovieTicket.forEach((appliesToMovieTicket) => {
311
+ returnFeesMovieTicket.push({
312
+ identifier: String(appliesToMovieTicket.identifier),
313
+ returnFees: policyByOffer.customerRemorseReturnFeesMovieTicket,
314
+ serviceOutput: { typeOf: appliesToMovieTicket.serviceOutput.typeOf }
315
+ });
316
+ });
317
+ }
318
+ }
319
+ });
320
+ }
321
+ });
322
+ return { returnFees, returnFeesMovieTicket };
323
+ }
@@ -0,0 +1,13 @@
1
+ import * as factory from '../../../../factory';
2
+ import { ICustomSellerReturnPolicy, IFixedAcceptedOffer } from './factory';
3
+ /**
4
+ * プロジェクトのカスタム返品ポリシーをリモートから取得する
5
+ */
6
+ declare function getReturnPolicyByProject(params: {
7
+ identifier: string;
8
+ sameAs: string;
9
+ order: Pick<factory.order.IOrder, 'orderDate' | 'orderNumber' | 'price'> & {
10
+ acceptedOffers: IFixedAcceptedOffer[];
11
+ };
12
+ }): Promise<ICustomSellerReturnPolicy>;
13
+ export { getReturnPolicyByProject };
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.getReturnPolicyByProject = getReturnPolicyByProject;
24
+ const http_status_1 = require("http-status");
25
+ const factory = require("../../../../factory");
26
+ function createOrder4returnPolicy(params) {
27
+ return {
28
+ orderDate: params.order.orderDate,
29
+ orderNumber: params.order.orderNumber,
30
+ price: params.order.price,
31
+ acceptedOffers: params.order.acceptedOffers.map((o) => {
32
+ var _a;
33
+ if (o.itemOffered.typeOf === factory.reservationType.EventReservation) {
34
+ const reservation = o.itemOffered;
35
+ const priceComponent = (_a = o.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent;
36
+ return {
37
+ itemOffered: {
38
+ additionalProperty: reservation.additionalProperty,
39
+ reservationFor: {
40
+ doorTime: reservation.reservationFor.doorTime,
41
+ endDate: reservation.reservationFor.endDate,
42
+ startDate: reservation.reservationFor.startDate
43
+ // superEvent: reservation.reservationFor.superEvent
44
+ },
45
+ reservedTicket: {
46
+ ticketedSeat: reservation.reservedTicket.ticketedSeat
47
+ }
48
+ },
49
+ priceSpecification: {
50
+ priceComponent: (Array.isArray(priceComponent))
51
+ ? priceComponent.map((component) => {
52
+ const { accounting, name, priceCurrency, valueAddedTaxIncluded } = component, postingComponent = __rest(component, ["accounting", "name", "priceCurrency", "valueAddedTaxIncluded"]);
53
+ return postingComponent;
54
+ })
55
+ : []
56
+ }
57
+ };
58
+ }
59
+ else {
60
+ return {
61
+ priceSpecification: o.priceSpecification
62
+ };
63
+ }
64
+ })
65
+ };
66
+ }
67
+ const TIMEOUT = 5000;
68
+ /**
69
+ * プロジェクトのカスタム返品ポリシーをリモートから取得する
70
+ */
71
+ function getReturnPolicyByProject(params) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ var _a;
74
+ // implement with fetch(2024-01-20~)
75
+ try {
76
+ const { identifier, sameAs } = params;
77
+ const res = yield fetch(sameAs, {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json'
81
+ },
82
+ body: JSON.stringify({
83
+ order: createOrder4returnPolicy({ order: params.order })
84
+ }),
85
+ // body data type must match "Content-Type" header
86
+ signal: AbortSignal.timeout(TIMEOUT)
87
+ });
88
+ let body;
89
+ try {
90
+ body = (yield res.json());
91
+ }
92
+ catch (error) {
93
+ // no op
94
+ }
95
+ let returnPolicy;
96
+ switch (res.status) {
97
+ case http_status_1.OK:
98
+ case http_status_1.CREATED:
99
+ case http_status_1.ACCEPTED:
100
+ case http_status_1.NO_CONTENT:
101
+ const restockingFeeValue = (_a = body === null || body === void 0 ? void 0 : body.restockingFee) === null || _a === void 0 ? void 0 : _a.value;
102
+ if (typeof restockingFeeValue !== 'number') {
103
+ throw new factory.errors.Internal('invalid return policy');
104
+ }
105
+ else {
106
+ const itemCondition = body === null || body === void 0 ? void 0 : body.itemCondition;
107
+ if (itemCondition !== undefined) {
108
+ if (itemCondition !== factory.offerItemCondition.OfferItemCondition.NewCondition) {
109
+ throw new factory.errors.Argument('', `unknown itemCondition: ${itemCondition}`);
110
+ }
111
+ }
112
+ returnPolicy = Object.assign({ typeOf: 'MerchantReturnPolicy', restockingFee: {
113
+ currency: factory.priceCurrency.JPY,
114
+ typeOf: 'MonetaryAmount',
115
+ value: restockingFeeValue
116
+ }, identifier }, (typeof itemCondition === 'string') ? { itemCondition } : undefined // support itemCondition(2025-05-17~)
117
+ );
118
+ }
119
+ break;
120
+ case http_status_1.NOT_FOUND:
121
+ throw new factory.errors.Argument('', `custom return policy returned statusCode: ${res.status}`);
122
+ // break;
123
+ default:
124
+ throw new factory.errors.Internal(`ProjectReturnPolicy unavailable. statusCode: ${res.status} body: ${body}`);
125
+ }
126
+ return returnPolicy;
127
+ }
128
+ catch (err) {
129
+ throw err;
130
+ }
131
+ });
132
+ }