@chevre/domain
Version:
Chevre Domain Library for Node.js
239 lines (238 loc) • 12.6 kB
JavaScript
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.searchOffersByIds = searchOffersByIds;
const createDebug = require("debug");
const factory = require("../../../factory");
const factory_1 = require("../factory");
const checkAvailability_1 = require("./checkAvailability");
const searchPriceSpecs4event_1 = require("./searchPriceSpecs4event");
const debug = createDebug('chevre-domain:service:offer');
// tslint:disable-next-line:max-func-body-length
function searchTicketOffersByItemOffered(params) {
// tslint:disable-next-line:max-func-body-length
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d;
const eventService = (yield repos.product.projectFields({
limit: 1,
page: 1,
id: { $eq: String((_a = params.itemOffered) === null || _a === void 0 ? void 0 : _a.id) }
}, ['hasOfferCatalog', 'project']
// []
)).shift();
if (eventService === undefined) {
throw new factory.errors.NotFound(factory.product.ProductType.EventService);
}
const offerCatalogItemsOfProduct = (_b = eventService.hasOfferCatalog) === null || _b === void 0 ? void 0 : _b.itemListElement;
/**
* プロダクトのカタログIDリスト
*/
const catalogIdsOfProduct = (Array.isArray(offerCatalogItemsOfProduct)) ? offerCatalogItemsOfProduct.map(({ id }) => id) : [];
/**
* プロダクトのひとつめのカタログID
*/
const firstCatalogIdOfProduct = catalogIdsOfProduct.at(0);
if (typeof firstCatalogIdOfProduct !== 'string') {
throw new factory.errors.NotFound('itemOffered.hasOfferCatalog');
}
/**
* カタログID or サブカタログID
*/
let subOfferCatalogId = firstCatalogIdOfProduct;
let isOfferCatalogItem = false;
const offerCatalogFirstElement = yield repos.offerCatalog.findFirstItemListElementById({ id: firstCatalogIdOfProduct });
if (offerCatalogFirstElement.typeOf === 'OfferCatalog') {
subOfferCatalogId = offerCatalogFirstElement.id;
isOfferCatalogItem = true;
}
// id指定必須(2023-09-13~)
if (!Array.isArray(params.ids)) {
throw new factory.errors.ArgumentNull('ids', 'ids must be specified');
}
/**
* オファーの含まれるカタログIDリスト
*/
let includedInDataCatalogIds = [subOfferCatalogId];
if (isOfferCatalogItem) {
// 複数カタログ対応(2023-09-27~)
const offerCatalogItems = yield repos.offerCatalog.findItemListElementById({
id: firstCatalogIdOfProduct,
project: { id: eventService.project.id }
});
includedInDataCatalogIds = offerCatalogItems.itemListElement.map((element) => element.id);
}
// includedInDataCatalogIdsを明示的に指定可能にする(2024-10-01~)
let includedInDataCatalogIdsSpecified = (_c = params.options.includedInDataCatalog) === null || _c === void 0 ? void 0 : _c.id;
if (Array.isArray(includedInDataCatalogIdsSpecified)) {
includedInDataCatalogIdsSpecified = [...new Set(includedInDataCatalogIdsSpecified)]; // unique
if (isOfferCatalogItem) {
// プロダクトのカタログに含まれるサブカタログにフィルター
const includedInDataCatalogIdsSpecifiedInOfferCatalog = yield repos.offerCatalog.searchItemListElement({
id: { $in: catalogIdsOfProduct },
itemListElement: { id: { $in: includedInDataCatalogIdsSpecified } }
});
if (includedInDataCatalogIdsSpecifiedInOfferCatalog.length !== includedInDataCatalogIdsSpecified.length) {
throw new factory.errors.Argument('includedInDataCatalog.id', 'specified sub catalog not found in product.hasOfferCatalog');
}
includedInDataCatalogIds = includedInDataCatalogIdsSpecified;
}
else {
// サブカタログでない場合は全てプロダクトのひとつめのカタログIDに一致するはず(現状プロダクトのカタログ数が1の前提なので)
const everySpecifiedCatalogIdsValid = includedInDataCatalogIdsSpecified.every((id) => id === subOfferCatalogId);
if (!everySpecifiedCatalogIdsValid) {
throw new factory.errors.Argument('includedInDataCatalog.id', 'invalid offerCatalog');
}
}
}
debug('searchOffersByIds:', 'searchAllByIdsAndOfferCatalogId processing...', eventService.project.id, params.ids.join(','), includedInDataCatalogIds.join(','));
const availableOffers = yield repos.offer.searchAllByIdsAndOfferCatalogId({
ids: params.ids,
includedInDataCatalog: { id: includedInDataCatalogIds, isOfferCatalogItem },
availableAtOrFrom: { id: (_d = params.store) === null || _d === void 0 ? void 0 : _d.id },
unacceptedPaymentMethod: params.unacceptedPaymentMethod,
excludeAppliesToMovieTicket: params.excludeAppliesToMovieTicket,
onlyValid: true
});
return { availableOffers };
});
}
/**
* イベントから興行(旅客)オファーを検索する
*/
function searchEventTicketOffersByEvent(params) {
// tslint:disable-next-line:max-func-body-length
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a;
const event = params.event;
let soundFormatTypes = [];
let videoFormatTypes = [];
if (event.typeOf === factory.eventType.ScreeningEvent) {
const superEvents = yield repos.eventSeries.projectEventSeriesFields({
limit: 1,
page: 1,
id: { $eq: event.superEvent.id }
// typeOf: factory.eventType.ScreeningEventSeries
}, ['soundFormat', 'videoFormat']);
const superEvent = superEvents.shift();
if (superEvent === undefined) {
throw new factory.errors.NotFound(factory.eventType.ScreeningEventSeries);
}
soundFormatTypes = (Array.isArray(superEvent.soundFormat)) ? superEvent.soundFormat.map((f) => f.typeOf) : [];
videoFormatTypes = (Array.isArray(superEvent.videoFormat)) ? superEvent.videoFormat.map((f) => f.typeOf) : [];
}
const unacceptedPaymentMethod = getUnacceptedPaymentMethodByEvent({ event });
// 上映方式がなければMovieTicket除外(2023-02-21~)
const excludeAppliesToMovieTicket = videoFormatTypes.length === 0;
// 興行設定があれば興行のカタログを参照する(2022-08-31~)
const eventOffers = event.offers;
const { availableOffers } = yield searchTicketOffersByItemOffered({
itemOffered: { id: String((_a = eventOffers === null || eventOffers === void 0 ? void 0 : eventOffers.itemOffered) === null || _a === void 0 ? void 0 : _a.id) },
ids: params.ids,
store: params.store,
// limit: params.limit,
// page: params.page,
// onlyValid: params.onlyValid,
// includedInDataCatalog: params.includedInDataCatalog,
unacceptedPaymentMethod,
excludeAppliesToMovieTicket,
options: params.options
// priceSpecification: params.priceSpecification
// withSortIndex: params.addSortIndex,
// useIncludeInDataCatalog: params.useIncludeInDataCatalog
})(repos);
const { soundFormatChargeSpecs, videoFormatChargeSpecs, movieTicketTypeChargeSpecs } = yield (0, searchPriceSpecs4event_1.searchPriceSpecs4event)({
project: { id: event.project.id },
soundFormatTypes,
videoFormatTypes,
availableOffers
})(repos);
const offers4event = [];
// 単価オファーから興行オファーを生成(順に処理)
for (const availableOffer of availableOffers) {
let availability;
if (params.validateOfferRateLimit) {
// レート制限を確認
availability = yield (0, checkAvailability_1.checkAvailability)({ event, unitPriceOffer: availableOffer })(repos);
}
offers4event.push((0, factory_1.createCompoundPriceSpec4event)({
eligibleQuantity: eventOffers.eligibleQuantity,
offer: availableOffer,
videoFormatChargeSpecs,
soundFormatChargeSpecs,
movieTicketTypeChargeSpecs,
videoFormatTypes,
availability,
addOn: (Array.isArray(availableOffer.addOn)) ? availableOffer.addOn : [],
includePotentialPriceComponent: false
// sortIndex // ソートindex不要
}));
}
return {
ticketOffers: offers4event,
unitPriceOffers: availableOffers
};
});
}
function getUnacceptedPaymentMethodByEvent(params) {
var _a;
let unacceptedPaymentMethod = [];
const unacceptedPaymentMethodByEvent = (_a = params.event.offers) === null || _a === void 0 ? void 0 : _a.unacceptedPaymentMethod;
// 施設コンテンツを参照する必要はない(2022-10-31~)
if (Array.isArray(unacceptedPaymentMethodByEvent)) {
unacceptedPaymentMethod = unacceptedPaymentMethodByEvent;
}
return unacceptedPaymentMethod;
}
/**
* 興行オファー承認時にオファーID指定で利用可能オファーを検索する
* パラメータ最適化(2024-09-30~)
*/
function searchOffersByIds(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
const eventType = params.event.typeOf;
// optimize projection(2024-07-17~)
const event = yield repos.event.projectEventFieldsById({ id: params.event.id }, [
'project', 'typeOf', 'startDate',
'superEvent.id',
'offers.itemOffered.id', 'offers.offeredThrough', 'offers.unacceptedPaymentMethod', 'offers.eligibleQuantity'
]);
let offers;
let unitPriceOffers;
const eventOffers = event.offers;
if (eventOffers === undefined) {
throw new factory.errors.NotFound('EventOffers', 'Event offers undefined');
}
if (eventOffers.offeredThrough === undefined) {
eventOffers.offeredThrough = { typeOf: 'WebAPI', identifier: factory.service.webAPI.Identifier.Chevre };
}
switch (eventOffers.offeredThrough.identifier) {
case factory.service.webAPI.Identifier.COA:
throw new factory.errors.NotImplemented(`booking service '${eventOffers.offeredThrough.identifier}' not implemented`);
default:
const searchOffersResult = yield searchEventTicketOffersByEvent({
ids: params.ids,
event,
store: params.store,
// priceSpecification: params.priceSpecification,
// includedInDataCatalog: params.includedInDataCatalog,
// limit: params.limit,
// page: params.page,
validateOfferRateLimit: true,
options: params.options
// onlyValid: params.onlyValid === true,
// useIncludeInDataCatalog: params.useIncludeInDataCatalog
})(repos);
offers = searchOffersResult.ticketOffers;
unitPriceOffers = searchOffersResult.unitPriceOffers;
}
return { ticketOffers: offers, unitPriceOffers };
});
}
;