UNPKG

@chevre/domain

Version:

Chevre Domain Library for Node.js

389 lines (388 loc) 21.3 kB
"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.validateAcceptedOffers = validateAcceptedOffers; const factory = require("../../../../factory"); function createAppliesToMovieTicket(params) { const isMvtkOrMG = typeof params.ticketInfo.mvtkNum === 'string' && params.ticketInfo.mvtkNum.length > 0; let movieTicketTypeChargePriceSpec; let appliesToMovieTicket; if (isMvtkOrMG) { // kbnMgtkから動的にavailablePaymentMethodを設定 let kbnMgtk = params.ticketInfo.kbnMgtk; if (typeof kbnMgtk !== 'string') { kbnMgtk = ''; } const availablePaymentMethodType = params.availablePaymentMethodTypes.find((categoryCode) => { var _a, _b; return ((_b = (_a = categoryCode.additionalProperty) === null || _a === void 0 ? void 0 : _a.find((property) => property.name === 'kbnMgtk')) === null || _b === void 0 ? void 0 : _b.value) === kbnMgtk; }); if (availablePaymentMethodType === undefined) { throw new factory.errors.Argument('offer', `available payment method type not found for kbnMgtk: ${kbnMgtk}`); } const availablePaymentMethod = availablePaymentMethodType.codeValue; movieTicketTypeChargePriceSpec = { typeOf: factory.priceSpecificationType.MovieTicketTypeChargeSpecification, name: { ja: params.ticketInfo.ticketName, en: params.ticketInfo.ticketNameEng }, price: params.ticketInfo.addPrice, priceCurrency: factory.priceCurrency.JPY, valueAddedTaxIncluded: true, appliesToMovieTicket: { typeOf: factory.service.paymentService.PaymentServiceType.MovieTicket, serviceType: params.ticketInfo.mvtkKbnKensyu, serviceOutput: { typeOf: availablePaymentMethod } }, appliesToVideoFormat: params.appliesToVideoFormat }; appliesToMovieTicket = { typeOf: factory.service.paymentService.PaymentServiceType.MovieTicket, identifier: params.ticketInfo.mvtkNum, serviceType: params.ticketInfo.mvtkKbnKensyu, serviceOutput: { typeOf: availablePaymentMethod } }; } return { movieTicketTypeChargePriceSpec, appliesToMovieTicket }; } // tslint:disable-next-line:cyclomatic-complexity max-func-body-length function createPriceComponent(params) { var _a, _b, _c, _d, _e, _f, _g, _h; const acceptedOffer = params.acceptedOffer; const availableUnitPriceOffer = params.availableUnitPriceOffer; const kbnJoueihousiki = (_a = params.screeningEvent.superEvent.coaInfo) === null || _a === void 0 ? void 0 : _a.kbnJoueihousiki; const appliesToVideoFormat = (typeof (kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunCode) === 'string') ? kbnJoueihousiki.kubunCode : 'Default'; const { name, ticketInfo } = acceptedOffer; // appliesToMovieTicket.serviceOutput.typeOfを自動補完(2023-03-13~) const { appliesToMovieTicket, movieTicketTypeChargePriceSpec } = createAppliesToMovieTicket({ ticketInfo, availablePaymentMethodTypes: params.availablePaymentMethodTypes, appliesToVideoFormat }); let surfrockChargePriceSpec; let appliesToMovieTicket4surfrock; // let eligibleMonetaryAmount: [factory.offer.IEligibleMonetaryAmount] | undefined; // appliesToSurfrockの指定があれば強制的にMovieTicket決済 const appliesToSurfrockByUnitPriceOffer = (_b = availableUnitPriceOffer.priceSpecification.appliesToMovieTicket) === null || _b === void 0 ? void 0 : _b.at(0); const surfrockIdentifier = (_d = (_c = acceptedOffer.priceSpecification) === null || _c === void 0 ? void 0 : _c.appliesToSurfrock) === null || _d === void 0 ? void 0 : _d.identifier; const surfrockPaymentMethodType = (_g = (_f = (_e = acceptedOffer.priceSpecification) === null || _e === void 0 ? void 0 : _e.appliesToSurfrock) === null || _f === void 0 ? void 0 : _f.serviceOutput) === null || _g === void 0 ? void 0 : _g.typeOf; if (typeof surfrockIdentifier === 'string' && surfrockIdentifier.length > 0 && typeof surfrockPaymentMethodType === 'string' && surfrockPaymentMethodType.length > 0) { const paymentMethodTypeByUnitPriceOffer = appliesToSurfrockByUnitPriceOffer === null || appliesToSurfrockByUnitPriceOffer === void 0 ? void 0 : appliesToSurfrockByUnitPriceOffer.serviceOutput.typeOf; if (typeof paymentMethodTypeByUnitPriceOffer === 'string') { if (paymentMethodTypeByUnitPriceOffer !== surfrockPaymentMethodType) { throw new factory.errors.Argument(`priceSpecification.appliesToSurfrock.serviceOutput.typeOf must be ${paymentMethodTypeByUnitPriceOffer}`); } } surfrockChargePriceSpec = { appliesToMovieTicket: { typeOf: factory.service.paymentService.PaymentServiceType.MovieTicket, serviceOutput: { typeOf: surfrockPaymentMethodType }, serviceType: ticketInfo.ticketCode // serviceTypeはticketCode }, appliesToVideoFormat, name, price: 0, // 加算料金は必ず0 priceCurrency: factory.priceCurrency.JPY, typeOf: factory.priceSpecificationType.MovieTicketTypeChargeSpecification, valueAddedTaxIncluded: true }; appliesToMovieTicket4surfrock = { typeOf: factory.service.paymentService.PaymentServiceType.MovieTicket, identifier: surfrockIdentifier, serviceOutput: { typeOf: surfrockPaymentMethodType }, serviceType: ticketInfo.ticketCode // serviceTypeはticketCode }; } else { // discontinue eligibleMonetaryAmount(2025-01-03~) // appliesToSurfrockの指定がなければ単価オファーの適用通貨条件を強制適用 // if (Array.isArray(availableUnitPriceOffer.eligibleMonetaryAmount)) { // eligibleMonetaryAmount = availableUnitPriceOffer.eligibleMonetaryAmount; // } if (typeof (appliesToSurfrockByUnitPriceOffer === null || appliesToSurfrockByUnitPriceOffer === void 0 ? void 0 : appliesToSurfrockByUnitPriceOffer.serviceType) === 'string') { throw new factory.errors.ArgumentNull('priceSpecification.appliesToSurfrock'); } } const { disPrice, limitCount, stdPrice } = ticketInfo; if (typeof stdPrice !== 'number') { throw new factory.errors.Argument('ticketInfo.stdPrice', 'must be number'); } const accountsReceivable = (ticketInfo.mvtkAppPrice > 0) ? ticketInfo.mvtkAppPrice : stdPrice; // const maxPrice: number = stdPrice; let price = stdPrice; // support disPrice(2024-09-02~) if (typeof disPrice === 'number' && disPrice > 0) { price -= disPrice; } let referenceQuantity = { typeOf: 'QuantitativeValue', unitCode: factory.unitCode.C62, value: 1 }; switch (ticketInfo.limitUnit) { case '001': referenceQuantity = { typeOf: 'QuantitativeValue', unitCode: factory.unitCode.C62, value: Number(limitCount) }; price = Number(limitCount) * price; break; case '002': referenceQuantity = { typeOf: 'QuantitativeValue', unitCode: factory.unitCode.C62, value: 1, minValue: Number(limitCount) }; break; default: // no op // referenceQuantity.value = 1; } const unitPriceSpec = Object.assign({ typeOf: factory.priceSpecificationType.UnitPriceSpecification, name: { ja: ticketInfo.ticketName, en: ticketInfo.ticketNameEng }, price, priceCurrency: factory.priceCurrency.JPY, referenceQuantity, valueAddedTaxIncluded: true, accounting: { typeOf: 'Accounting', accountsReceivable } }, (appliesToMovieTicket !== undefined || appliesToMovieTicket4surfrock !== undefined) ? { appliesToMovieTicket: [ ...(appliesToMovieTicket !== undefined) ? [appliesToMovieTicket] : [], ...(appliesToMovieTicket4surfrock !== undefined) ? [appliesToMovieTicket4surfrock] : [] ] } : undefined); // 区分加算料金 const categoryCodeChargeSpecs = []; // movieTicketTypeChargePriceSpecにaddPriceが含まれる場合は除く if (movieTicketTypeChargePriceSpec === undefined) { if (ticketInfo.addPrice > 0) { const videoFormatTypeCharge = (typeof (kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunAddPrice) === 'number') ? kbnJoueihousiki.kubunAddPrice : 0; const kbnAcoustic = (_h = params.screeningEvent.coaInfo) === null || _h === void 0 ? void 0 : _h.kbnAcoustic; const soundFormatTypeCharge = (typeof (kbnAcoustic === null || kbnAcoustic === void 0 ? void 0 : kbnAcoustic.kubunAddPrice) === 'number') ? kbnAcoustic.kubunAddPrice : 0; // 上映方式区分加算料金と音響区分加算料金を考慮する if (videoFormatTypeCharge > 0) { categoryCodeChargeSpecs.push({ name: { en: (typeof (kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunNameEng) === 'string') ? kbnJoueihousiki.kubunNameEng : String(kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunCode), ja: (typeof (kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunName) === 'string') ? `${kbnJoueihousiki.kubunName}加算料金` : '加算単価' }, price: videoFormatTypeCharge, priceCurrency: factory.priceCurrency.JPY, typeOf: factory.priceSpecificationType.CategoryCodeChargeSpecification, appliesToCategoryCode: [{ typeOf: 'CategoryCode', codeValue: String(kbnJoueihousiki === null || kbnJoueihousiki === void 0 ? void 0 : kbnJoueihousiki.kubunCode), inCodeSet: { typeOf: 'CategoryCodeSet', identifier: factory.categoryCode.CategorySetIdentifier.VideoFormatType } }], valueAddedTaxIncluded: true }); } if (soundFormatTypeCharge > 0) { categoryCodeChargeSpecs.push({ name: { en: (typeof (kbnAcoustic === null || kbnAcoustic === void 0 ? void 0 : kbnAcoustic.kubunNameEng) === 'string') ? kbnAcoustic.kubunNameEng : String(kbnAcoustic === null || kbnAcoustic === void 0 ? void 0 : kbnAcoustic.kubunCode), ja: (typeof (kbnAcoustic === null || kbnAcoustic === void 0 ? void 0 : kbnAcoustic.kubunName) === 'string') ? `${kbnAcoustic.kubunName}加算料金` : '加算単価' }, price: soundFormatTypeCharge, priceCurrency: factory.priceCurrency.JPY, typeOf: factory.priceSpecificationType.CategoryCodeChargeSpecification, appliesToCategoryCode: [{ typeOf: 'CategoryCode', codeValue: String(kbnAcoustic === null || kbnAcoustic === void 0 ? void 0 : kbnAcoustic.kubunCode), inCodeSet: { typeOf: 'CategoryCodeSet', identifier: factory.categoryCode.CategorySetIdentifier.SoundFormatType } }], valueAddedTaxIncluded: true }); } } } if (ticketInfo.spseatAdd1 > 0) { const existingSeatingType = params.seatingTypes.find((seatingType) => seatingType.codeValue === ticketInfo.spseatKbn); categoryCodeChargeSpecs.push({ name: { en: (typeof (existingSeatingType === null || existingSeatingType === void 0 ? void 0 : existingSeatingType.name.en) === 'string') ? `${existingSeatingType.name.en}` : ticketInfo.spseatKbn, ja: (typeof (existingSeatingType === null || existingSeatingType === void 0 ? void 0 : existingSeatingType.name.ja) === 'string') ? `${existingSeatingType.name.ja}加算料金` : '特別席加算額' }, price: ticketInfo.spseatAdd1, priceCurrency: factory.priceCurrency.JPY, typeOf: factory.priceSpecificationType.CategoryCodeChargeSpecification, appliesToCategoryCode: [{ // project: { id: params.project.id, typeOf: factory.organizationType.Project }, typeOf: 'CategoryCode', codeValue: ticketInfo.spseatKbn, inCodeSet: { typeOf: 'CategoryCodeSet', identifier: factory.categoryCode.CategorySetIdentifier.SeatingType } }], valueAddedTaxIncluded: true }); } // アドオン単価 const addOnUnitPriceSpecs = []; if (ticketInfo.spseatAdd2 > 0) { addOnUnitPriceSpecs.push({ typeOf: factory.priceSpecificationType.UnitPriceSpecification, name: { ja: 'ミールクーポン', en: 'Meal Coupon' }, price: ticketInfo.spseatAdd2, priceCurrency: factory.priceCurrency.JPY, referenceQuantity: { typeOf: 'QuantitativeValue', unitCode: factory.unitCode.C62, value: 1 }, valueAddedTaxIncluded: true, appliesToAddOn: [{ typeOf: factory.offerType.Offer, // id?: string; // identifier?: string; itemOffered: { // id: '', name: { ja: 'ミールクーポン', en: 'Meal Coupon' }, productID: '', typeOf: factory.product.ProductType.Product } }] }); } if (ticketInfo.addGlasses > 0) { addOnUnitPriceSpecs.push({ typeOf: factory.priceSpecificationType.UnitPriceSpecification, name: { ja: 'メガネ', en: 'Glasses' }, price: Number(ticketInfo.addGlasses), priceCurrency: factory.priceCurrency.JPY, referenceQuantity: { typeOf: 'QuantitativeValue', unitCode: factory.unitCode.C62, value: 1 }, valueAddedTaxIncluded: true, appliesToAddOn: [{ typeOf: factory.offerType.Offer, // id?: string; // identifier?: string; itemOffered: { // id: '', name: { ja: 'メガネ', en: 'Glasses' }, productID: '', typeOf: factory.product.ProductType.Product } }] }); } const priceComponent = [ unitPriceSpec, ...(movieTicketTypeChargePriceSpec !== undefined) ? [movieTicketTypeChargePriceSpec] : [], ...(surfrockChargePriceSpec !== undefined) ? [surfrockChargePriceSpec] : [], ...categoryCodeChargeSpecs, ...addOnUnitPriceSpecs ]; return { priceComponent }; } /** * 受け入れらたオファーの内容を検証 */ // tslint:disable-next-line:max-func-body-length function validateAcceptedOffers(params) { // tslint:disable-next-line:max-func-body-length return (repos) => __awaiter(this, void 0, void 0, function* () { var _a; const theaterCode = String((_a = params.screeningEvent.coaInfo) === null || _a === void 0 ? void 0 : _a.theaterCode); const offerIdentifiers = (Array.isArray(params.object.acceptedOffer)) ? [...new Set((params.object.acceptedOffer).map((o) => { return `COA-${theaterCode}-${String(o.ticketInfo.ticketCode)}`; }))] : []; let availableUnitPriceOffers = []; // 指定された単価オファーを検索 // ticketCodeで検索(2023-03-22~) if (offerIdentifiers.length > 0) { availableUnitPriceOffers = yield repos.offer.search({ identifier: { $in: offerIdentifiers }, project: { id: { $eq: params.project.id } } }); } const acceptedOffers = params.object.acceptedOffer.map((acceptedOffer) => { var _a, _b; const availableUnitPriceOffer = availableUnitPriceOffers.find((unitPriceOffer) => { var _a, _b; const ticketCodeByUnitPriceOffer = (_b = (_a = unitPriceOffer.additionalProperty) === null || _a === void 0 ? void 0 : _a.find((p) => p.name === 'ticketCode')) === null || _b === void 0 ? void 0 : _b.value; return ticketCodeByUnitPriceOffer === acceptedOffer.ticketInfo.ticketCode; }); if (availableUnitPriceOffer === undefined) { throw new factory.errors.NotFound(factory.offerType.Offer, `${acceptedOffer.ticketInfo.ticketCode} not found`); } const { additionalProperty, itemOffered, name, ticketInfo } = acceptedOffer; // priceComponentを再生成(2023-03-14~) const { priceComponent } = createPriceComponent({ project: { id: params.project.id }, availablePaymentMethodTypes: params.availablePaymentMethodTypes, seatingTypes: params.seatingTypes, videoFormatTypes: params.videoFormatTypes, acceptedOffer, availableUnitPriceOffer, screeningEvent: params.screeningEvent }); const priceSpecification = { typeOf: factory.priceSpecificationType.CompoundPriceSpecification, priceCurrency: factory.priceCurrency.JPY, priceComponent, valueAddedTaxIncluded: true }; // 実際の発生金額を算出 const price = [ ticketInfo.salesTicketSalePrice, ticketInfo.addGlasses, ticketInfo.spseatAdd1, ticketInfo.spseatAdd2 ].reduce((a, b) => a + b, 0); // COAに渡す販売金額については、特別席加算額は興収部分のみ加算 const salePrice = [ ticketInfo.salesTicketSalePrice, ticketInfo.addGlasses, ticketInfo.spseatAdd1 ].reduce((a, b) => a + b, 0); const usePointValue = (_b = (_a = availableUnitPriceOffer.additionalProperty) === null || _a === void 0 ? void 0 : _a.find((p) => p.name === 'usePoint')) === null || _b === void 0 ? void 0 : _b.value; return Object.assign({ additionalProperty, itemOffered, name, price, priceSpecification, ticketInfo: Object.assign(Object.assign({}, ticketInfo), { // usePointを自動設定(2023-03-22~) usePoint: (typeof usePointValue === 'string') ? Number(usePointValue) : 0, salePrice // COAに渡す販売金額を上書き(2023-03-20~) }), // 以下属性については単価オファーから読む(2023-03-09~) priceCurrency: availableUnitPriceOffer.priceCurrency, id: availableUnitPriceOffer.id, identifier: availableUnitPriceOffer.identifier, typeOf: availableUnitPriceOffer.typeOf }, { // discontinue(2025-01-03~) // seatNumber: itemOffered.serviceOutput?.reservedTicket?.ticketedSeat?.seatNumber, // discontinue(2025-01-03~) // seatSection: itemOffered.serviceOutput?.reservedTicket?.ticketedSeat?.seatSection }); }); return { acceptedOffers }; }); }