@chevre/domain 25.2.0-alpha.2 → 25.2.0-alpha.21

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 (53) hide show
  1. package/lib/chevre/repo/action/actionProcess.js +57 -57
  2. package/lib/chevre/repo/action.d.ts +16 -9
  3. package/lib/chevre/repo/action.js +99 -180
  4. package/lib/chevre/repo/mongoose/schemas/action.js +67 -66
  5. package/lib/chevre/repo/mongoose/schemas/order.d.ts +4 -0
  6. package/lib/chevre/repo/mongoose/schemas/order.js +1 -0
  7. package/lib/chevre/repo/mongoose/schemas/task.js +12 -12
  8. package/lib/chevre/repo/order.d.ts +2 -0
  9. package/lib/chevre/repo/orderInTransaction.d.ts +41 -0
  10. package/lib/chevre/repo/orderInTransaction.js +131 -0
  11. package/lib/chevre/repo/transaction/placeOrder.d.ts +1 -44
  12. package/lib/chevre/repo/transaction/placeOrder.js +42 -82
  13. package/lib/chevre/service/assetTransaction/pay/start/factory.js +3 -4
  14. package/lib/chevre/service/offer/event/authorize/factory.d.ts +5 -1
  15. package/lib/chevre/service/offer/event/authorize/factory.js +22 -12
  16. package/lib/chevre/service/offer/event/authorize.d.ts +4 -0
  17. package/lib/chevre/service/offer/event/authorize.js +1 -1
  18. package/lib/chevre/service/offer/eventServiceByCOA/authorize.js +2 -2
  19. package/lib/chevre/service/offer/eventServiceByCOA/changeOffers.js +1 -1
  20. package/lib/chevre/service/order/deleteOrder.d.ts +5 -1
  21. package/lib/chevre/service/order/deleteOrder.js +8 -1
  22. package/lib/chevre/service/payment/any/authorize/fixOrderAsNeeded.js +1 -2
  23. package/lib/chevre/service/payment/any/authorize/fixTransactionNumber.d.ts +3 -2
  24. package/lib/chevre/service/payment/any/authorize/handlePrePublishedPaymentMethodIdOnAuthorizing.d.ts +4 -3
  25. package/lib/chevre/service/payment/any/authorize/handlePrePublishedPaymentMethodIdOnAuthorizing.js +3 -31
  26. package/lib/chevre/service/payment/any/authorize.js +13 -37
  27. package/lib/chevre/service/payment/any/factory.d.ts +6 -6
  28. package/lib/chevre/service/payment/any/factory.js +19 -22
  29. package/lib/chevre/service/payment/any/invalidatePaymentUrl.d.ts +2 -0
  30. package/lib/chevre/service/payment/any/invalidatePaymentUrl.js +4 -66
  31. package/lib/chevre/service/payment/any/publishPaymentUrl.d.ts +2 -0
  32. package/lib/chevre/service/payment/any/publishPaymentUrl.js +2 -16
  33. package/lib/chevre/service/payment/any/voidPayTransaction.d.ts +2 -0
  34. package/lib/chevre/service/payment/any/voidPayTransaction.js +1 -23
  35. package/lib/chevre/service/payment/creditCard/authorize/processAuthorizeCreditCard.d.ts +1 -1
  36. package/lib/chevre/service/payment/creditCard/authorize/processAuthorizeCreditCard.js +5 -9
  37. package/lib/chevre/service/task/publishPaymentUrl.js +2 -2
  38. package/lib/chevre/service/task/voidPayTransaction.js +3 -7
  39. package/lib/chevre/service/transaction/deleteTransaction/deletePayTransactionsByPlaceOrder.d.ts +15 -0
  40. package/lib/chevre/service/transaction/deleteTransaction/deletePayTransactionsByPlaceOrder.js +51 -0
  41. package/lib/chevre/service/transaction/deleteTransaction/deleteReservationsByPlaceOrder.d.ts +23 -0
  42. package/lib/chevre/service/transaction/deleteTransaction/deleteReservationsByPlaceOrder.js +65 -0
  43. package/lib/chevre/service/transaction/deleteTransaction.js +15 -152
  44. package/lib/chevre/service/transaction/placeOrder/confirm/prepareUnitPriceOfferConditions.d.ts +22 -0
  45. package/lib/chevre/service/transaction/placeOrder/confirm/prepareUnitPriceOfferConditions.js +120 -0
  46. package/lib/chevre/service/transaction/placeOrder/confirm/validation/factory.d.ts +5 -1
  47. package/lib/chevre/service/transaction/placeOrder/confirm/validation.d.ts +14 -2
  48. package/lib/chevre/service/transaction/placeOrder/confirm/validation.js +108 -89
  49. package/lib/chevre/service/transaction/placeOrder/confirm.d.ts +7 -0
  50. package/lib/chevre/service/transaction/placeOrder/confirm.js +35 -60
  51. package/lib/chevre/service/transaction/placeOrder/publishConfirmationNumberIfNotExist.d.ts +4 -7
  52. package/lib/chevre/service/transaction/placeOrder/publishConfirmationNumberIfNotExist.js +33 -15
  53. package/package.json +2 -2
@@ -17,23 +17,20 @@ const factory_1 = require("../../../../factory");
17
17
  const validateInvoiceReferencesOrder_1 = require("./validation/validateInvoiceReferencesOrder");
18
18
  const validateMovieTicket_1 = require("./validation/validateMovieTicket");
19
19
  const validatePrice_1 = require("./validation/validatePrice");
