@chevre/domain
Version:
Chevre Domain Library for Node.js
377 lines (376 loc) • 22.6 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAdditionalProperty = createAdditionalProperty;
exports.createAdditionalTicketText = createAdditionalTicketText;
exports.createReservation = createReservation;
exports.createReservedTicket = createReservedTicket;
exports.validateAppliesToMovieTicket = validateAppliesToMovieTicket;
const createDebug = require("debug");
const moment = require("moment");
const util = require("util");
const factory = require("../../../../../factory");
const price_1 = require("./price");
const debug = createDebug('chevre-domain:service:assetTransaction');
function createTicketIdentifier(params) {
var _a, _b, _c, _d;
// チケット識別子の規定値を作成
let ticketIdentifier = (typeof ((_a = params.ticketedSeat) === null || _a === void 0 ? void 0 : _a.seatNumber) === 'string')
? util.format('%s:%s:%s', params.reservationFor.id, params.ticketedSeat.seatSection, params.ticketedSeat.seatNumber)
: util.format('%s:%s', params.reservationFor.id, params.id);
// 指定があれば採用
const ticketIdentifierByRequest = (_d = (_c = (_b = params.acceptedOffer.itemOffered) === null || _b === void 0 ? void 0 : _b.serviceOutput) === null || _c === void 0 ? void 0 : _c.reservedTicket) === null || _d === void 0 ? void 0 : _d.identifier;
if (typeof ticketIdentifierByRequest === 'string' && ticketIdentifierByRequest.length > 0) {
ticketIdentifier = ticketIdentifierByRequest;
}
return ticketIdentifier;
}
function createReservedTicket(params) {
var _a, _b, _c;
let acceptedTicketedSeat;
const acceptedTicketedSeatByItemOffered = (_c = (_b = (_a = params.acceptedOffer.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;
const acceptedTicketedSeatNumber = acceptedTicketedSeatByItemOffered === null || acceptedTicketedSeatByItemOffered === void 0 ? void 0 : acceptedTicketedSeatByItemOffered.seatNumber;
if (typeof acceptedTicketedSeatNumber === 'string') {
acceptedTicketedSeat = acceptedTicketedSeatByItemOffered;
}
let ticketedSeat;
if (params.reservedSeatsOnly) {
// 指定席のみの場合、座席指定が必須
if (acceptedTicketedSeat === undefined) {
throw new factory.errors.ArgumentNull('ticketedSeat');
}
let seat;
let screeningRoomSection;
const seatSection = acceptedTicketedSeat.seatSection;
const seatNumber = acceptedTicketedSeat.seatNumber;
if (Array.isArray(params.screeningRoomSections)) {
screeningRoomSection = params.screeningRoomSections.find((section) => section.branchCode === seatSection);
if (screeningRoomSection === undefined) {
throw new factory.errors.NotFound(factory.placeType.ScreeningRoomSection, `${factory.placeType.ScreeningRoomSection} ${acceptedTicketedSeat.seatSection} not found`);
}
seat = screeningRoomSection.containsPlace.find((p) => p.branchCode === seatNumber);
}
if (Array.isArray(params.availableSeatOffers)) {
seat = params.availableSeatOffers.find((o) => { var _a; return o.branchCode === seatNumber && ((_a = o.containedInPlace) === null || _a === void 0 ? void 0 : _a.branchCode) === seatSection; });
}
if (seat === undefined) {
throw new factory.errors.NotFound(factory.placeType.Seat, `${factory.placeType.Seat} ${seatNumber} not found`);
}
validateDate({
availableOffer: params.availableOffer,
dateIssued: params.dateIssued
});
validateEligibleSeatingType({
availableOffer: params.availableOffer,
seat: seat
});
validateEligibleSubReservation({
seatSection,
availableOffer: params.availableOffer,
acceptedOffer: params.acceptedOffer,
screeningRoomSection: screeningRoomSection,
availableSeatOffers: params.availableSeatOffers
});
// 座席タイプをArrayに統一
let seatingType = seat.seatingType;
if (typeof seatingType === 'string') {
seatingType = [seatingType];
}
// 最適化する(2021-10-19~)
ticketedSeat = Object.assign({ typeOf: factory.placeType.Seat, seatNumber, seatRow: '', seatSection }, (Array.isArray(seatingType)) ? { seatingType } : undefined);
}
const ticketType = createTicketType({ availableOffer: params.availableOffer });
const issuedBy = createIssuedBy({ acceptedOffer: params.acceptedOffer, availableOffer: params.availableOffer });
const ticketIdentifier = createTicketIdentifier({
acceptedOffer: params.acceptedOffer,
id: params.id,
reservationFor: params.reservationFor,
ticketedSeat
});
return Object.assign({
// dateIssued: params.dateIssued, // discontinue(2024-12-03~)
identifier: ticketIdentifier, issuedBy,
ticketType, typeOf: 'Ticket' }, (ticketedSeat !== undefined) ? { ticketedSeat } : {});
}
/**
* 予約に最適化された単価オファーを作成する
*/
function createTicketType(params) {
var _a;
const availableOffer = params.availableOffer;
return Object.assign(Object.assign(Object.assign(Object.assign({ description: availableOffer.description, id: availableOffer.id, identifier: availableOffer.identifier, name: availableOffer.name,
// 不要なので廃止(2022-12-17~)
// priceCurrency: availableOffer.priceCurrency,
// priceSpecificationを最適化(accounting不要)
// accounting: { typeOf: "Accounting", … }
// 不要なので廃止(2022-12-17~)
// project: availableOffer.project,
typeOf: availableOffer.typeOf }, (Array.isArray(availableOffer.additionalProperty)) ? { additionalProperty: availableOffer.additionalProperty } : undefined), (typeof ((_a = availableOffer.category) === null || _a === void 0 ? void 0 : _a.codeValue) === 'string') ? { category: availableOffer.category } : undefined), (typeof availableOffer.color === 'string') ? { color: availableOffer.color } : undefined), (availableOffer.validRateLimit !== undefined) ? { validRateLimit: availableOffer.validRateLimit } : undefined);
}
function createIssuedBy(params) {
var _a, _b, _c, _d, _e, _f, _g, _h;
let typeOf = (_d = (_c = (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservedTicket) === null || _c === void 0 ? void 0 : _c.issuedBy) === null || _d === void 0 ? void 0 : _d.typeOf;
if (typeof typeOf !== 'string') {
typeOf = params.availableOffer.project.typeOf;
}
let name = (_h = (_g = (_f = (_e = params.acceptedOffer.itemOffered) === null || _e === void 0 ? void 0 : _e.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservedTicket) === null || _g === void 0 ? void 0 : _g.issuedBy) === null || _h === void 0 ? void 0 : _h.name;
if (typeof name !== 'string') {
name = params.availableOffer.project.id;
}
return { name, typeOf };
}
function validateDate(params) {
const dateIssued = moment(params.dateIssued);
if (params.availableOffer.validFrom instanceof Date) {
const validFrom = moment(params.availableOffer.validFrom);
if (dateIssued.isBefore(validFrom)) {
throw new factory.errors.Argument('acceptedOffer.id', `Offer ${params.availableOffer.id} is valid from ${validFrom.toISOString()}`);
}
}
if (params.availableOffer.validThrough instanceof Date) {
const validThrough = moment(params.availableOffer.validThrough);
if (dateIssued.isAfter(validThrough)) {
throw new factory.errors.Argument('acceptedOffer.id', `Offer ${params.availableOffer.id} is valid through ${validThrough.toISOString()}`);
}
}
}
function validateEligibleSeatingType(params) {
const seat = params.seat;
// 座席タイプ制約のあるオファーの場合、確認
// 座席の持つ座席タイプがどれかひとつeligibleSeatingTypesに含まれればよい
const eligibleSeatingTypes = params.availableOffer.eligibleSeatingType;
if (Array.isArray(eligibleSeatingTypes)) {
const seatingTypes = (Array.isArray(seat.seatingType)) ? seat.seatingType
: (typeof seat.seatingType === 'string') ? [seat.seatingType]
: [];
const isEligible = seatingTypes.some((seatingTypeCodeValue) => eligibleSeatingTypes.some((eligibleSeatingType) => eligibleSeatingType.codeValue === seatingTypeCodeValue));
if (!isEligible) {
throw new factory.errors.Argument('ticketedSeat', `${seat.branchCode} is not eligible for the offer ${params.availableOffer.id}`);
}
}
}
function validateEligibleSubReservation(params) {
var _a, _b;
const eligibleSubReservations = params.availableOffer.eligibleSubReservation;
// サブ予約条件が存在すればacceptedOfferが適切かどうか確認する
if (Array.isArray(eligibleSubReservations)) {
const subReservations = (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.subReservation;
if (!Array.isArray(subReservations)) {
throw new factory.errors.ArgumentNull('subReservation');
}
let seats4subReservation = [];
const screeningRoomSection = params.screeningRoomSection;
if (screeningRoomSection !== undefined) {
seats4subReservation = subReservations.map((subReservation) => {
var _a, _b;
const seatNumber4subReservation = (_b = (_a = subReservation.reservedTicket) === null || _a === void 0 ? void 0 : _a.ticketedSeat) === null || _b === void 0 ? void 0 : _b.seatNumber;
const seat4subReservation = screeningRoomSection.containsPlace.find((p) => p.branchCode === seatNumber4subReservation);
if (seat4subReservation === undefined) {
throw new factory.errors.NotFound(factory.placeType.Seat, `${factory.placeType.Seat} ${seatNumber4subReservation} not found`);
}
return seat4subReservation;
});
}
if (Array.isArray(params.availableSeatOffers)) {
seats4subReservation = subReservations.map((subReservation) => {
var _a, _b;
const seatNumber4subReservation = (_b = (_a = subReservation.reservedTicket) === null || _a === void 0 ? void 0 : _a.ticketedSeat) === null || _b === void 0 ? void 0 : _b.seatNumber;
const seat4subReservation = params.availableSeatOffers.find((p) => { var _a; return p.branchCode === seatNumber4subReservation && ((_a = p.containedInPlace) === null || _a === void 0 ? void 0 : _a.branchCode) === params.seatSection; });
if (seat4subReservation === undefined) {
throw new factory.errors.NotFound(factory.placeType.Seat, `${factory.placeType.Seat} ${seatNumber4subReservation} not found`);
}
return seat4subReservation;
});
}
const isEligible = eligibleSubReservations.some((eligibleSubReservation) => {
const includesEligilbeSeatingType = seats4subReservation.every((seat) => {
const seatingTypes = (Array.isArray(seat.seatingType)) ? seat.seatingType
: (typeof seat.seatingType === 'string') ? [seat.seatingType]
: [];
// 座席が条件の座席タイプを含むかどうか
return seatingTypes.includes(eligibleSubReservation.typeOfGood.seatingType);
});
// 座席数が条件に等しいかどうか
const includesEligibleAmount = seats4subReservation.length === eligibleSubReservation.amountOfThisGood;
return includesEligilbeSeatingType && includesEligibleAmount;
});
if (!isEligible) {
throw new factory.errors.Argument('subReservation', `${seats4subReservation.map((seat) => seat.branchCode)
.join(',')} is not eligible for the offer ${params.availableOffer.id}`);
}
}
}
function validateEligibleMembershipType(params) {
debug('validateEligibleMembershipType: validating...', JSON.stringify(params.programMembershipUsed), JSON.stringify(params.availableOffer.eligibleMembershipType));
const programMembershipUsed = params.programMembershipUsed;
// 使用メンバーシップがeligibleMembershipに含まれればよい
const eligibleMembershipType = params.availableOffer.eligibleMembershipType;
if (Array.isArray(eligibleMembershipType)) {
if ((programMembershipUsed === null || programMembershipUsed === void 0 ? void 0 : programMembershipUsed.typeOf) !== factory.programMembership.ProgramMembershipType.ProgramMembership) {
throw new factory.errors.Argument('programMembershipUsed', 'programMembership required');
}
const { identifier, issuedThrough } = programMembershipUsed;
if (typeof identifier !== 'string' || identifier === '') {
throw new factory.errors.Argument('programMembershipUsed', 'programMembership.identifier required');
}
// programMembershipUsed.issuedThrough.serviceTypeで検証する
const isEligible = eligibleMembershipType.some((membershipType) =>
// FaceToFaceについては問答無用に受け入れる(2024-08-14~)
issuedThrough.typeOf === factory.service.paymentService.PaymentServiceType.FaceToFace
|| membershipType.codeValue === issuedThrough.serviceType.codeValue);
if (!isEligible) {
throw new factory.errors.Argument('programMembershipUsed', `${programMembershipUsed.identifier} is not eligible for the offer ${params.availableOffer.id}`);
}
}
}
function validateAppliesToMovieTicket(params) {
var _a, _b;
// 複数決済カード指定対応(2022-08-01~)
let isAppliesToMovieTicketSpecifiedAsArray = false;
let appliesToMovieTicketAsArray;
if (Array.isArray(params.appliesToMovieTicket)) {
isAppliesToMovieTicketSpecifiedAsArray = true;
appliesToMovieTicketAsArray = params.appliesToMovieTicket;
}
else if (typeof ((_a = params.appliesToMovieTicket) === null || _a === void 0 ? void 0 : _a.identifier) === 'string') {
appliesToMovieTicketAsArray = [params.appliesToMovieTicket];
}
// 複数決済カード対応(2022-07-11~)
const priceSpecificationAppliesToMovieTicket = (_b = params.availableOffer.priceSpecification) === null || _b === void 0 ? void 0 : _b.appliesToMovieTicket;
if (Array.isArray(priceSpecificationAppliesToMovieTicket)) {
// ひとまず1以外は未実装(2022-07-11~)
// 決済カード指定数は1 or 2(2022-09-09~)
// tslint:disable-next-line:no-magic-numbers
if (priceSpecificationAppliesToMovieTicket.length < 1 || priceSpecificationAppliesToMovieTicket.length > 2) {
throw new factory.errors.NotImplemented(`${priceSpecificationAppliesToMovieTicket.length} appliesToMovieTicket not implemented`);
}
// 決済カード指定必須
if (!Array.isArray(appliesToMovieTicketAsArray) || appliesToMovieTicketAsArray.length === 0) {
throw new factory.errors.ArgumentNull('appliesToMovieTicket');
}
appliesToMovieTicketAsArray.forEach((eachAppliesToMovieTicket) => {
// identifierは指定されているか
if (typeof eachAppliesToMovieTicket.identifier !== 'string' || eachAppliesToMovieTicket.identifier.length === 0) {
throw new factory.errors.ArgumentNull('appliesToMovieTicket.identifier');
}
});
// 指定決済カードの数は適切か
if (appliesToMovieTicketAsArray.length !== priceSpecificationAppliesToMovieTicket.length) {
throw new factory.errors.Argument('appliesToMovieTicket', 'invalid number of appliesToMovieTicket');
}
// Array指定の場合、決済方法は適切か
if (isAppliesToMovieTicketSpecifiedAsArray) {
const paymentMethodTypesSpecified = appliesToMovieTicketAsArray.map((a) => { var _a; return String((_a = a.serviceOutput) === null || _a === void 0 ? void 0 : _a.typeOf); });
const paymentMethodTypesRequired = priceSpecificationAppliesToMovieTicket.map((a) => String(a.serviceOutput.typeOf));
if (paymentMethodTypesSpecified.length !== paymentMethodTypesRequired.length) {
throw new factory.errors.Argument('appliesToMovieTicket', 'invalid paymentMethodTypes');
}
// paymentMethodTypesSpecifiedはuniqueか
if (paymentMethodTypesSpecified.length !== [...new Set(paymentMethodTypesSpecified)].length) {
throw new factory.errors.Argument('appliesToMovieTicket', 'paymentMethodTypes must be unique');
}
// paymentMethodTypesRequiredはuniqueか
if (paymentMethodTypesRequired.length !== [...new Set(paymentMethodTypesRequired)].length) {
throw new factory.errors.NotImplemented('paymentMethodTypes of appliesToMovieTicket must be unique');
}
const everyPaymentMethodTypeSpecified = paymentMethodTypesRequired.every((paymentMethodType) => {
return paymentMethodTypesSpecified.includes(paymentMethodType);
});
if (!everyPaymentMethodTypeSpecified) {
throw new factory.errors.Argument('appliesToMovieTicket', 'every paymentMethodTypes required');
}
}
// Arrayでないケースは廃止(2022-09-10~)
}
}
/**
* 追加特性を生成する
*/
function createAdditionalProperty(params) {
var _a, _b;
let additionalProperty = (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.additionalProperty;
if (!Array.isArray(additionalProperty)) {
additionalProperty = [];
}
return additionalProperty;
}
/**
* 追加チケットテキストを生成する
*/
function createAdditionalTicketText(params) {
var _a, _b;
return (_b = (_a = params.acceptedOffer.itemOffered) === null || _a === void 0 ? void 0 : _a.serviceOutput) === null || _b === void 0 ? void 0 : _b.additionalTicketText;
}
// tslint:disable-next-line:cyclomatic-complexity max-func-body-length
function createReservation(params) {
var _a, _b;
// 適用メンバーシップ確認
validateEligibleMembershipType({
availableOffer: params.availableOffer,
programMembershipUsed: params.programMembershipUsed
});
// 適用MovieTicketのidentifier指定を必須化(2022-06-02~)
if (params.validateAppliesToMovieTicket) {
validateAppliesToMovieTicket({
availableOffer: params.availableOffer,
appliesToMovieTicket: params.appliesToMovieTicket
});
}
// priceを最適化
const price4reservation = (0, price_1.createPrice)(params);
if (params.reservationFor.typeOf === factory.eventType.ScreeningEvent) {
return Object.assign(Object.assign(Object.assign({
// project: params.project, // 廃止(2024-04-08~)
typeOf: factory.reservationType.EventReservation, id: params.id,
// reservationPackage保管に移行(2023-06-06~)
// issuedThrough,
additionalProperty: params.additionalProperty,
// bookingTime: params.reserveDate, // 廃止(2024-04-08~)
// modifiedTime: params.reserveDate, // 廃止(2024-04-08~)
numSeats: 1, price: price4reservation, priceCurrency: factory.priceCurrency.JPY,
// reservationNumber: params.reservationNumber, // 廃止(2024-04-08~)
// statusは不要なので削除(2023-07-19~)
// reservationStatus: factory.reservationStatusType.ReservationPending,
reservedTicket: params.reservedTicket }, (typeof params.additionalTicketText === 'string') ? { additionalTicketText: params.additionalTicketText } : undefined), (Array.isArray(params.subReservation))
? {
subReservation: params.subReservation.map((r) => {
return {
reservedTicket: {
ticketedSeat: r.reservedTicket.ticketedSeat,
typeOf: 'Ticket'
}
};
})
}
: undefined), (typeof ((_a = params.programMembershipUsed) === null || _a === void 0 ? void 0 : _a.identifier) === 'string')
? { programMembershipUsed: params.programMembershipUsed }
: undefined);
}
else {
return Object.assign(Object.assign(Object.assign({
// project: params.project,
typeOf: factory.reservationType.BusReservation, id: params.id,
// reservationPackage保管に移行(2023-06-06~)
// issuedThrough,
additionalProperty: params.additionalProperty,
// bookingTime: params.reserveDate,
// modifiedTime: params.reserveDate,
numSeats: 1, price: price4reservation, priceCurrency: factory.priceCurrency.JPY,
// reservationNumber: params.reservationNumber,
// statusは不要なので削除(2023-07-19~)
// reservationStatus: factory.reservationStatusType.ReservationPending,
reservedTicket: params.reservedTicket }, (typeof params.additionalTicketText === 'string') ? { additionalTicketText: params.additionalTicketText } : undefined), (Array.isArray(params.subReservation))
? {
subReservation: params.subReservation.map((r) => {
return {
reservedTicket: {
ticketedSeat: r.reservedTicket.ticketedSeat,
typeOf: 'Ticket'
}
};
})
}
: undefined), (typeof ((_b = params.programMembershipUsed) === null || _b === void 0 ? void 0 : _b.identifier) === 'string')
? { programMembershipUsed: params.programMembershipUsed }
: undefined);
}
}
;