@chevre/domain
Version:
Chevre Domain Library for Node.js
593 lines (592 loc) • 32.8 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
const createDebug = require("debug");
const moment = require("moment");
const factory = require("../../../factory");
const pecorinoapi = require("../../../pecorinoapi");
const seat_1 = require("../../../repo/place/seat");
const OfferService = require("../../offer");
const searchOffersByIds_1 = require("../../offer/event/searchOffersByIds");
const cancelReservation_1 = require("../../reserve/cancelReservation");
const onReservationsCreated_1 = require("../../reserve/potentialActions/onReservationsCreated");
const createSubReservations_1 = require("./start/createSubReservations");
const createPointAward_1 = require("./start/factory/createPointAward");
const createStartParams_1 = require("./start/factory/createStartParams");
const validateStartRequest_1 = require("./validateStartRequest");
const debug = createDebug('chevre-domain:service:assetTransaction:reserve');
const ONE_MONTH_IN_DAYS = 31;
/**
* 取引開始
*/
function start(params, options) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const now = new Date();
const reservationNumber = params.transactionNumber;
if (typeof reservationNumber !== 'string' || reservationNumber.length === 0) {
throw new factory.errors.ArgumentNull('transactionNumber'); // 自動発行廃止(2022-05-17~)
}
// eventをfix
const event = yield fixEvent(params)(repos);
// validationを承認アクション開始前から移行(2023-01-27~)
yield (0, validateStartRequest_1.validateStartRequest)({
object: params.object,
event,
validateEventOfferPeriod: params.validateEventOfferPeriod,
validateEvent: params.validateEvent,
now,
store: { id: (_a = params.availableAtOrFrom) === null || _a === void 0 ? void 0 : _a.id }
})({
eventOffer: repos.eventOffer,
issuer: repos.issuer,
memberProgram: repos.memberProgram
});
// objectに必要な情報をそろえる
const { acceptedOffers4transactionObject, objectSubReservations } = yield createObjectAttributes({
// reservationFor: startParams.object.reservationFor,
transaction: { transactionNumber: reservationNumber },
now,
object: params.object,
event,
preSearchedTicketOffers: params.preSearchedTicketOffers,
preSearchedUnitPriceOffers: params.preSearchedUnitPriceOffers,
availableAtOrFrom: { id: (_b = params.availableAtOrFrom) === null || _b === void 0 ? void 0 : _b.id },
validateAppliesToMovieTicket: params.validateAppliesToMovieTicket
// stockHoldUntilDaysAfterEventEnd: params.stockHoldUntilDaysAfterEventEnd
}, options)(repos);
const startParams = (0, createStartParams_1.createStartParams)(Object.assign(Object.assign({}, params), { provider: { id: event.organizer.id }, reservationNumber, event, acceptedOffers4transactionObject, objectSubReservations }));
// reimplement using startWithMinimalResponse(2024-07-02~)
// const transaction = await repos.assetTransaction.start<factory.assetTransactionType.Reserve>(startParams);
const { id, startDate } = yield repos.assetTransaction.startWithMinimalResponse(startParams);
yield addReservations({
reservationFor: startParams.object.reservationFor,
transaction: {
id,
transactionNumber: reservationNumber,
instrument: (Array.isArray(startParams.instrument)) ? startParams.instrument : [],
startDate
},
event,
// stockHoldUntilDaysAfterEventEnd: params.stockHoldUntilDaysAfterEventEnd,
objectSubReservations
})(repos);
return {
transaction: { id },
objectSubReservations,
issuedThrough: startParams.object.issuedThrough,
reservationFor: startParams.object.reservationFor
};
});
}
function fixEvent(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const reservationForId = (_a = params.object.reservationFor) === null || _a === void 0 ? void 0 : _a.id;
if (typeof reservationForId !== 'string' || reservationForId.length === 0) {
throw new factory.errors.ArgumentNull('object.reservationFor.id');
}
const event = yield repos.event.projectEventFieldsById({ id: reservationForId }, [
'project', 'organizer', 'typeOf',
// additionalProperty, // discontinue(2024-07-20~)
'name', 'doorTime', 'endDate', 'eventStatus',
'location', 'startDate', 'superEvent',
'offers'
// 'coaInfo', // discontinue(2024-07-24~)
// 'identifier' // discontinue(2024-07-24~)
]);
const offeredThroughIdentifier = (_b = event.offers.offeredThrough) === null || _b === void 0 ? void 0 : _b.identifier;
if (offeredThroughIdentifier === factory.service.webAPI.Identifier.COA) {
throw new factory.errors.NotImplemented(`${offeredThroughIdentifier} not implemented`);
}
return event;
});
}
function createObjectAttributes(params, options) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a;
const { event, now } = params;
const reservationNumber = params.transaction.transactionNumber;
const acceptedOffers = (Array.isArray(params.object.acceptedOffer)) ? params.object.acceptedOffer : [];
if (event.typeOf !== factory.eventType.ScreeningEvent && event.typeOf !== factory.eventType.Event) {
throw new factory.errors.Argument('object.reservationFor.id', `invalid event type ${event.typeOf}`);
}
if (event.typeOf === factory.eventType.ScreeningEvent || event.typeOf === factory.eventType.Event) {
validateEvent({ now, event }, options);
}
// 受け入れたオファーIDだけ取得する(2023-01-26~)
const acceptedOfferIds = [...new Set(acceptedOffers.map((o) => String(o.id)))];
let ticketOffers;
let availableOffers;
// 承認アクションを介した予約取引開始時の冗長なオファー検索処理について最適化(2023-01-27~)
if (Array.isArray(params.preSearchedTicketOffers) && Array.isArray(params.preSearchedUnitPriceOffers)) {
ticketOffers = params.preSearchedTicketOffers;
availableOffers = params.preSearchedUnitPriceOffers;
}
else {
// 興行オファー検索
const searchEventTicketOffersResult = yield (0, searchOffersByIds_1.searchOffersByIds)({
ids: acceptedOfferIds,
event: { id: event.id, typeOf: event.typeOf },
store: { id: (_a = params.availableAtOrFrom) === null || _a === void 0 ? void 0 : _a.id },
options: {} // 明示的なサブカタログ指定には未対応(2024-10-01~)
// priceSpecification: {}, // 絞る必要なし
// includedInDataCatalog: { id: '' }, // 承認時はカタログ指定の必要なし
// onlyValid: true,
// addSortIndex: false,
// validateOfferRateLimit: true
// useIncludeInDataCatalog: false
})(repos);
ticketOffers = searchEventTicketOffersResult.ticketOffers;
availableOffers = searchEventTicketOffersResult.unitPriceOffers;
}
const availableSeatOffers = yield searchAvailableSeatOffers({ acceptedOffers, event })(repos);
return createAcceptedOffers4transactionObject({
acceptedOffers, ticketOffers, availableOffers, now,
event, availableSeatOffers, reservationNumber,
availableAtOrFrom: params.availableAtOrFrom,
validateAppliesToMovieTicket: params.validateAppliesToMovieTicket
})(repos);
});
}
/**
* 予約追加
*/
function addReservations(params) {
return (repos
// settings: Settings
) => __awaiter(this, void 0, void 0, function* () {
const reservationNumber = params.transaction.transactionNumber;
const { event, reservationFor, objectSubReservations } = params;
let lockedOfferRateLimitKeys = [];
try {
lockedOfferRateLimitKeys = yield processLockOfferRateLimit({
project: { id: params.event.project.id },
reservations: objectSubReservations,
reservationFor,
reservationNumber
})(repos);
}
catch (error) {
if (lockedOfferRateLimitKeys.length > 0) {
yield Promise.all(objectSubReservations.map((reservation) => __awaiter(this, void 0, void 0, function* () {
yield (0, cancelReservation_1.processUnlockOfferRateLimit)({
project: { id: params.event.project.id },
reservation: {
reservationNumber,
reservedTicket: reservation.reservedTicket
},
reservationFor
})(repos);
})));
}
throw error;
}
// 座席指定でも座席ロック
// イベントキャパシティ設定のみでも座席ロック
yield processLockSeats({
event: event,
reservations: objectSubReservations,
transaction: {
id: params.transaction.id,
transactionNumber: params.transaction.transactionNumber,
startDate: params.transaction.startDate
}
// stockHoldUntilDaysAfterEventEnd: params.stockHoldUntilDaysAfterEventEnd
})(repos);
// ストックホルダー処理(stockHolderで残席数を集計しているので必要)
yield (0, onReservationsCreated_1.onReservationsCreated)({
project: { id: event.project.id },
event: { id: event.id },
transaction: params.transaction
})(repos);
});
}
/**
* イベントに対する座席オファーを座席コードとセクションコード指定で検索する
*/
// tslint:disable-next-line:max-func-body-length
function searchEventSeatOffers(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f;
let offers = [];
// 座席指定利用可能かどうか
const eventOffers = params.event.offers;
const reservedSeatsAvailable = ((_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;
if (reservedSeatsAvailable) {
const roomBranchCode = String((_d = (_c = eventOffers.itemOffered) === null || _c === void 0 ? void 0 : _c.availableChannel) === null || _d === void 0 ? void 0 : _d.serviceLocation.branchCode);
const movieTheaterBranchCode = String((_f = (_e = eventOffers.itemOffered) === null || _e === void 0 ? void 0 : _e.availableChannel) === null || _f === void 0 ? void 0 : _f.serviceLocation.containedInPlace.branchCode);
// reimplement using projectSeatsByScreeningRoom
const seats = yield repos.seat.projectSeatsByScreeningRoom({
project: { id: { $eq: params.event.project.id } },
screeningRoom: {
branchCode: { $eq: roomBranchCode },
containedInPlace: {
branchCode: { $eq: movieTheaterBranchCode }
}
},
branchCode: { $in: params.branchCode.$in },
containedInPlace: {
branchCode: {
$in: params.containedInPlace.branchCode.$in
}
},
$projection: Object.assign({}, params.$projection)
});
if (seats.length > 0) {
const availabilities = yield repos.stockHolder.searchHolders({
project: { id: params.event.project.id },
eventId: params.event.id,
startDate: moment(params.event.startDate)
.toDate(),
hasTicketedSeat: true,
offers: seats.map((s) => {
var _a;
return {
seatNumber: s.branchCode,
seatSection: (_a = s.containedInPlace) === null || _a === void 0 ? void 0 : _a.branchCode
};
})
});
// ルームに含まれる座席区分のみ加算料金を検索(2024-08-06~)
const uniqueSeatingTypes = yield repos.seat.aggregateSeatingTypes({
project: { id: { $eq: params.event.project.id } },
branchCode: { $in: params.branchCode.$in },
containedInPlace: {
branchCode: {
$in: params.containedInPlace.branchCode.$in
},
containedInPlace: {
branchCode: { $eq: roomBranchCode },
containedInPlace: { branchCode: { $eq: movieTheaterBranchCode } }
}
}
});
debug('searchEventSeatOffers: uniqueSeatingTypes:', uniqueSeatingTypes, params.event.project.id, params.branchCode.$in, params.containedInPlace.branchCode.$in, roomBranchCode, movieTheaterBranchCode);
// 座席タイプ価格仕様を検索
let priceSpecs = [];
if (Array.isArray(uniqueSeatingTypes) && uniqueSeatingTypes.length > 0) {
priceSpecs = yield repos.priceSpecification.search({
project: { id: { $eq: params.event.project.id } },
typeOf: factory.priceSpecificationType.CategoryCodeChargeSpecification,
appliesToCategoryCode: {
inCodeSet: { identifier: { $eq: factory.categoryCode.CategorySetIdentifier.SeatingType } },
codeValue: { $in: uniqueSeatingTypes } // ルームに含まれる座席区分のみ加算料金を検索(2024-08-06~)
}
});
}
offers = seats.map((seat, index) => {
return OfferService.addOffers2Seat({
seat,
// unavailableOffers: [],
// availability: availabilities[index].availability,
availability: (typeof availabilities[index] === 'string')
? factory.itemAvailability.OutOfStock // ホルダーが存在すればOutOfStock
: factory.itemAvailability.InStock,
priceSpecs
});
});
}
}
return offers;
});
}
function searchAvailableSeatOffers(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
// 座席オファー検索(必要な分だけ)
const { acceptedSeatNumbers, acceptedSeatSections } = getAcceptedSeatNumbersAndSeatSections({ acceptedOffers: params.acceptedOffers });
return searchEventSeatOffers({
branchCode: { $in: acceptedSeatNumbers },
containedInPlace: { branchCode: { $in: acceptedSeatSections } },
event: params.event,
// 試しに冗長な情報を非取得にしてみる
$projection: {
'containedInPlace.containedInPlace': 0
}
})(repos);
});
}
function validateEvent(params, options) {
const { maxReservationGracePeriodInDays } = options;
// キャンセルステータスであれば予約不可
if (params.event.eventStatus === factory.eventStatusType.EventCancelled) {
throw new factory.errors.Argument('Event', `Event status ${params.event.eventStatus}`);
}
// 予約取引開始可能なイベント開始日時範囲を明確に制限(2024-03-11~)
const reservableThrough = moment(params.now)
.add(maxReservationGracePeriodInDays, 'days');
const reservableFrom = moment(params.now)
.add(-ONE_MONTH_IN_DAYS, 'days');
if (!moment(params.event.startDate)
.isBetween(reservableFrom, reservableThrough, 'second', '[]')) {
throw new factory.errors.Argument('Event', `bookingTime must be between ${maxReservationGracePeriodInDays} days before and ${ONE_MONTH_IN_DAYS} days after the event start date`);
}
// イベントが一定期間後であれば予約不可
// if (moment(params.event.startDate)
// .isAfter(reservableThrough)) {
// throw new factory.errors.Argument(
// 'Event',
// `Maximum reservation grace period is ${MAXIMUM_RESERVATION_GRACE_PERIOD_IN_DAYS} days`
// );
// }
}
function createAcceptedOffers4transactionObject(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
// 予約番号
// const reservationNumber = params.transaction.object.reservationNumber;
const reservationNumber = params.reservationNumber;
if (typeof reservationNumber !== 'string') {
throw new factory.errors.Internal('Reservation number undefined');
}
const objectSubReservations = yield (0, createSubReservations_1.createSubReservations)(params)(repos);
const acceptedOffers4transactionObject = [];
let reservationIndex = -1;
for (const acceptedOffer of params.acceptedOffers) {
reservationIndex += 1;
const ticketOffer = params.ticketOffers.find((t) => t.id === acceptedOffer.id);
if (ticketOffer === undefined) {
throw new factory.errors.NotFound('Ticket Offer');
}
const reservationId = `${reservationNumber}-${reservationIndex}`;
// 入金先検証
yield validatePointAward({ project: { id: params.event.project.id }, acceptedOffer })(repos);
const pointAward = (0, createPointAward_1.createPointAward)({
project: { id: params.event.project.id },
acceptedOffer: acceptedOffer,
offer: ticketOffer,
reservation: { id: reservationId }
});
// acceptedOffers4transactionObjectには必要な情報のみ保管する
acceptedOffers4transactionObject.push({
id: acceptedOffer.id,
itemOffered: Object.assign(Object.assign({}, (pointAward !== undefined) ? { pointAward } : undefined), { serviceOutput: { id: reservationId } })
});
}
return { acceptedOffers4transactionObject, objectSubReservations };
});
}
function getAcceptedSeatNumbersAndSeatSections(params) {
const acceptedSeatNumbers = [];
const acceptedSeatSections = [];
params.acceptedOffers.forEach((o) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
const acceptedSeatNumber = (_d = (_c = (_b = (_a = o.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservedTicket) === null || _c === void 0 ? void 0 : _c.ticketedSeat) === null || _d === void 0 ? void 0 : _d.seatNumber;
const acceptedSeatSection = (_h = (_g = (_f = (_e = o.itemOffered) === null || _e === void 0 ? void 0 : _e.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservedTicket) === null || _g === void 0 ? void 0 : _g.ticketedSeat) === null || _h === void 0 ? void 0 : _h.seatSection;
if (typeof acceptedSeatNumber === 'string' && acceptedSeatNumber.length > 0) {
acceptedSeatNumbers.push(acceptedSeatNumber);
}
if (typeof acceptedSeatSection === 'string' && acceptedSeatSection.length > 0) {
acceptedSeatSections.push(acceptedSeatSection);
}
const subReservation = (_k = (_j = o.itemOffered) === null || _j === void 0 ? void 0 : _j.serviceOutput) === null || _k === void 0 ? void 0 : _k.subReservation;
if (Array.isArray(subReservation)) {
subReservation.forEach((s) => {
var _a, _b, _c, _d;
const subReservationSeatNumber = (_b = (_a = s.reservedTicket) === null || _a === void 0 ? void 0 : _a.ticketedSeat) === null || _b === void 0 ? void 0 : _b.seatNumber;
const subReservationSeatSection = (_d = (_c = s.reservedTicket) === null || _c === void 0 ? void 0 : _c.ticketedSeat) === null || _d === void 0 ? void 0 : _d.seatSection;
if (typeof subReservationSeatNumber === 'string' && subReservationSeatNumber.length > 0) {
acceptedSeatNumbers.push(subReservationSeatNumber);
}
if (typeof subReservationSeatSection === 'string' && subReservationSeatSection.length > 0) {
acceptedSeatSections.push(subReservationSeatSection);
}
});
}
});
return {
acceptedSeatNumbers,
acceptedSeatSections
};
}
function createPermitService(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g;
const product = (yield repos.product.projectFields({
limit: 1,
page: 1,
id: { $eq: params.issuedThrough.id }
}, ['availableChannel']
// []
)).shift();
if (product === undefined) {
throw new factory.errors.NotFound('Product');
}
const permitServiceEndpoint = (_a = product.availableChannel) === null || _a === void 0 ? void 0 : _a.serviceUrl;
const permitServiceAuthorizeServerDomain = (_c = (_b = product.availableChannel) === null || _b === void 0 ? void 0 : _b.credentials) === null || _c === void 0 ? void 0 : _c.authorizeServerDomain;
const permitServiceClientId = (_e = (_d = product.availableChannel) === null || _d === void 0 ? void 0 : _d.credentials) === null || _e === void 0 ? void 0 : _e.clientId;
const permitServiceClientSecret = (_g = (_f = product.availableChannel) === null || _f === void 0 ? void 0 : _f.credentials) === null || _g === void 0 ? void 0 : _g.clientSecret;
if (typeof permitServiceEndpoint !== 'string' || permitServiceEndpoint.length === 0
|| typeof permitServiceAuthorizeServerDomain !== 'string' || permitServiceAuthorizeServerDomain.length === 0
|| typeof permitServiceClientId !== 'string' || permitServiceClientId.length === 0
|| typeof permitServiceClientSecret !== 'string' || permitServiceClientSecret.length === 0) {
throw new factory.errors.Internal('product availableChannel invalid');
}
return new (yield pecorinoapi.loadPecorino()).service.Permit({
endpoint: permitServiceEndpoint,
auth: yield pecorinoapi.auth.ClientCredentials.createInstance({
domain: permitServiceAuthorizeServerDomain,
clientId: permitServiceClientId,
clientSecret: permitServiceClientSecret,
scopes: [],
state: ''
})
});
});
}
function validatePointAward(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g;
// 口座番号確認ではなく、Permit識別子確認
const permitIdentifier = (_c = (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.pointAward) === null || _b === void 0 ? void 0 : _b.toLocation) === null || _c === void 0 ? void 0 : _c.identifier;
const issuedThroughId = (_g = (_f = (_e = (_d = params.acceptedOffer.itemOffered) === null || _d === void 0 ? void 0 : _d.pointAward) === null || _e === void 0 ? void 0 : _e.toLocation) === null || _f === void 0 ? void 0 : _f.issuedThrough) === null || _g === void 0 ? void 0 : _g.id;
if (typeof permitIdentifier === 'string' && permitIdentifier.length > 0) {
if (typeof issuedThroughId !== 'string' || issuedThroughId.length === 0) {
throw new factory.errors.ArgumentNull('acceptedOffer.itemOffered.pointAward.toLocation.issuedThrough.id');
}
// pointAwardの指定がある場合、Permitの存在確認
const permitService = yield createPermitService({ issuedThrough: { id: issuedThroughId } })(repos);
yield permitService.findByIdentifier({
project: { id: params.project.id },
identifier: permitIdentifier,
issuedThrough: { typeOf: factory.product.ProductType.PaymentCard }
});
}
});
}
function processLockOfferRateLimit(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
const rateLimitKeys = [];
params.reservations.forEach((reservation) => {
var _a, _b;
const scope = (_a = reservation.reservedTicket.ticketType.validRateLimit) === null || _a === void 0 ? void 0 : _a.scope;
const unitInSeconds = (_b = reservation.reservedTicket.ticketType.validRateLimit) === null || _b === void 0 ? void 0 : _b.unitInSeconds;
if (typeof scope === 'string' && typeof unitInSeconds === 'number') {
const rateLimitKey = {
project: { id: params.project.id },
reservedTicket: {
ticketType: {
validRateLimit: {
scope: scope,
unitInSeconds: unitInSeconds
}
}
},
reservationFor: {
startDate: (params.reservationFor.typeOf === factory.eventType.ScreeningEvent)
? moment(params.reservationFor.startDate)
.toDate()
: moment(params.reservationFor.departureTime)
.toDate()
},
reservationNumber: params.reservationNumber
};
rateLimitKeys.push(rateLimitKey);
}
});
if (rateLimitKeys.length > 0) {
if (rateLimitKeys.length > 1) {
throw new factory.errors.Argument('acceptedOffers', `Number of offers with rateLimit must be less than or equal to 1`);
}
yield repos.offerRateLimit.lock(rateLimitKeys[0]);
}
return rateLimitKeys;
});
}
/**
* 座席ロックプロセス
*/
function processLockSeats(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
const setting = yield repos.setting.findOne({ project: { id: { $eq: '*' } } }, ['storage']);
const stockHoldAfterEventEndInDays = (_a = setting === null || setting === void 0 ? void 0 : setting.storage) === null || _a === void 0 ? void 0 : _a.stockHoldAfterEventEndInDays;
if (typeof stockHoldAfterEventEndInDays !== 'number') {
throw new factory.errors.NotFound('setting.storage.stockHoldAfterEventEndInDays');
}
if (stockHoldAfterEventEndInDays <= 0) {
throw new factory.errors.Argument('setting.storage.stockHoldAfterEventEndInDays', 'must be > 0');
}
const offers = [];
params.reservations.forEach((r) => {
var _a, _b;
const seatSection = (_a = r.reservedTicket.ticketedSeat) === null || _a === void 0 ? void 0 : _a.seatSection;
const seatNumber = (_b = r.reservedTicket.ticketedSeat) === null || _b === void 0 ? void 0 : _b.seatNumber;
// 指定席のみの場合、ticketedSeatの存在は保証されている
if (typeof seatSection === 'string' && typeof seatNumber === 'string') {
// subReservationがあれば、そちらもロック
const subReservations = r.subReservation;
if (Array.isArray(subReservations)) {
subReservations.forEach((subReservation) => {
var _a, _b, _c, _d;
const seatSection4sub = (_b = (_a = subReservation.reservedTicket) === null || _a === void 0 ? void 0 : _a.ticketedSeat) === null || _b === void 0 ? void 0 : _b.seatSection;
const seatNumber4sub = (_d = (_c = subReservation.reservedTicket) === null || _c === void 0 ? void 0 : _c.ticketedSeat) === null || _d === void 0 ? void 0 : _d.seatNumber;
// 指定席のみの場合、ticketedSeatの存在は保証されている
if (typeof seatSection4sub !== 'string' || typeof seatNumber4sub !== 'string') {
throw new factory.errors.ArgumentNull('subReservation.reservedTicket.ticketedSeat');
}
offers.push({ seatSection: seatSection4sub, seatNumber: seatNumber4sub });
});
}
offers.push({ seatSection: seatSection, seatNumber: seatNumber });
}
else {
// 指定席でない場合、予約IDでロック
offers.push({
itemOffered: { serviceOutput: { id: r.id } },
seatSection: '',
seatNumber: ''
});
}
});
const expires = moment(params.event.endDate)
.add(stockHoldAfterEventEndInDays, 'days')
.toDate();
const holder = params.transaction.transactionNumber; // fix as transactionNumber(2024-07-02~)
const bookingTime = params.transaction.startDate; // fix as transactionNumber(2024-07-02~)
const hasTicketedSeat = ((_d = (_c = (_b = params.event.offers.itemOffered.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservedTicket) === null || _c === void 0 ? void 0 : _c.ticketedSeat) === null || _d === void 0 ? void 0 : _d.typeOf) === factory.placeType.Seat;
let maximumAttendeeCapacity4event = (_e = params.event.location) === null || _e === void 0 ? void 0 : _e.maximumAttendeeCapacity;
// 座席無の場合デフォルトmaximumAttendeeCapacityを適用(2025-04-20~)
if (!hasTicketedSeat) {
if (typeof maximumAttendeeCapacity4event !== 'number') {
maximumAttendeeCapacity4event = seat_1.DEFAULT_ROOM_MAXIMUM_CAPACITY;
}
}
if (typeof maximumAttendeeCapacity4event === 'number') {
yield repos.stockHolder.lockIfNotLimitExceeded({
project: { id: params.event.project.id },
provider: { id: params.event.organizer.id },
eventId: params.event.id,
startDate: moment(params.event.startDate)
.toDate(),
hasTicketedSeat,
offers,
expires,
holder,
bookingTime
}, maximumAttendeeCapacity4event);
}
else {
yield repos.stockHolder.lock({
project: { id: params.event.project.id },
provider: { id: params.event.organizer.id },
eventId: params.event.id,
startDate: moment(params.event.startDate)
.toDate(),
hasTicketedSeat,
offers,
expires,
holder,
bookingTime
});
}
});
}