20
- const debug = (0, debug_1.default)('chevre-domain:service:transaction');
20
+ const debug = (0, debug_1.default)('chevre-domain:service:transaction:placeOrder:confirm:validation');
21
21
  /**
22
22
  * 取引が確定可能な状態かどうかをチェックする
23
23
  */
24
- function validateTransaction(transaction, acceptPayActions, authorizePaymentActions, authorizeEventServiceOfferActions,
25
- // authorizeProductOfferActions: Pick<IAuthorizeProductOffer, 'id' | 'result'>[],
26
- eventReservationAcceptedOffers, payTransactions, customer) {
27
- // validateProfile(transaction);
24
+ function validateTransaction(transaction, acceptPayActions, authorizePaymentActions, authorizeEventServiceOfferActions, eventReservationAcceptedOffers, payTransactions, customer, options) {
25
+ const { paymentMethodIdByTransaction } = options;
28
26
  validateProfile({ customer });
29
27
  (0, validatePrice_1.validatePrice)(authorizePaymentActions, authorizeEventServiceOfferActions);
30
28
  // 請求のreferencesOrder検証(2025-11-23~)
31
29
  (0, validateInvoiceReferencesOrder_1.validateInvoiceReferencesOrder)(authorizePaymentActions, eventReservationAcceptedOffers);
32
- // 利用可能な通貨単位に対して取引検証
33
- validateMonetaryAmount(authorizePaymentActions, authorizeEventServiceOfferActions);
30
+ // // 利用可能な通貨単位に対して取引検証
31
+ // validateMonetaryAmount(authorizePaymentActions, authorizeEventServiceOfferActions); // discontinue(2026-07-06~)
34
32
  // 利用可能なMovieTicketIF決済方法タイプに対して動的にコーディング
35
33
  const movieTicketPaymentMethodTypes = findMovieTicketPaymentMethodTypesFromTransaction(authorizePaymentActions, eventReservationAcceptedOffers);
36
- debug('processing validateMovieTicket... movieTicketPaymentMethodTypes:', movieTicketPaymentMethodTypes);
37
34
  if (Array.isArray(movieTicketPaymentMethodTypes) && movieTicketPaymentMethodTypes.length > 0) {
38
35
  movieTicketPaymentMethodTypes.forEach((paymentMethodType) => {
39
36
  const authorizeMovieTicketActions = authorizePaymentActions.filter((a) => {
@@ -59,13 +56,12 @@ eventReservationAcceptedOffers, payTransactions, customer) {
59
56
  authorizedMovieTickets.push(...object.paymentMethod.movieTickets);
60
57
  }
61
58
  });
62
- debug(authorizedMovieTickets.length, 'movie tickets authorized', 'transaction:', transaction.id);
63
59
  // validateMovieTicket(paymentMethodType, { id: transaction.id }, authorizePaymentActions, eventReservationAcceptedOffers);
64
60
  (0, validateMovieTicket_1.validateMovieTicket)(paymentMethodType, { id: transaction.id }, authorizedMovieTickets, eventReservationAcceptedOffers);
65
61
  });
66
62
  }
67
63
  // 決済URLが発行されている場合、検証
68
- validatePaymentUrl(transaction, acceptPayActions, authorizePaymentActions);
64
+ validatePaymentUrl({ paymentMethodIdByTransaction, acceptPayActions, authorizePaymentActions });
69
65
  }
