@chevre/domain 21.37.0-alpha.8 → 21.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/src/chevre/processOrder.ts +87 -0
- package/example/src/chevre/transaction/processPlaceOrder.ts +17 -143
- package/lib/chevre/factory/reservedAgentIdentifireNames.js +2 -1
- package/lib/chevre/factory/transaction.d.ts +1 -4
- package/lib/chevre/repo/passport.d.ts +39 -0
- package/lib/chevre/repo/passport.js +134 -0
- package/lib/chevre/repo/task.d.ts +9 -0
- package/lib/chevre/repo/task.js +23 -2
- package/lib/chevre/repository.d.ts +5 -0
- package/lib/chevre/repository.js +15 -2
- package/lib/chevre/service/accountTransaction/deposit.js +0 -1
- package/lib/chevre/service/accountTransaction/transfer.js +0 -1
- package/lib/chevre/service/accountTransaction/withdraw.js +0 -1
- package/lib/chevre/service/assetTransaction/reserve/cancel.d.ts +22 -0
- package/lib/chevre/service/assetTransaction/reserve/cancel.js +41 -0
- package/lib/chevre/service/assetTransaction/reserve/confirm/factory.d.ts +8 -0
- package/lib/chevre/service/assetTransaction/reserve/confirm/factory.js +94 -0
- package/lib/chevre/service/assetTransaction/reserve/confirm.d.ts +19 -0
- package/lib/chevre/service/assetTransaction/reserve/confirm.js +93 -0
- package/lib/chevre/service/assetTransaction/reserve/exportTasksById.d.ts +15 -0
- package/lib/chevre/service/assetTransaction/reserve/exportTasksById.js +99 -0
- package/lib/chevre/service/assetTransaction/reserve/start/createSubReservations.d.ts +28 -0
- package/lib/chevre/service/assetTransaction/reserve/start/createSubReservations.js +405 -0
- package/lib/chevre/service/assetTransaction/reserve/start/factory/createPointAward.d.ts +15 -0
- package/lib/chevre/service/assetTransaction/reserve/start/factory/createPointAward.js +40 -0
- package/lib/chevre/service/assetTransaction/reserve/start/factory/createReservation.d.ts +54 -0
- package/lib/chevre/service/assetTransaction/reserve/{factory.js → start/factory/createReservation.js} +3 -222
- package/lib/chevre/service/assetTransaction/reserve/start/factory/createStartParams.d.ts +22 -0
- package/lib/chevre/service/assetTransaction/reserve/start/factory/createStartParams.js +90 -0
- package/lib/chevre/service/assetTransaction/reserve/{factory → start/factory}/price.d.ts +1 -1
- package/lib/chevre/service/assetTransaction/reserve/{factory → start/factory}/price.js +1 -1
- package/lib/chevre/service/assetTransaction/reserve/start.d.ts +74 -0
- package/lib/chevre/service/assetTransaction/reserve/start.js +570 -0
- package/lib/chevre/service/assetTransaction/reserve.d.ts +6 -128
- package/lib/chevre/service/assetTransaction/reserve.js +9 -1047
- package/lib/chevre/service/offer/event/{defaultOffer.d.ts → authorize/defaultOffer.d.ts} +1 -1
- package/lib/chevre/service/offer/event/{defaultOffer.js → authorize/defaultOffer.js} +1 -1
- package/lib/chevre/service/offer/event/{factory.d.ts → authorize/factory.d.ts} +13 -20
- package/lib/chevre/service/offer/event/{factory.js → authorize/factory.js} +72 -146
- package/lib/chevre/service/offer/event/{processStartReserve4chevre.d.ts → authorize/processStartReserve4chevre.d.ts} +19 -19
- package/lib/chevre/service/offer/event/{processStartReserve4chevre.js → authorize/processStartReserve4chevre.js} +8 -13
- package/lib/chevre/service/offer/event/authorize.d.ts +1 -1
- package/lib/chevre/service/offer/event/authorize.js +104 -128
- package/lib/chevre/service/offer/event/importFromCOA/factory.d.ts +9 -0
- package/lib/chevre/service/offer/event/importFromCOA/factory.js +67 -0
- package/lib/chevre/service/offer/event/importFromCOA.js +1 -1
- package/lib/chevre/service/offer/eventServiceByCOA/authorize.js +0 -3
- package/lib/chevre/service/offer/eventServiceByCOA/factory.d.ts +3 -3
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/factory.d.ts +4 -4
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/processOrder.d.ts +16 -0
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/processOrder.js +168 -0
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing.d.ts +4 -5
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing.js +4 -135
- package/lib/chevre/service/order/onOrderStatusChanged.d.ts +2 -2
- package/lib/chevre/service/order/onOrderStatusChanged.js +2 -1
- package/lib/chevre/service/order.d.ts +2 -2
- package/lib/chevre/service/order.js +2 -1
- package/lib/chevre/service/transaction/moneyTransfer.d.ts +3 -2
- package/lib/chevre/service/transaction/moneyTransfer.js +1 -2
- package/lib/chevre/service/transaction/placeOrderInProgress/start/factory.d.ts +10 -0
- package/lib/chevre/service/transaction/placeOrderInProgress/start/factory.js +36 -0
- package/lib/chevre/service/transaction/placeOrderInProgress/start.d.ts +6 -1
- package/lib/chevre/service/transaction/placeOrderInProgress/start.js +26 -12
- package/lib/chevre/service/validation/validateOrder.js +1 -1
- package/lib/chevre/settings.d.ts +1 -0
- package/lib/chevre/settings.js +5 -1
- package/package.json +3 -3
- package/example/src/chevre/migrateAuthorizeEventServiceOfferResult.ts +0 -163
- package/lib/chevre/service/assetTransaction/reserve/factory.d.ts +0 -96
- package/lib/chevre/service/transaction/placeOrderInProgress/factory.d.ts +0 -2
- package/lib/chevre/service/transaction/placeOrderInProgress/factory.js +0 -29
- package/lib/chevre/service/transaction/validation.d.ts +0 -14
- package/lib/chevre/service/transaction/validation.js +0 -101
|
@@ -0,0 +1,405 @@
|
|
|
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.createSubReservations = void 0;
|
|
13
|
+
const createDebug = require("debug");
|
|
14
|
+
const moment = require("moment");
|
|
15
|
+
const factory = require("../../../../factory");
|
|
16
|
+
const pecorinoapi = require("../../../../pecorinoapi");
|
|
17
|
+
const OfferService = require("../../../offer");
|
|
18
|
+
const createReservation_1 = require("./factory/createReservation");
|
|
19
|
+
const debug = createDebug('chevre-domain:service:assetTransaction');
|
|
20
|
+
function createSubReservations(params) {
|
|
21
|
+
// tslint:disable-next-line:max-func-body-length
|
|
22
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
24
|
+
// 予約番号
|
|
25
|
+
// const reservationNumber = params.transaction.object.reservationNumber;
|
|
26
|
+
const reservationNumber = params.reservationNumber;
|
|
27
|
+
if (typeof reservationNumber !== 'string') {
|
|
28
|
+
throw new factory.errors.Internal('Reservation number undefined');
|
|
29
|
+
}
|
|
30
|
+
// 指定席のみかどうか
|
|
31
|
+
const eventOffers = params.event.offers;
|
|
32
|
+
const reservedSeatsOnly = ((_b = (_a = eventOffers === null || eventOffers === void 0 ? void 0 : eventOffers.itemOffered.serviceOutput) === null || _a === void 0 ? void 0 : _a.reservedTicket) === null || _b === void 0 ? void 0 : _b.ticketedSeat) !== undefined;
|
|
33
|
+
// オファーIDごとにオファー適用条件を確認(興行オファー承認アクションから処理を移行)(2024-07-03~)
|
|
34
|
+
validateQuantityRequirement({ acceptedOffers: params.acceptedOffers, ticketOffers: params.ticketOffers, reservationNumber });
|
|
35
|
+
const reservations = [];
|
|
36
|
+
let reservationIndex = -1;
|
|
37
|
+
for (const acceptedOffer of params.acceptedOffers) {
|
|
38
|
+
reservationIndex += 1;
|
|
39
|
+
const reservationId = `${reservationNumber}-${reservationIndex}`;
|
|
40
|
+
const ticketOffer = params.ticketOffers.find((t) => t.id === acceptedOffer.id);
|
|
41
|
+
if (ticketOffer === undefined) {
|
|
42
|
+
throw new factory.errors.NotFound('Ticket Offer');
|
|
43
|
+
}
|
|
44
|
+
const ticketType = params.availableOffers.find((o) => o.id === acceptedOffer.id);
|
|
45
|
+
if (ticketType === undefined) {
|
|
46
|
+
throw new factory.errors.NotFound(ticketOffer.typeOf);
|
|
47
|
+
}
|
|
48
|
+
// 事前予約要件検証(2023-08-10~)
|
|
49
|
+
validateAdvanceBookingRequirement({
|
|
50
|
+
unitPriceOffer: ticketType,
|
|
51
|
+
now: params.now,
|
|
52
|
+
reservationFor: params.event
|
|
53
|
+
});
|
|
54
|
+
const programMembershipUsed = yield validateProgramMembershipUsed({
|
|
55
|
+
acceptedOffer,
|
|
56
|
+
project: { id: params.event.project.id }
|
|
57
|
+
})(repos);
|
|
58
|
+
// チケット作成
|
|
59
|
+
const reservedTicket = (0, createReservation_1.createReservedTicket)({
|
|
60
|
+
id: reservationId,
|
|
61
|
+
acceptedOffer: acceptedOffer,
|
|
62
|
+
availableOffer: ticketType,
|
|
63
|
+
dateIssued: params.now,
|
|
64
|
+
reservationFor: { id: params.event.id },
|
|
65
|
+
reservedSeatsOnly,
|
|
66
|
+
availableSeatOffers: params.availableSeatOffers,
|
|
67
|
+
ticketOffer: ticketOffer
|
|
68
|
+
});
|
|
69
|
+
const additionalTicketText = (0, createReservation_1.createAdditionalTicketText)({ acceptedOffer, reservedTicket });
|
|
70
|
+
const additionalProperty = (0, createReservation_1.createAdditionalProperty)({ acceptedOffer });
|
|
71
|
+
// 座席指定であれば、座席タイプチャージを検索する
|
|
72
|
+
const seatPriceComponent = [];
|
|
73
|
+
// 区分加算料金を適用しないオプションを追加(2023-01-26~)
|
|
74
|
+
const ignoreCategoryCodeChargeSpec = ((_c = ticketType.settings) === null || _c === void 0 ? void 0 : _c.ignoreCategoryCodeChargeSpec) === true;
|
|
75
|
+
if (!ignoreCategoryCodeChargeSpec) {
|
|
76
|
+
const seatSection = (_d = reservedTicket.ticketedSeat) === null || _d === void 0 ? void 0 : _d.seatSection;
|
|
77
|
+
const seatNumber = (_e = reservedTicket.ticketedSeat) === null || _e === void 0 ? void 0 : _e.seatNumber;
|
|
78
|
+
if (typeof seatSection === 'string' && typeof seatNumber === 'string') {
|
|
79
|
+
const offersOnSeat = (_f = params.availableSeatOffers.find((o) => {
|
|
80
|
+
var _a;
|
|
81
|
+
return o.branchCode === seatNumber && ((_a = o.containedInPlace) === null || _a === void 0 ? void 0 : _a.branchCode) === seatSection;
|
|
82
|
+
})) === null || _f === void 0 ? void 0 : _f.offers;
|
|
83
|
+
if (Array.isArray(offersOnSeat)) {
|
|
84
|
+
const availableSeatOffer = offersOnSeat[0];
|
|
85
|
+
const seatPriceSpecs = (_g = availableSeatOffer === null || availableSeatOffer === void 0 ? void 0 : availableSeatOffer.priceSpecification) === null || _g === void 0 ? void 0 : _g.priceComponent;
|
|
86
|
+
if (Array.isArray(seatPriceSpecs)) {
|
|
87
|
+
seatPriceComponent.push(...seatPriceSpecs);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// 指定されたアドオンがオファーに存在すれば、アドオンの単価仕様作成
|
|
93
|
+
const acceptedAddOns = [];
|
|
94
|
+
let availableAddOns;
|
|
95
|
+
const acceptedAddOnsParams = acceptedOffer.addOn;
|
|
96
|
+
if (Array.isArray(acceptedAddOnsParams) && acceptedAddOnsParams.length > 0) {
|
|
97
|
+
// アドオンオファー検索(2023-03-02~)
|
|
98
|
+
availableAddOns = yield searchAvailableAddOns({
|
|
99
|
+
ids: acceptedAddOnsParams.map((acceptedAddOn) => String(acceptedAddOn.id)),
|
|
100
|
+
project: { id: params.event.project.id },
|
|
101
|
+
ticketOffer,
|
|
102
|
+
availableAtOrFrom: params.availableAtOrFrom
|
|
103
|
+
})(repos);
|
|
104
|
+
}
|
|
105
|
+
if (Array.isArray(availableAddOns) && Array.isArray(acceptedAddOnsParams)) {
|
|
106
|
+
acceptedAddOnsParams.forEach((acceptedAddOnParams) => {
|
|
107
|
+
var _a, _b, _c;
|
|
108
|
+
const availableAddOn = availableAddOns === null || availableAddOns === void 0 ? void 0 : availableAddOns.find((addOn) => addOn.id === acceptedAddOnParams.id);
|
|
109
|
+
if (availableAddOn !== undefined) {
|
|
110
|
+
// acceptedAddOnsの重複を避ける(単価オファーIDに対して)
|
|
111
|
+
if (!acceptedAddOns.some((addOn) => addOn.id === availableAddOn.id)) {
|
|
112
|
+
const availableAddOnReferenceQuantityValue = availableAddOn.priceSpecification.referenceQuantity.value;
|
|
113
|
+
if (typeof availableAddOnReferenceQuantityValue !== 'number') {
|
|
114
|
+
throw new factory.errors.NotImplemented('addOn.priceSpecification.referenceQuantity.value must be number');
|
|
115
|
+
}
|
|
116
|
+
// 受入数量はデフォルトで単価オファーの基準数量
|
|
117
|
+
let referenceQuantityValueAccepted = availableAddOnReferenceQuantityValue;
|
|
118
|
+
// 数量指定を検証(2023-08-31~)
|
|
119
|
+
const specifiedReferencedQuantityValue = (_b = (_a = acceptedAddOnParams.priceSpecification) === null || _a === void 0 ? void 0 : _a.referenceQuantity) === null || _b === void 0 ? void 0 : _b.value;
|
|
120
|
+
if (typeof specifiedReferencedQuantityValue === 'number') {
|
|
121
|
+
if (specifiedReferencedQuantityValue < 1) {
|
|
122
|
+
throw new factory.errors.Argument('addOn.priceSpecification.referenceQuantity.value must be > 0');
|
|
123
|
+
}
|
|
124
|
+
// 数量が適用単位要件を満たしていなければエラー
|
|
125
|
+
if (specifiedReferencedQuantityValue % availableAddOnReferenceQuantityValue !== 0) {
|
|
126
|
+
throw new factory.errors.Argument('addOn.priceSpecification.referenceQuantity.value', `Offer ${availableAddOn.id} requires reference quantity value ${specifiedReferencedQuantityValue}`);
|
|
127
|
+
}
|
|
128
|
+
// 基準数量上書き
|
|
129
|
+
referenceQuantityValueAccepted = specifiedReferencedQuantityValue;
|
|
130
|
+
}
|
|
131
|
+
const priceAccepted = availableAddOn.priceSpecification.price *
|
|
132
|
+
(referenceQuantityValueAccepted / availableAddOnReferenceQuantityValue);
|
|
133
|
+
const accountsReceivableAccepted = (typeof ((_c = availableAddOn.priceSpecification.accounting) === null || _c === void 0 ? void 0 : _c.accountsReceivable) === 'number')
|
|
134
|
+
? availableAddOn.priceSpecification.accounting.accountsReceivable *
|
|
135
|
+
(referenceQuantityValueAccepted / availableAddOnReferenceQuantityValue)
|
|
136
|
+
: undefined;
|
|
137
|
+
const acceptedAddOn = Object.assign(Object.assign({}, availableAddOn), { priceSpecification: Object.assign(Object.assign(Object.assign({}, availableAddOn.priceSpecification), (typeof accountsReceivableAccepted === 'number')
|
|
138
|
+
? {
|
|
139
|
+
accounting: Object.assign(Object.assign({}, availableAddOn.priceSpecification.accounting), { accountsReceivable: accountsReceivableAccepted, typeOf: 'Accounting' })
|
|
140
|
+
}
|
|
141
|
+
: undefined), { price: priceAccepted, referenceQuantity: Object.assign(Object.assign({}, availableAddOn.priceSpecification.referenceQuantity), { value: referenceQuantityValueAccepted }) }) });
|
|
142
|
+
acceptedAddOns.push(acceptedAddOn);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// acceptedAddOns = availableAddOns.filter(
|
|
147
|
+
// (availableAddOn) => acceptedAddOnsParams.some((acceptedAddOn) => availableAddOn.id === acceptedAddOn.id)
|
|
148
|
+
// );
|
|
149
|
+
}
|
|
150
|
+
const subReservation = (_j = (_h = acceptedOffer.itemOffered) === null || _h === void 0 ? void 0 : _h.serviceOutput) === null || _j === void 0 ? void 0 : _j.subReservation;
|
|
151
|
+
reservations.push((0, createReservation_1.createReservation)({
|
|
152
|
+
project: { id: params.event.project.id, typeOf: factory.organizationType.Project },
|
|
153
|
+
id: reservationId,
|
|
154
|
+
reservationFor: params.event,
|
|
155
|
+
reservedTicket: reservedTicket,
|
|
156
|
+
additionalProperty: additionalProperty,
|
|
157
|
+
additionalTicketText: additionalTicketText,
|
|
158
|
+
ticketOffer: ticketOffer,
|
|
159
|
+
seatPriceComponent: seatPriceComponent,
|
|
160
|
+
acceptedAddOns: acceptedAddOns,
|
|
161
|
+
subReservation: subReservation,
|
|
162
|
+
programMembershipUsed,
|
|
163
|
+
availableOffer: ticketType,
|
|
164
|
+
appliesToMovieTicket: (_k = acceptedOffer.priceSpecification) === null || _k === void 0 ? void 0 : _k.appliesToMovieTicket,
|
|
165
|
+
validateAppliesToMovieTicket: params.validateAppliesToMovieTicket
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
return reservations;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
exports.createSubReservations = createSubReservations;
|
|
172
|
+
function searchAvailableAddOns(params) {
|
|
173
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
var _a;
|
|
175
|
+
const availableAddOns = [];
|
|
176
|
+
if (Array.isArray(params.ticketOffer.addOn)) {
|
|
177
|
+
const addOnProductIds = [...new Set(params.ticketOffer.addOn.map((o) => String(o.itemOffered.id)))];
|
|
178
|
+
for (const addOnProductId of addOnProductIds) {
|
|
179
|
+
const { offers, product } = yield OfferService.product.search(Object.assign({ ids: params.ids, project: { id: params.project.id }, itemOffered: { id: addOnProductId }, onlyValid: true, addSortIndex: false, includedInDataCatalog: { id: '' }, useIncludeInDataCatalog: false }, (typeof ((_a = params.availableAtOrFrom) === null || _a === void 0 ? void 0 : _a.id) === 'string')
|
|
180
|
+
? { availableAt: { id: params.availableAtOrFrom.id } }
|
|
181
|
+
: undefined))(repos);
|
|
182
|
+
availableAddOns.push(...offers.map((o) => {
|
|
183
|
+
const itemOffered4addOn = {
|
|
184
|
+
description: product.description,
|
|
185
|
+
id: product.id,
|
|
186
|
+
name: product.name,
|
|
187
|
+
productID: product.productID,
|
|
188
|
+
typeOf: product.typeOf
|
|
189
|
+
};
|
|
190
|
+
const unitPriceSpec = o.priceSpecification.priceComponent.find((component) => {
|
|
191
|
+
return component.typeOf === factory.priceSpecificationType.UnitPriceSpecification;
|
|
192
|
+
});
|
|
193
|
+
if ((unitPriceSpec === null || unitPriceSpec === void 0 ? void 0 : unitPriceSpec.typeOf) !== factory.priceSpecificationType.UnitPriceSpecification) {
|
|
194
|
+
throw new factory.errors.NotFound('UnitPriceSpecification of an addOn');
|
|
195
|
+
}
|
|
196
|
+
return Object.assign(Object.assign({ alternateName: o.alternateName, availability: o.availability, description: o.description, id: String(o.id), identifier: o.identifier, itemOffered: itemOffered4addOn, name: o.name, priceCurrency: o.priceCurrency, priceSpecification: unitPriceSpec, typeOf: o.typeOf }, (o.validFrom instanceof Date) ? { validFrom: o.validFrom } : undefined), (o.validThrough instanceof Date) ? { validThrough: o.validThrough } : undefined);
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return availableAddOns;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function validateQuantityRequirement(params) {
|
|
204
|
+
const { acceptedOffers, ticketOffers, reservationNumber } = params;
|
|
205
|
+
const offerIds = (Array.isArray(acceptedOffers))
|
|
206
|
+
? [...new Set(params.acceptedOffers.map(({ id }) => id))]
|
|
207
|
+
: [];
|
|
208
|
+
debug('validating quantity requirement... reservationNumber:', reservationNumber, offerIds);
|
|
209
|
+
// オファーIDごとにオファー適用条件を確認
|
|
210
|
+
offerIds.forEach((offerId) => {
|
|
211
|
+
var _a, _b, _c;
|
|
212
|
+
const numAcceptedOffersByOfferId = params.acceptedOffers.filter(({ id }) => id === offerId).length;
|
|
213
|
+
const ticketOffer = ticketOffers.find(({ id }) => id === offerId);
|
|
214
|
+
if (ticketOffer === undefined) {
|
|
215
|
+
throw new factory.errors.NotFound('Ticket Offer');
|
|
216
|
+
}
|
|
217
|
+
let referenceQuantityValue = 1;
|
|
218
|
+
// 単価仕様を取り出す
|
|
219
|
+
const unitPriceSpec = ticketOffer.priceSpecification.priceComponent.find((spec) => spec.typeOf === factory.priceSpecificationType.UnitPriceSpecification && (!Array.isArray(spec.appliesToAddOn)));
|
|
220
|
+
// 単価仕様は必ず存在するはず
|
|
221
|
+
if ((unitPriceSpec === null || unitPriceSpec === void 0 ? void 0 : unitPriceSpec.typeOf) !== factory.priceSpecificationType.UnitPriceSpecification) {
|
|
222
|
+
throw new factory.errors.Internal(`unitPriceSpec of the offer '${offerId}' not found`);
|
|
223
|
+
}
|
|
224
|
+
const unitPriceSpecReferenceQuantityValue = (_a = unitPriceSpec.referenceQuantity) === null || _a === void 0 ? void 0 : _a.value;
|
|
225
|
+
if (typeof unitPriceSpecReferenceQuantityValue === 'number') {
|
|
226
|
+
referenceQuantityValue = unitPriceSpecReferenceQuantityValue;
|
|
227
|
+
}
|
|
228
|
+
// アイテム数が適用単位要件を満たしていなければエラー
|
|
229
|
+
debug('validating referenceQuantity... reservationNumber:', reservationNumber, offerId, 'numAcceptedOffersByOfferId:', numAcceptedOffersByOfferId, 'referenceQuantityValue:', referenceQuantityValue);
|
|
230
|
+
if (numAcceptedOffersByOfferId % referenceQuantityValue !== 0) {
|
|
231
|
+
throw new factory.errors.Argument('acceptedOffers', `Offer ${offerId} requires reference quantity value ${referenceQuantityValue}`);
|
|
232
|
+
}
|
|
233
|
+
// 適用数量要件を満たしていなければエラー
|
|
234
|
+
const maxValue = (_b = unitPriceSpec.eligibleQuantity) === null || _b === void 0 ? void 0 : _b.maxValue;
|
|
235
|
+
if (typeof maxValue === 'number') {
|
|
236
|
+
debug('validating eligibleQuantity.maxValue... reservationNumber:', reservationNumber, offerId, 'numAcceptedOffersByOfferId:', numAcceptedOffersByOfferId, 'maxValue:', maxValue);
|
|
237
|
+
if (numAcceptedOffersByOfferId > maxValue) {
|
|
238
|
+
throw new factory.errors.Argument('acceptedOffers', `Number of offer:${offerId} must be less than or equal to ${maxValue}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const minValue = (_c = unitPriceSpec.eligibleQuantity) === null || _c === void 0 ? void 0 : _c.minValue;
|
|
242
|
+
if (typeof minValue === 'number') {
|
|
243
|
+
debug('validating eligibleQuantity.minValue... reservationNumber:', reservationNumber, offerId, 'numAcceptedOffersByOfferId:', numAcceptedOffersByOfferId, 'minValue:', minValue);
|
|
244
|
+
if (numAcceptedOffersByOfferId < minValue) {
|
|
245
|
+
throw new factory.errors.Argument('acceptedOffers', `Number of offer:${offerId} must be more than or equal to ${minValue}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 事前予約要件を検証する
|
|
252
|
+
*/
|
|
253
|
+
function validateAdvanceBookingRequirement(params) {
|
|
254
|
+
var _a, _b;
|
|
255
|
+
const advanceBookingRequirementMinValue = (_a = params.unitPriceOffer.advanceBookingRequirement) === null || _a === void 0 ? void 0 : _a.minValue;
|
|
256
|
+
const advanceBookingRequirementUnitCode = (_b = params.unitPriceOffer.advanceBookingRequirement) === null || _b === void 0 ? void 0 : _b.unitCode;
|
|
257
|
+
if (typeof advanceBookingRequirementMinValue === 'number' && typeof advanceBookingRequirementUnitCode === 'string') {
|
|
258
|
+
if (advanceBookingRequirementMinValue < 0) {
|
|
259
|
+
throw new factory.errors.NotImplemented('negative value as advanceBookingRequirement.minValue not implemented');
|
|
260
|
+
}
|
|
261
|
+
if (advanceBookingRequirementUnitCode !== factory.unitCode.Sec) {
|
|
262
|
+
throw new factory.errors.NotImplemented(`only ${factory.unitCode.Sec} implemented`);
|
|
263
|
+
}
|
|
264
|
+
const reservationForMustStartAfter = moment(params.now)
|
|
265
|
+
.add(advanceBookingRequirementMinValue, 'seconds');
|
|
266
|
+
const requirementSatisfied = moment(params.reservationFor.startDate)
|
|
267
|
+
.isSameOrAfter(reservationForMustStartAfter);
|
|
268
|
+
if (!requirementSatisfied) {
|
|
269
|
+
throw new factory.errors.Argument('acceptedOffer.id', 'advanceBookingRequirement not satisfied');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function validateProgramMembershipUsed(params) {
|
|
274
|
+
// tslint:disable-next-line:max-func-body-length
|
|
275
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
var _a, _b, _c;
|
|
277
|
+
const now = new Date();
|
|
278
|
+
let programMembershipUsed;
|
|
279
|
+
const requestedProgramMembershipUsed = (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.programMembershipUsed;
|
|
280
|
+
if (typeof requestedProgramMembershipUsed === 'string') {
|
|
281
|
+
throw new factory.errors.Argument('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed', 'must be object');
|
|
282
|
+
}
|
|
283
|
+
const programMembershipUsedIdentifier = requestedProgramMembershipUsed === null || requestedProgramMembershipUsed === void 0 ? void 0 : requestedProgramMembershipUsed.identifier;
|
|
284
|
+
const issuedThroughId = (_c = requestedProgramMembershipUsed === null || requestedProgramMembershipUsed === void 0 ? void 0 : requestedProgramMembershipUsed.issuedThrough) === null || _c === void 0 ? void 0 : _c.id;
|
|
285
|
+
if (typeof programMembershipUsedIdentifier === 'string' && programMembershipUsedIdentifier.length > 0) {
|
|
286
|
+
if (typeof issuedThroughId !== 'string' || issuedThroughId.length === 0) {
|
|
287
|
+
throw new factory.errors.ArgumentNull('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed.issuedThrough.id');
|
|
288
|
+
}
|
|
289
|
+
let permitIssuedThrough;
|
|
290
|
+
// まずメンバーシップを検索して、存在しなければCreditCardを検索(どちらが発行元サービスか不明なので)
|
|
291
|
+
permitIssuedThrough = (yield repos.product.searchProducts({
|
|
292
|
+
limit: 1,
|
|
293
|
+
page: 1,
|
|
294
|
+
id: { $eq: issuedThroughId },
|
|
295
|
+
typeOf: { $eq: factory.product.ProductType.MembershipService }
|
|
296
|
+
}, ['_id', 'typeOf', 'project', 'serviceType', 'serviceOutput'], [])).shift();
|
|
297
|
+
if (permitIssuedThrough === undefined) {
|
|
298
|
+
permitIssuedThrough = (yield repos.paymentService.searchPaymentServices({
|
|
299
|
+
limit: 1,
|
|
300
|
+
page: 1,
|
|
301
|
+
id: { $eq: issuedThroughId },
|
|
302
|
+
typeOf: { $eq: factory.service.paymentService.PaymentServiceType.CreditCard }
|
|
303
|
+
}, ['_id', 'typeOf', 'project', 'serviceType', 'serviceOutput'], [])).shift();
|
|
304
|
+
}
|
|
305
|
+
if (typeof (permitIssuedThrough === null || permitIssuedThrough === void 0 ? void 0 : permitIssuedThrough.typeOf) !== 'string') {
|
|
306
|
+
throw new factory.errors.NotFound(`Permit issuer service [${issuedThroughId}]`);
|
|
307
|
+
}
|
|
308
|
+
// permitIssuedThrough =
|
|
309
|
+
// await repos.product.findById({ id: issuedThroughId }, ['_id', 'typeOf', 'project', 'serviceType', 'serviceOutput'], []);
|
|
310
|
+
switch (permitIssuedThrough.typeOf) {
|
|
311
|
+
// 発行サービスがCreditCardのケースに対応(2023-09-01~)
|
|
312
|
+
case factory.service.paymentService.PaymentServiceType.CreditCard:
|
|
313
|
+
// 決済サービスのserviceOutputにPermitが存在すれば、設定されたメンバーシップ区分のPermitをprogramMembershipUsedとして適用する
|
|
314
|
+
let issuedThroughServiceType;
|
|
315
|
+
if (Array.isArray(permitIssuedThrough.serviceOutput)) {
|
|
316
|
+
const serviceOutputAsPermit = permitIssuedThrough.serviceOutput.find((output) => output.typeOf === factory.permit.PermitType.Permit);
|
|
317
|
+
if ((serviceOutputAsPermit === null || serviceOutputAsPermit === void 0 ? void 0 : serviceOutputAsPermit.typeOf) === factory.permit.PermitType.Permit) {
|
|
318
|
+
issuedThroughServiceType = serviceOutputAsPermit.issuedThrough.serviceType;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if ((issuedThroughServiceType === null || issuedThroughServiceType === void 0 ? void 0 : issuedThroughServiceType.typeOf) === 'CategoryCode') {
|
|
322
|
+
programMembershipUsed = {
|
|
323
|
+
project: permitIssuedThrough.project,
|
|
324
|
+
typeOf: factory.permit.PermitType.Permit,
|
|
325
|
+
identifier: programMembershipUsedIdentifier,
|
|
326
|
+
issuedThrough: {
|
|
327
|
+
id: permitIssuedThrough.id,
|
|
328
|
+
serviceType: issuedThroughServiceType,
|
|
329
|
+
typeOf: permitIssuedThrough.typeOf
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
throw new factory.errors.Argument('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed', 'issuedThrough has no serviceOutput as Permit');
|
|
335
|
+
}
|
|
336
|
+
break;
|
|
337
|
+
case factory.product.ProductType.MembershipService:
|
|
338
|
+
// requestedProgramMembershipUsedの発行サービスIDから外部連携設定を取得する
|
|
339
|
+
const permitService = yield createPermitService({ issuedThrough: { id: issuedThroughId } })(repos);
|
|
340
|
+
// メンバーシップの存在確認
|
|
341
|
+
const serviceOutput = yield permitService.findByIdentifier({
|
|
342
|
+
project: { id: params.project.id },
|
|
343
|
+
identifier: programMembershipUsedIdentifier,
|
|
344
|
+
issuedThrough: { typeOf: factory.product.ProductType.MembershipService }
|
|
345
|
+
});
|
|
346
|
+
// 有効期間のチェック
|
|
347
|
+
if (serviceOutput.validFrom === undefined || serviceOutput.validFrom === null
|
|
348
|
+
|| serviceOutput.validUntil === undefined || serviceOutput.validUntil === null) {
|
|
349
|
+
throw new factory.errors.Argument('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed', 'not valid programMembership');
|
|
350
|
+
}
|
|
351
|
+
if (moment(serviceOutput.validFrom)
|
|
352
|
+
.isAfter(moment(now))
|
|
353
|
+
|| moment(serviceOutput.validUntil)
|
|
354
|
+
.isBefore(moment(now))) {
|
|
355
|
+
throw new factory.errors.Argument('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed', 'unavailable programMembership');
|
|
356
|
+
}
|
|
357
|
+
programMembershipUsed = {
|
|
358
|
+
project: serviceOutput.project,
|
|
359
|
+
typeOf: serviceOutput.typeOf,
|
|
360
|
+
identifier: serviceOutput.identifier,
|
|
361
|
+
issuedThrough: serviceOutput.issuedThrough
|
|
362
|
+
};
|
|
363
|
+
break;
|
|
364
|
+
default:
|
|
365
|
+
throw new factory.errors.Argument('acceptedOffer.itemOffered.serviceOutput.programMembershipUsed', `${permitIssuedThrough.typeOf} not implemented`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return programMembershipUsed;
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function createPermitService(params) {
|
|
372
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
373
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
374
|
+
// const product = <Pick<factory.product.IProduct, 'availableChannel'>>
|
|
375
|
+
// await repos.product.findProductById({ id: params.issuedThrough.id }, ['availableChannel'], []);
|
|
376
|
+
const product = (yield repos.product.searchProducts({
|
|
377
|
+
limit: 1,
|
|
378
|
+
page: 1,
|
|
379
|
+
id: { $eq: params.issuedThrough.id }
|
|
380
|
+
}, ['availableChannel'], [])).shift();
|
|
381
|
+
if (product === undefined) {
|
|
382
|
+
throw new factory.errors.NotFound('Product');
|
|
383
|
+
}
|
|
384
|
+
const permitServiceEndpoint = (_a = product.availableChannel) === null || _a === void 0 ? void 0 : _a.serviceUrl;
|
|
385
|
+
const permitServiceAuthorizeServerDomain = (_c = (_b = product.availableChannel) === null || _b === void 0 ? void 0 : _b.credentials) === null || _c === void 0 ? void 0 : _c.authorizeServerDomain;
|
|
386
|
+
const permitServiceClientId = (_e = (_d = product.availableChannel) === null || _d === void 0 ? void 0 : _d.credentials) === null || _e === void 0 ? void 0 : _e.clientId;
|
|
387
|
+
const permitServiceClientSecret = (_g = (_f = product.availableChannel) === null || _f === void 0 ? void 0 : _f.credentials) === null || _g === void 0 ? void 0 : _g.clientSecret;
|
|
388
|
+
if (typeof permitServiceEndpoint !== 'string' || permitServiceEndpoint.length === 0
|
|
389
|
+
|| typeof permitServiceAuthorizeServerDomain !== 'string' || permitServiceAuthorizeServerDomain.length === 0
|
|
390
|
+
|| typeof permitServiceClientId !== 'string' || permitServiceClientId.length === 0
|
|
391
|
+
|| typeof permitServiceClientSecret !== 'string' || permitServiceClientSecret.length === 0) {
|
|
392
|
+
throw new factory.errors.Internal('product availableChannel invalid');
|
|
393
|
+
}
|
|
394
|
+
return new (yield pecorinoapi.loadPecorino()).service.Permit({
|
|
395
|
+
endpoint: permitServiceEndpoint,
|
|
396
|
+
auth: yield pecorinoapi.auth.ClientCredentials.createInstance({
|
|
397
|
+
domain: permitServiceAuthorizeServerDomain,
|
|
398
|
+
clientId: permitServiceClientId,
|
|
399
|
+
clientSecret: permitServiceClientSecret,
|
|
400
|
+
scopes: [],
|
|
401
|
+
state: ''
|
|
402
|
+
})
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as factory from '../../../../../factory';
|
|
2
|
+
/**
|
|
3
|
+
* ポイント特典を作成する
|
|
4
|
+
*/
|
|
5
|
+
declare function createPointAward(params: {
|
|
6
|
+
acceptedOffer: factory.assetTransaction.reserve.IAcceptedTicketOfferWithoutDetail;
|
|
7
|
+
offer: factory.product.ITicketOffer;
|
|
8
|
+
reservation: {
|
|
9
|
+
id: string;
|
|
10
|
+
};
|
|
11
|
+
project: {
|
|
12
|
+
id: string;
|
|
13
|
+
};
|
|
14
|
+
}): factory.action.transfer.moneyTransfer.IPointAward | undefined;
|
|
15
|
+
export { createPointAward };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPointAward = void 0;
|
|
4
|
+
const factory = require("../../../../../factory");
|
|
5
|
+
const accountTransactionIdentifier_1 = require("../../../../../factory/accountTransactionIdentifier");
|
|
6
|
+
/**
|
|
7
|
+
* ポイント特典を作成する
|
|
8
|
+
*/
|
|
9
|
+
function createPointAward(params) {
|
|
10
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
11
|
+
let pointAward;
|
|
12
|
+
const pointAwardAmount = (_b = (_a = params.offer.itemOffered) === null || _a === void 0 ? void 0 : _a.pointAward) === null || _b === void 0 ? void 0 : _b.amount;
|
|
13
|
+
const pointAwardDescription = (_d = (_c = params.offer.itemOffered) === null || _c === void 0 ? void 0 : _c.pointAward) === null || _d === void 0 ? void 0 : _d.description;
|
|
14
|
+
const pointAwardToLocationIdentifier = (_g = (_f = (_e = params.acceptedOffer.itemOffered) === null || _e === void 0 ? void 0 : _e.pointAward) === null || _f === void 0 ? void 0 : _f.toLocation) === null || _g === void 0 ? void 0 : _g.identifier;
|
|
15
|
+
const pointAwardToLocationIssuedThroughId = (_k = (_j = (_h = params.acceptedOffer.itemOffered) === null || _h === void 0 ? void 0 : _h.pointAward) === null || _j === void 0 ? void 0 : _j.toLocation) === null || _k === void 0 ? void 0 : _k.issuedThrough.id;
|
|
16
|
+
const pointAwardRecipient = (_m = (_l = params.acceptedOffer.itemOffered) === null || _l === void 0 ? void 0 : _l.pointAward) === null || _m === void 0 ? void 0 : _m.recipient;
|
|
17
|
+
// const pointAwardPurposeIdentifier = params.acceptedOffer.itemOffered?.pointAward?.purpose?.identifier;
|
|
18
|
+
// オファーのpointAward設定が適切にされていれば、指定されたtoLocationを反映する
|
|
19
|
+
if (typeof (pointAwardAmount === null || pointAwardAmount === void 0 ? void 0 : pointAwardAmount.value) === 'number'
|
|
20
|
+
&& typeof (pointAwardAmount === null || pointAwardAmount === void 0 ? void 0 : pointAwardAmount.currency) === 'string'
|
|
21
|
+
&& typeof pointAwardToLocationIdentifier === 'string'
|
|
22
|
+
&& typeof pointAwardToLocationIssuedThroughId === 'string') {
|
|
23
|
+
// ここで識別子を作成する(入金のユニークネスが保証される)
|
|
24
|
+
const purposeIdentifier = (0, accountTransactionIdentifier_1.createPointAwardPurposeIdentifier4reservation)({
|
|
25
|
+
assetTransaction: { typeOf: factory.assetTransactionType.Reserve },
|
|
26
|
+
project: { id: params.project.id },
|
|
27
|
+
reservation: { id: params.reservation.id },
|
|
28
|
+
toLocation: { identifier: pointAwardToLocationIdentifier }
|
|
29
|
+
});
|
|
30
|
+
pointAward = Object.assign(Object.assign({ amount: pointAwardAmount, purpose: { identifier: purposeIdentifier }, toLocation: {
|
|
31
|
+
typeOf: factory.permit.PermitType.Permit,
|
|
32
|
+
identifier: pointAwardToLocationIdentifier,
|
|
33
|
+
issuedThrough: { id: pointAwardToLocationIssuedThroughId }
|
|
34
|
+
}, typeOf: factory.actionType.MoneyTransfer }, (typeof pointAwardDescription === 'string') ? { description: pointAwardDescription } : undefined), (pointAwardRecipient !== undefined) ? { recipient: pointAwardRecipient } : undefined
|
|
35
|
+
// ...(typeof pointAwardPurposeIdentifier === 'string') ? { purpose: { identifier: pointAwardPurposeIdentifier } } : undefined
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return pointAward;
|
|
39
|
+
}
|
|
40
|
+
exports.createPointAward = createPointAward;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as factory from '../../../../../factory';
|
|
2
|
+
import { IMinimizedIndividualEvent } from '../../../../../factory/event';
|
|
3
|
+
import { IAcceptedAddOn } from './price';
|
|
4
|
+
type IObjectSubReservation = factory.assetTransaction.reserve.IObjectSubReservation;
|
|
5
|
+
declare function createReservedTicket(params: {
|
|
6
|
+
id: string;
|
|
7
|
+
acceptedOffer: factory.assetTransaction.reserve.IAcceptedTicketOfferWithoutDetail;
|
|
8
|
+
availableOffer: factory.unitPriceOffer.IUnitPriceOffer;
|
|
9
|
+
dateIssued: Date;
|
|
10
|
+
reservationFor: {
|
|
11
|
+
id: string;
|
|
12
|
+
};
|
|
13
|
+
reservedSeatsOnly: boolean;
|
|
14
|
+
screeningRoomSections?: factory.place.screeningRoomSection.IPlace[];
|
|
15
|
+
availableSeatOffers: factory.place.seat.IPlaceWithOffer[];
|
|
16
|
+
ticketOffer: factory.product.ITicketOffer;
|
|
17
|
+
}): factory.reservation.ITicket;
|
|
18
|
+
declare function validateAppliesToMovieTicket(params: {
|
|
19
|
+
availableOffer: factory.unitPriceOffer.IUnitPriceOffer;
|
|
20
|
+
appliesToMovieTicket?: factory.assetTransaction.reserve.IAcceptedAppliesToMovieTicket;
|
|
21
|
+
}): void;
|
|
22
|
+
/**
|
|
23
|
+
* 追加特性を生成する
|
|
24
|
+
*/
|
|
25
|
+
declare function createAdditionalProperty(params: {
|
|
26
|
+
acceptedOffer: factory.assetTransaction.reserve.IAcceptedTicketOfferWithoutDetail;
|
|
27
|
+
}): factory.propertyValue.IPropertyValue<string>[];
|
|
28
|
+
/**
|
|
29
|
+
* 追加チケットテキストを生成する
|
|
30
|
+
*/
|
|
31
|
+
declare function createAdditionalTicketText(params: {
|
|
32
|
+
acceptedOffer: factory.assetTransaction.reserve.IAcceptedTicketOfferWithoutDetail;
|
|
33
|
+
reservedTicket: factory.reservation.ITicket;
|
|
34
|
+
}): string | undefined;
|
|
35
|
+
declare function createReservation(params: {
|
|
36
|
+
project: {
|
|
37
|
+
id: string;
|
|
38
|
+
typeOf: factory.organizationType.Project;
|
|
39
|
+
};
|
|
40
|
+
id: string;
|
|
41
|
+
reservationFor: IMinimizedIndividualEvent<factory.eventType.ScreeningEvent> | IMinimizedIndividualEvent<factory.eventType.Event>;
|
|
42
|
+
reservedTicket: factory.reservation.ITicket;
|
|
43
|
+
additionalProperty?: factory.propertyValue.IPropertyValue<string>[];
|
|
44
|
+
additionalTicketText?: string;
|
|
45
|
+
ticketOffer: factory.product.ITicketOffer;
|
|
46
|
+
seatPriceComponent: factory.place.seat.IPriceComponent[];
|
|
47
|
+
acceptedAddOns: IAcceptedAddOn[];
|
|
48
|
+
subReservation?: factory.reservation.ISubReservation<factory.reservationType.EventReservation>[];
|
|
49
|
+
programMembershipUsed?: factory.reservation.IProgramMembershipUsed<factory.reservationType.EventReservation>;
|
|
50
|
+
availableOffer: factory.unitPriceOffer.IUnitPriceOffer;
|
|
51
|
+
appliesToMovieTicket?: factory.assetTransaction.reserve.IAcceptedAppliesToMovieTicket;
|
|
52
|
+
validateAppliesToMovieTicket: boolean;
|
|
53
|
+
}): IObjectSubReservation;
|
|
54
|
+
export { createAdditionalProperty, createAdditionalTicketText, createReservation, createReservedTicket, IAcceptedAddOn, validateAppliesToMovieTicket };
|