70
66
  function findMovieTicketPaymentMethodTypesFromTransaction(authorizePaymentActions, eventReservationAcceptedOffers) {
71
67
  const paymentMethodTypes = [];
@@ -95,18 +91,6 @@ function findMovieTicketPaymentMethodTypesFromTransaction(authorizePaymentAction
95
91
  // ];
96
92
  return [...new Set(paymentMethodTypes)];
97
93
  }
98
- // function validateProfile(transaction: Pick<factory.transaction.placeOrder.ITransaction, 'object'>) {
99
- // // object.customerで検証(2022-05-26~)
100
- // const profile = transaction.object.customer;
101
- // const profileSatisfied = typeof profile?.typeOf === 'string' && profile.typeOf.length > 0
102
- // && typeof profile.email === 'string' && profile.email.length > 0
103
- // && typeof profile.familyName === 'string' && profile.familyName.length > 0
104
- // && typeof profile.givenName === 'string' && profile.givenName.length > 0
105
- // && typeof profile.telephone === 'string' && profile.telephone.length > 0;
106
- // if (!profileSatisfied) {
107
- // throw new factory.errors.Argument('Transaction', 'Customer Profile Required');
108
- // }
109
- // }
110
94
  function validateProfile(params) {
111
95
  const profile = params.customer;
112
96
  const profileSatisfied = typeof profile?.typeOf === 'string' && profile.typeOf.length > 0
@@ -122,9 +106,11 @@ function validateProfile(params) {
122
106
  throw new factory_1.factory.errors.Argument('Transaction', 'customer name required');
123
107
  }
124
108
  }
125
- function validatePaymentUrl(transaction, acceptPayActions, authorizePaymentActions) {
109
+ function validatePaymentUrl(params) {
110
+ const { paymentMethodIdByTransaction, acceptPayActions, authorizePaymentActions } = params;
126
111
  // 決済URLが発行されている場合、検証
127
- const paymentMethodId = transaction.object.paymentMethods?.paymentMethodId;
112
+ const paymentMethodId = paymentMethodIdByTransaction;
113
+ debug('validatePaymentUrl: paymentMethodIdByTransaction:', paymentMethodIdByTransaction);
128
114
  if (typeof paymentMethodId === 'string' && paymentMethodId.length > 0) {
129
115
  // check existing accept action(2025-02-26~)
130
116
  const acceptActionExists = acceptPayActions.some(({ object, result }) => {
@@ -132,6 +118,7 @@ function validatePaymentUrl(transaction, acceptPayActions, authorizePaymentActio
132
118
  && result?.paymentMethodId === paymentMethodId
133
119
  && typeof result?.paymentUrl === 'string';
134
120
  });
121
+ debug('validatePaymentUrl: acceptActionExists:', acceptActionExists);
135
122
  if (!acceptActionExists) {
136
123
  throw new factory_1.factory.errors.NotFound(factory_1.factory.actionType.AcceptAction);
137
124
  }
@@ -143,68 +130,69 @@ function validatePaymentUrl(transaction, acceptPayActions, authorizePaymentActio
143
130
  : undefined;
144
131
  return resultAsInvoice?.paymentMethodId === paymentMethodId;
145
132
  });
133
+ debug('validatePaymentUrl: authorizePaymentAction4paymentUrlExists:', authorizePaymentAction4paymentUrlExists);
146
134
  if (!authorizePaymentAction4paymentUrlExists) {
147
135
  throw new factory_1.factory.errors.Argument('Transaction', 'Payment for published payment URL required');
148
136
  }
149
137
  }
150
138
  }
151
- /**
152
- * JPY以外の通貨について取引を検証する
153
- */
154
- function validateMonetaryAmount(_authorizePaymentActions, authorizeEventServiceOfferActions) {
155
- // PaymentCard決済を廃止したので、JPY以外の通貨に対しての承認はありえない(2026-04-18~)
156
- const authorizeMonetaryAmountActions = [];
157
- // const authorizeMonetaryAmountActions = authorizePaymentActions.filter(({ result }) => {
158
- // const resultAsInvoice = (Array.isArray(result))
159
- // // ? result.find(({ typeOf }) => typeOf === factory.action.authorize.paymentMethod.any.ResultType.Payment)
160
- // ? result[0]
161
- // : undefined;
162
- // // JPY以外の通貨に対して承認可能なのはPaymentServiceType.PaymentCardのみ
163
- // return resultAsInvoice?.issuedThrough.typeOf === factory.service.paymentService.PaymentServiceType.PaymentCard
164
- // && resultAsInvoice.totalPaymentDue?.currency !== factory.priceCurrency.JPY;
165
- // });
166
- const requiredMonetaryAmountByCurrencyType = [];
167
- authorizeEventServiceOfferActions.forEach((a) => {
168
- const amount = a.result?.amount;
169
- if (Array.isArray(amount)) {
170
- amount.forEach((monetaryAmount) => {
171
- if (typeof monetaryAmount.value === 'number') {
172
- requiredMonetaryAmountByCurrencyType.push({ currency: monetaryAmount.currency, value: monetaryAmount.value });
173
- }
174
- });
175
- }
176
- }, 0);
177
- const requiredCurrencyTypes = [...new Set(requiredMonetaryAmountByCurrencyType.map((m) => m.currency))];
178
- const authorizedCurrencyTypes = [...new Set(authorizeMonetaryAmountActions.map(({ result }) => {
179
- const resultAsInvoice = (Array.isArray(result))
180
- // ? result.find(({ typeOf }) => typeOf === factory.action.authorize.paymentMethod.any.ResultType.Payment)
181
- ? result[0]
182
- : undefined;
183
- return resultAsInvoice?.totalPaymentDue?.currency;
184
- }))];
185
- if (requiredCurrencyTypes.length !== authorizedCurrencyTypes.length) {
186
- throw new factory_1.factory.errors.Argument('Transaction', 'MonetaryAmount account types not matched');
187
- }
188
- const requireMonetaryAmountSatisfied = requiredCurrencyTypes.every((currencyType) => {
189
- const requiredMonetaryAmount = requiredMonetaryAmountByCurrencyType
190
- .filter((m) => m.currency === currencyType)
191
- .reduce((a, b) => a + b.value, 0);
192
- let authorizedMonetaryAmount = 0;
193
- authorizeMonetaryAmountActions.forEach(({ result }) => {
194
- const resultAsInvoice = (Array.isArray(result))
195
- // ? result.find(({ typeOf }) => typeOf === factory.action.authorize.paymentMethod.any.ResultType.Payment)
196
- ? result[0]
197
- : undefined;
198
- if (resultAsInvoice?.totalPaymentDue?.currency === currencyType) {
199
- authorizedMonetaryAmount += resultAsInvoice.totalPaymentDue.value;
200
- }
201
- });
202
- return requiredMonetaryAmount === authorizedMonetaryAmount;
203
- });
204
- if (!requireMonetaryAmountSatisfied) {
205
- throw new factory_1.factory.errors.Argument('Transaction', 'Required MonetaryAmount not satisfied');
206
- }
207
- }
139
+ // JPY以外の通貨決済はひとまず廃止(2026-07-06~)
140
+ // /**
141
+ // * JPY以外の通貨について取引を検証する
142
+ // */
143
+ // function validateMonetaryAmount(
144
+ // _authorizePaymentActions: IAuthorizePaymentAction[],
145
+ // authorizeEventServiceOfferActions: Pick<IAuthorizeEventServiceOffer, 'result'>[]
146
+ // ) {
147
+ // // PaymentCard決済を廃止したので、JPY以外の通貨に対しての承認はありえない(2026-04-18~)
148
+ // const authorizeMonetaryAmountActions: IAuthorizePaymentAction[] = [];
149
+ // const requiredMonetaryAmountByCurrencyType: {
150
+ // currency: string;
151
+ // value: number;
152
+ // }[] = [];
153
+ // authorizeEventServiceOfferActions.forEach(
154
+ // (a) => {
155
+ // const amount = a.result?.amount;
156
+ // if (Array.isArray(amount)) {
157
+ // amount.forEach((monetaryAmount) => {
158
+ // if (typeof monetaryAmount.value === 'number') {
159
+ // requiredMonetaryAmountByCurrencyType.push({ currency: monetaryAmount.currency, value: monetaryAmount.value });
160
+ // }
161
+ // });
162
+ // }
163
+ // },
164
+ // 0
165
+ // );
166
+ // const requiredCurrencyTypes = [...new Set(requiredMonetaryAmountByCurrencyType.map((m) => m.currency))];
167
+ // const authorizedCurrencyTypes = [...new Set(authorizeMonetaryAmountActions.map(({ result }) => {
168
+ // const resultAsInvoice = (Array.isArray(result))
169
+ // ? result[0]
170
+ // : undefined;
171
+ // return resultAsInvoice?.totalPaymentDue?.currency as string;
172
+ // }
173
+ // ))];
174
+ // if (requiredCurrencyTypes.length !== authorizedCurrencyTypes.length) {
175
+ // throw new factory.errors.Argument('Transaction', 'MonetaryAmount account types not matched');
176
+ // }
177
+ // const requireMonetaryAmountSatisfied = requiredCurrencyTypes.every((currencyType) => {
178
+ // const requiredMonetaryAmount = requiredMonetaryAmountByCurrencyType
179
+ // .filter((m) => m.currency === currencyType)
180
+ // .reduce((a, b) => a + b.value, 0);
181
+ // let authorizedMonetaryAmount = 0;
182
+ // authorizeMonetaryAmountActions.forEach(({ result }) => {
183
+ // const resultAsInvoice = (Array.isArray(result))
184
+ // ? result[0]
185
+ // : undefined;
186
+ // if (resultAsInvoice?.totalPaymentDue?.currency === currencyType) {
187
+ // authorizedMonetaryAmount += resultAsInvoice.totalPaymentDue.value;
188
+ // }
189
+ // });
190
+ // return requiredMonetaryAmount === authorizedMonetaryAmount;
191
+ // });
192
+ // if (!requireMonetaryAmountSatisfied) {
193
+ // throw new factory.errors.Argument('Transaction', 'Required MonetaryAmount not satisfied');
194
+ // }
195
+ // }
208
196
  /**
209
197
  * 注文オファー数検証
210
198
  */
@@ -257,7 +245,6 @@ function validateAcceptedOffers(params) {
257
245
  });
258
246
  if (ticketIdentifiers.length > 0) {
259
247
  ticketIdentifiers = [...new Set(ticketIdentifiers)];
260
- debug('ticketIdentifiers unique?', ticketIdentifiers.join(' '), 'numAcceptedOffers:', numAcceptedOffers);
261
248
  // チケット識別子が注文内ユニークなので、注文オファー数に一致するはず
262
249
  if (ticketIdentifiers.length !== numAcceptedOffers) {
263
250
  throw new factory_1.factory.errors.Argument('Transaction', 'ticketIdentifiers must be unique');
@@ -274,7 +261,6 @@ function validateAcceptedOffers(params) {
274
261
  });
275
262
  if (ticketNumbers.length > 0) {
276
263
  ticketNumbers = [...new Set(ticketNumbers)];
277
- debug('ticketNumbers unique?', ticketNumbers.join(' '), 'numAcceptedOffers:', numAcceptedOffers);
278
264
  // チケット識別子が注文内ユニークなので、注文オファー数に一致するはず
279
265
  if (ticketNumbers.length !== numAcceptedOffers) {
280
266
  throw new factory_1.factory.errors.Argument('Transaction', 'ticketNumbers must be unique');
@@ -313,6 +299,42 @@ function validatePaymentMethods(params, options) {
313
299
  * 興行オファー適用条件確認
314
300
  */
315
301
  function validateEventOffers(params) {
302
+ const { unitPriceOfferConditions } = params;
303
+ /**
304
+ * 以下処理で検証に使用するアクション結果リスト
305
+ */
306
+ let validatingAuthorizeOfferActions;
307
+ // 承認アクションと比較する
308
+ if (Array.isArray(unitPriceOfferConditions)) {
309
+ const everyActionsMatched = unitPriceOfferConditions.length === params.authorizeOfferActions.length
310
+ && params.authorizeOfferActions.every((authorizeEventServiceOfferAction) => {
311
+ const conditionExpected = unitPriceOfferConditions.find(({ id }) => id === authorizeEventServiceOfferAction.id);
312
+ let resultMatched;
313
+ // 承認アクションのresultが最適化済の場合,price以外を比較しても意味がないので比較しない(2026-07-10~)
314
+ if (authorizeEventServiceOfferAction.result?.onlyPrice === true) {
315
+ resultMatched = typeof conditionExpected?.result?.price === 'number'
316
+ && conditionExpected?.result.price === authorizeEventServiceOfferAction.result.price;
317
+ }
318
+ else {
319
+ resultMatched = (0, util_1.isDeepStrictEqual)(conditionExpected?.result, authorizeEventServiceOfferAction.result);
320
+ }
321
+ debug('validateEventOffers: unitPriceOfferConditions: resultMatched?', resultMatched, params.project.id, authorizeEventServiceOfferAction.id);
322
+ if (!resultMatched) {
323
+ console.error('validateEventOffers: unitPriceOfferConditions not matched!', params.project.id, authorizeEventServiceOfferAction.id, conditionExpected?.result, authorizeEventServiceOfferAction.result);
324
+ }
325
+ return resultMatched;
326
+ });
327
+ // 全アクションについて結果が一致していればunitPriceOfferConditionsを採用する(2026-07-07~)
328
+ if (everyActionsMatched) {
329
+ validatingAuthorizeOfferActions = [...unitPriceOfferConditions];
330
+ }
331
+ else {
332
+ validatingAuthorizeOfferActions = [...params.authorizeOfferActions];
333
+ }
334
+ }
335
+ else {
336
+ validatingAuthorizeOfferActions = [...params.authorizeOfferActions];
337
+ }
316
338
  const { paymentMethods } = params;
317
339
  const firstCreditCardPaymentMethodIdentifier = paymentMethods.find((referenceInvoice) => {
318
340
  return referenceInvoice.issuedThrough.typeOf === factory_1.factory.service.paymentService.PaymentServiceType.CreditCard
@@ -322,7 +344,7 @@ function validateEventOffers(params) {
322
344
  return referenceInvoice.issuedThrough.typeOf === factory_1.factory.service.paymentService.PaymentServiceType.CreditCard
323
345
  || referenceInvoice.issuedThrough.typeOf === factory_1.factory.service.paymentService.PaymentServiceType.FaceToFace;
324
346
  }).length;
325
- params.authorizeEventServiceOfferActions.forEach((a) => {
347
+ validatingAuthorizeOfferActions.forEach((a) => {
326
348
  // support result.offers(2024-06-18~)
327
349
  const acceptedOffersInResult = a.result?.offers;
328
350
  if (Array.isArray(acceptedOffersInResult) && acceptedOffersInResult.length > 0) {
@@ -348,20 +370,18 @@ function validateEventOffers(params) {
348
370
  // }
349
371
  // 適用数量検証(全興行オファー承認アクションについて)(2023-11-15~)
350
372
  // 適用数量要件を満たしていなければエラー
351
- const numAcceptedOffersByOfferId = params.authorizeEventServiceOfferActions.reduce((previousNumOffer, { result }) => {
373
+ const numAcceptedOffersByOfferId = validatingAuthorizeOfferActions.reduce((previousNumOffer, { result }) => {
352
374
  const numOfferOnCurrentAction = result?.offers?.find(({ id }) => id === offerId)?.includesObject.amountOfThisGood;
353
375
  return previousNumOffer + ((typeof numOfferOnCurrentAction === 'number') ? numOfferOnCurrentAction : 0);
354
376
  }, 0);
355
377
  const eligibleQuantityMaxValue = unitPriceSpec?.eligibleQuantity?.maxValue;
356
378
  if (typeof eligibleQuantityMaxValue === 'number') {
357
- debug('validateEventOffers: numAcceptedOffersByOfferId > eligibleQuantityMaxValue?', numAcceptedOffersByOfferId, eligibleQuantityMaxValue);
358
379
  if (numAcceptedOffersByOfferId > eligibleQuantityMaxValue) {
359
380
  throw new factory_1.factory.errors.Argument('Transaction', `Number of offer:${offerId} must be less than or equal to ${eligibleQuantityMaxValue}`);
360
381
  }
361
382
  }
362
383
  const eligibleQuantityMinValue = unitPriceSpec?.eligibleQuantity?.minValue;
363
384
  if (typeof eligibleQuantityMinValue === 'number') {
364
- debug('validateEventOffers: numAcceptedOffersByOfferId < eligibleQuantityMinValue?', numAcceptedOffersByOfferId, eligibleQuantityMinValue);
365
385
  if (numAcceptedOffersByOfferId < eligibleQuantityMinValue) {
366
386
  throw new factory_1.factory.errors.Argument('Transaction', `Number of offer:${offerId} must be more than or equal to ${eligibleQuantityMinValue}`);
367
387
  }
@@ -372,7 +392,6 @@ function validateEventOffers(params) {
372
392
  const satisfyAcceptedPaymentMethod = numCreditCardOrFaceToFacePaymentMethod === 1
373
393
  && typeof firstCreditCardPaymentMethodIdentifier === 'string'
374
394
  && acceptedPaymentMethodTypes.includes(firstCreditCardPaymentMethodIdentifier);
375
- debug('validateEventOffers: satisfyAcceptedPaymentMethod?', JSON.stringify(acceptedPaymentMethodTypes));
376
395
  if (!satisfyAcceptedPaymentMethod) {
377
396
  throw new factory_1.factory.errors.Argument('Transaction', `acceptedPaymentMethod requirement not satisfied`);
378
397
  }
@@ -381,7 +400,7 @@ function validateEventOffers(params) {
381
400
  }
382
401
  });
383
402
  // check programMembershipUsed(2024-08-15~)
384
- const programMembershipRequired = params.authorizeEventServiceOfferActions.reduce((a, b) => {
403
+ const programMembershipRequired = validatingAuthorizeOfferActions.reduce((a, b) => {
385
404
  const programMembershipUsedfromResult = b.result?.itemOffered?.serviceOutput.programMembershipUsed;
386
405
  if (Array.isArray(programMembershipUsedfromResult)) {
387
406
  a.push(...programMembershipUsedfromResult);
@@ -5,6 +5,7 @@ import type { AssetTransactionRepo } from '../../../repo/assetTransaction';
5
5
  import type { AuthorizationRepo } from '../../../repo/authorization';
6
6
  import type { ConfirmationNumberRepo } from '../../../repo/confirmationNumber';
7
7
  import type { MessageRepo } from '../../../repo/message';
8
+ import type { OfferRepo } from '../../../repo/offer/unitPriceInCatalog';
8
9
  import type { OrderInTransactionRepo } from '../../../repo/orderInTransaction';
9
10
  import type { ProjectRepo } from '../../../repo/project';
10
11
  import type { SettingRepo } from '../../../repo/setting';
@@ -19,6 +20,7 @@ interface IConfirmOperationRepos {
19
20
  assetTransaction: AssetTransactionRepo;
20
21
  authorization: AuthorizationRepo;
21
22
  message: MessageRepo;
23
+ offer: OfferRepo;
22
24
  project: ProjectRepo;
23
25
  placeOrder: PlaceOrderRepo;
24
26
  orderInTransaction: OrderInTransactionRepo;
@@ -39,6 +41,11 @@ interface IConfirmOptions {
39
41
  * 注文における最大CreditCardIF決済方法数
40
42
  */
41
43
  maxNumCreditCardPaymentMethod: number;
44
+ /**
45
+ * 2026-07-06~
46
+ * 実験的に
47
+ */
48
+ usePrepareUnitPriceOfferConditions?: boolean;
42
49
  }
43
50
  type IConfirmParams = PlaceOrderFactory.IConfirmParams;
44
51
  interface IConfirmResult {
@@ -12,6 +12,7 @@ const factory_2 = require("../../order/placeOrder/factory");
12
12
  const orderedItem_1 = require("../../order/placeOrder/factory/orderedItem");
13
13
  const result_1 = require("./confirm/factory/result");
14
14
  const potentialActions_1 = require("./confirm/potentialActions");
15
+ const prepareUnitPriceOfferConditions_1 = require("./confirm/prepareUnitPriceOfferConditions");
15
16
  const publishCode_1 = require("./confirm/publishCode");
16
17
  const validation_1 = require("./confirm/validation");
17
18
  const publishConfirmationNumberIfNotExist_1 = require("./publishConfirmationNumberIfNotExist");
@@ -57,9 +58,9 @@ function processTransactionNotInProgress(params) {
57
58
  function confirm(params, options) {
58
59
  return async (repos) => {
59
60
  // 確認番号を事前発行
60
- await (0, publishConfirmationNumberIfNotExist_1.publishConfirmationNumberIfNotExist)({
61
+ const confirmationNumber = await (0, publishConfirmationNumberIfNotExist_1.publishConfirmationNumberIfNotExist)({
61
62
  id: params.id,
62
- status: { $in: [factory_1.factory.transactionStatusType.Confirmed, factory_1.factory.transactionStatusType.InProgress] },
63
+ // status: { $in: [factory.transactionStatusType.Confirmed, factory.transactionStatusType.InProgress] },
63
64
  object: { orderDate: params.result.order.orderDate }
64
65
  })(repos);
65
66
  const transaction = await repos.placeOrder.findPlaceOrderById({ typeOf: factory_1.factory.transactionType.PlaceOrder, id: params.id }, ['typeOf', 'project', 'status', 'agent', 'seller', 'object', 'result']);
@@ -81,10 +82,12 @@ function confirm(params, options) {
81
82
  // if (typeof orderNumber !== 'string' || orderNumber === '') {
82
83
  // throw new factory.errors.Argument('transactionId', 'orderNumber not issued');
83
84
  // }
85
+ // 注文に決済方法IDが発行済か確認(2026-07-12)
86
+ const paymentMethodIdByTransaction = await repos.orderInTransaction.findPaymentMethodId({ id: params.id });
84
87
  // 取引に対する全ての承認アクションをマージ
85
88
  const completedAuthorizeActions = await searchAuthorizeActions(params)(repos);
86
89
  let acceptPayActions = [];
87
- if (typeof transaction.object.paymentMethods?.paymentMethodId === 'string') {
90
+ if (typeof paymentMethodIdByTransaction === 'string') {
88
91
  acceptPayActions = await searchAcceptPayActions(params)(repos);
89
92
  }
90
93
  // 必要あらば注文コード発行(2024-02-05~)
@@ -114,6 +117,16 @@ function confirm(params, options) {
114
117
  project: { id: transaction.project.id }
115
118
  }))
116
119
  .filter(({ serialNumber }) => typeof serialNumber === 'string' && serialNumbers.includes(serialNumber));
120
+ // 単価オファーの全適用条件を検証するために、単価オファーを参照(2026-07-06~)
121
+ let unitPriceOfferConditions;
122
+ const { usePrepareUnitPriceOfferConditions } = options;
123
+ if (usePrepareUnitPriceOfferConditions === true) {
124
+ unitPriceOfferConditions = await (0, prepareUnitPriceOfferConditions_1.prepareUnitPriceOfferConditions)({
125
+ project: { id: transaction.project.id, },
126
+ acceptedOffers,
127
+ authorizeEventServiceOfferActions
128
+ })({ offer: repos.offer });
129
+ }
117
130
  // authorizePaymentActionsからpayTransactionsを参照(2024-06-20~)
118
131
  let payTransactions = [];
119
132
  // 決済承認アクションのinstrument依存をobject依存へ変更(2025-12-14~)
@@ -131,25 +144,16 @@ function confirm(params, options) {
131
144
  const seller = (0, factory_2.createSeller)({ transaction });
132
145
  const { paymentMethods, placingOrder, result, eventId, reservationIds } = createResult({
133
146
  ...params,
134
- orderNumber, transaction,
147
+ orderNumber,
148
+ confirmationNumber,
149
+ transaction,
135
150
  acceptPayActions,
136
151
  authorizePaymentActions, authorizeEventServiceOfferActions,
137
- // authorizeProductOfferActions,
138
152
  acceptedOffers, payTransactions, customer,
139
- ...(typeof code === 'string') ? { code } : undefined
153
+ ...(typeof code === 'string') ? { code } : undefined,
154
+ ...((Array.isArray(unitPriceOfferConditions)) && { unitPriceOfferConditions }),
155
+ paymentMethodIdByTransaction
140
156
  }, options);
141
- // discontinue emailMessageRepo
142
- // // デフォルトEメールメッセージを検索
143
- // let emailMessageOnOrderSent: factory.creativeWork.message.email.ICreativeWork | undefined;
144
- // if (repos.emailMessage !== undefined) {
145
- // const searchEmailMessagesResult = await repos.emailMessage.search({
146
- // limit: 1,
147
- // page: 1,
148
- // project: { id: { $eq: transaction.project.id } },
149
- // about: { identifier: { $eq: factory.creativeWork.message.email.AboutIdentifier.OnOrderSent } }
150
- // });
151
- // emailMessageOnOrderSent = searchEmailMessagesResult.shift();
152
- // }
153
157
  // ポストアクションを作成
154
158
  const setting = await repos.setting.findOne({ project: { id: { $eq: '*' } } }, ['defaultSenderEmail']);
155
159
  if (typeof setting?.defaultSenderEmail !== 'string') {
@@ -179,7 +183,8 @@ function confirm(params, options) {
179
183
  id: transaction.id,
180
184
  object: {
181
185
  orderDate: params.result.order.orderDate,
182
- orderNumber
186
+ orderNumber,
187
+ confirmationNumber: placingOrder.confirmationNumber
183
188
  },
184
189
  result: result,
185
190
  potentialActions: potentialActions
@@ -319,17 +324,20 @@ function createResult(params, options) {
319
324
  }
320
325
  });
321
326
  // 取引の確定条件が全て整っているかどうか確認
322
- (0, validation_1.validateTransaction)(transaction, params.acceptPayActions, params.authorizePaymentActions, params.authorizeEventServiceOfferActions,
323
- // params.authorizeProductOfferActions,
324
- eventReservationAcceptedOffers, params.payTransactions, params.customer);
327
+ const { paymentMethodIdByTransaction } = params;
328
+ (0, validation_1.validateTransaction)({ id: transaction.id }, params.acceptPayActions, params.authorizePaymentActions, params.authorizeEventServiceOfferActions, eventReservationAcceptedOffers, params.payTransactions, params.customer, {
329
+ ...((typeof paymentMethodIdByTransaction === 'string') && { paymentMethodIdByTransaction })
330
+ });
325
331
  const { paymentMethods, price } = (0, factory_2.createPaymentMethods)({ authorizePaymentActions: params.authorizePaymentActions });
326
332
  const orderedItem = (0, orderedItem_1.acceptedOffers2orderedItem)({
327
333
  eventReservationAcceptedOffers
328
334
  });
329
335
  (0, validation_1.validateEventOffers)({
336
+ project: { id: transaction.project.id },
330
337
  order: { price },
331
338
  paymentMethods,
332
- authorizeEventServiceOfferActions: params.authorizeEventServiceOfferActions
339
+ authorizeOfferActions: params.authorizeEventServiceOfferActions,
340
+ ...((Array.isArray(params.unitPriceOfferConditions)) && { unitPriceOfferConditions: params.unitPriceOfferConditions })
333
341
  });
334
342
  // 注文オファー検証
335
343
  (0, validation_1.validateAcceptedOffers)({
@@ -342,8 +350,10 @@ function createResult(params, options) {
342
350
  result: params.result
343
351
  });
344
352
  (0, validation_1.validatePaymentMethods)({ order: { paymentMethods } }, options);
345
- // 確認番号を発行
346
- const { confirmationNumber } = createConfirmationNumber({ transaction });
353
+ // 取引のobjectへの依存を排除する(2026-07-08~)
354
+ const { confirmationNumber } = params;
355
+ // // 確認番号を発行
356
+ // const { confirmationNumber } = createConfirmationNumber({ transaction });
347
357
  // 注文作成
348
358
  const orderAsResult = (0, result_1.createOrderAsResult)({
349
359
  orderNumber: params.orderNumber,
@@ -390,21 +400,6 @@ function createResult(params, options) {
390
400
  }
391
401
  function searchAcceptPayActions(params) {
392
402
  return async (repos) => {
393
- // let acceptPayActions = <IAcceptPayAction[]>await repos.action.search(
394
- // {
395
- // project: { id: { $eq: params.project.id } },
396
- // typeOf: { $eq: factory.actionType.AcceptAction },
397
- // actionStatus: { $in: [factory.actionStatusType.CompletedActionStatus] },
398
- // purpose: {
399
- // id: { $in: [params.id] },
400
- // typeOf: { $in: [factory.transactionType.PlaceOrder] }
401
- // },
402
- // object: {
403
- // typeOf: { $eq: factory.assetTransactionType.Pay }
404
- // }
405
- // },
406
- // ['object', 'endDate', 'result']
407
- // );
408
403
  let acceptPayActions = await repos.acceptPayAction.findAcceptActionsByPurpose({
409
404
  project: { id: params.project.id },
410
405
  actionStatus: factory_1.factory.actionStatusType.CompletedActionStatus,
@@ -423,15 +418,6 @@ function searchAcceptPayActions(params) {
423
418
  function searchAuthorizeActions(params) {
424
419
  return async (repos) => {
425
420
  // 取引に対する全ての承認アクションをマージ
426
- // let authorizeActions = <IAuthorizeOfferOrPaymentAction[]>await repos.action.searchByPurpose({
427
- // typeOf: factory.actionType.AuthorizeAction,
428
- // purpose: {
429
- // typeOf: factory.transactionType.PlaceOrder,
430
- // id: params.id
431
- // },
432
- // // Completedに絞る(2023-05-16~)
433
- // actionStatus: { $eq: factory.actionStatusType.CompletedActionStatus }
434
- // });
435
421
  let authorizeActions = [
436
422
  ...await repos.authorizePaymentMethodAction.findAuthorizePaymentMethodActionsByPurpose({
437
423
  purpose: {
@@ -458,14 +444,3 @@ function searchAuthorizeActions(params) {
458
444
  return authorizeActions;
459
445
  };
460
446
  }
461
- function createConfirmationNumber(params) {
462
- const confirmationNumber = params.transaction.object.confirmationNumber;
463
- // 取引に確認番号が保管されていなければ、確認番号を発行
464
- if (typeof confirmationNumber !== 'string') {
465
- // 事前に発行済なはずなので、ありえないフロー
466
- throw new factory_1.factory.errors.Internal('object.confirmationNumber undefined');
467
- }
468
- return {
469
- confirmationNumber,
470
- };
471
- }
@@ -1,22 +1,19 @@
1
1
  import type { ConfirmationNumberRepo } from '../../../repo/confirmationNumber';
2
- import type { PlaceOrderRepo } from '../../../repo/transaction/placeOrder';
3
- import { factory } from '../../../factory';
2
+ import type { OrderInTransactionRepo } from '../../../repo/orderInTransaction';
4
3
  /**
5
- * 未発行であれば、注文の確認番号を発行して取引に保管する
4
+ * 未発行であれば、確認番号を発行して注文ドキュメントに保管する
5
+ * reimplement using OrderInTransactionRepo(2026-07-09~)
6
6
  */
7
7
  declare function publishConfirmationNumberIfNotExist(params: {
8
8
  /**
9
9
  * 取引ID
10
10
  */
11
11
  id: string;
12
- status: {
13
- $in: factory.transactionStatusType[];
14
- };
15
12
  object: {
16
13
  orderDate: Date;
17
14
  };
18
15
  }): (repos: {
19
- placeOrder: PlaceOrderRepo;
20
16
  confirmationNumber: ConfirmationNumberRepo;
17
+ orderInTransaction: OrderInTransactionRepo;
21
18
  }) => Promise<string>;
22
19
  export { publishConfirmationNumberIfNotExist };
@@ -1,36 +1,54 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.publishConfirmationNumberIfNotExist = publishConfirmationNumberIfNotExist;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ // import type { PlaceOrderRepo } from '../../../repo/transaction/placeOrder';
4
9
  const factory_1 = require("../../../factory");
10
+ const debug = (0, debug_1.default)('chevre-domain:service:transaction:placeOrder:publishConfirmationNumberIfNotExist');
5
11
  /**
6
- * 未発行であれば、注文の確認番号を発行して取引に保管する
12
+ * 未発行であれば、確認番号を発行して注文ドキュメントに保管する
13
+ * reimplement using OrderInTransactionRepo(2026-07-09~)
7
14
  */
8
15
  function publishConfirmationNumberIfNotExist(params) {
9
16
  return async (repos) => {
10
- let confirmationNumber = await repos.placeOrder.findInProgressConfirmationNumberById({
11
- id: params.id,
12
- status: { $in: params.status.$in }
13
- });
17
+ // let confirmationNumber = await repos.placeOrder.findInProgressConfirmationNumberById({
18
+ // id: params.id,
19
+ // status: { $in: params.status.$in }
20
+ // });
21
+ let confirmationNumber = await repos.orderInTransaction.findConfirmationNumberByIdentifier({ identifier: params.id });
22
+ debug('already exists?', confirmationNumber);
14
23
  // すでに発行済であれば何もしない
15
24
  if (typeof confirmationNumber === 'string') {
16
25
  return confirmationNumber;
17
26
  }
18
27
  // 確認番号を発行
19
28
  confirmationNumber = await repos.confirmationNumber.publish({ orderDate: params.object.orderDate });
20
- // 取引に存在しなければ保管
21
- await repos.placeOrder.saveConfirmationNumberIfNotExist({
22
- id: params.id,
23
- status: { $in: params.status.$in },
29
+ debug('saving new confirmationNumber...', confirmationNumber);
30
+ // // 取引に存在しなければ保管
31
+ // await repos.placeOrder.saveConfirmationNumberIfNotExist({
32
+ // id: params.id,
33
+ // status: { $in: params.status.$in },
34
+ // confirmationNumber
35
+ // });
36
+ // 注文ドキュメントにも保管(2026-07-08~)
37
+ const saveResult = await repos.orderInTransaction.saveConfirmationNumberIfNotExist({
38
+ identifier: params.id,
24
39
  confirmationNumber
25
- });
40
+ }, { onlyPlaceOrder: true });
41
+ debug('saveConfirmationNumberIfNotExist result:', JSON.stringify(saveResult));
26
42
  // 確認番号を取引から再取得
27
- confirmationNumber = await repos.placeOrder.findInProgressConfirmationNumberById({
28
- id: params.id,
29
- status: { $in: params.status.$in }
30
- });
43
+ // confirmationNumber = await repos.placeOrder.findInProgressConfirmationNumberById({
44
+ // id: params.id,
45
+ // status: { $in: params.status.$in }
46
+ // });
47
+ confirmationNumber = await repos.orderInTransaction.findConfirmationNumberByIdentifier({ identifier: params.id });
48
+ debug('confirmationNumber should exist:', confirmationNumber);
31
49
  // 万が一処理が想定通りでない場合confirmationNumberが存在しない
32
50
  if (typeof confirmationNumber !== 'string') {
33
- throw new factory_1.factory.errors.Internal('transaction.object.confirmationNumber not found');
51
+ throw new factory_1.factory.errors.Internal('orderInTransaction.confirmationNumber not found');
34
52
  }
35
53
  return confirmationNumber;
36
54
  };