@chevre/domain 21.2.0-alpha.63 → 21.2.0-alpha.65

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.
@@ -1,5 +1,5 @@
1
1
  // tslint:disable:no-console
2
- import * as moment from 'moment';
2
+ // import * as moment from 'moment';
3
3
  import * as mongoose from 'mongoose';
4
4
 
5
5
  import { chevre } from '../../../lib/index';
@@ -4,6 +4,7 @@ import * as mongoose from 'mongoose';
4
4
  import { chevre } from '../../../lib/index';
5
5
 
6
6
  // const project = { id: String(process.env.PROJECT_ID) };
7
+ const orderNumbers = ['TTT9-4703865-8892744', 'TTT9-4703865-8398074', 'SSK6-4815238-3010844'];
7
8
 
8
9
  async function main() {
9
10
  await mongoose.connect(<string>process.env.MONGOLAB_URI);
@@ -11,10 +12,45 @@ async function main() {
11
12
  const orderRepo = new chevre.repository.Order(mongoose.connection);
12
13
 
13
14
  const reservatioForIds = await orderRepo.searchReservationForIdsByOrderNumbers({
14
- orderNumber: { $in: ['TTT9-4703865-8892744', 'TTT9-4703865-8398074', 'SSK9-4703865-4744524'] }
15
+ orderNumber: { $in: orderNumbers }
15
16
  });
16
17
  console.log('reservatioForIds found', reservatioForIds);
17
18
  console.log(reservatioForIds.length, 'reservatioForIds found');
19
+
20
+ const reservationNumbers = await orderRepo.searchReservationNumbersByOrderNumbers({
21
+ orderNumber: { $in: orderNumbers }
22
+ });
23
+ console.log('reservationNumbers found', reservationNumbers);
24
+ console.log(reservationNumbers.length, 'reservationNumbers found');
25
+
26
+ const offers = await orderRepo.searchAcceptedOffersByOrderNumbers({
27
+ orderNumber: { $in: orderNumbers }
28
+ });
29
+ console.log('offers found', offers);
30
+ console.log(offers.length, 'offers found');
31
+
32
+ const movieTickets: any[] = [];
33
+ offers.forEach((offer) => {
34
+ const movieTicketTypeChargeSpecExists = offer.priceSpecification.priceComponent.some((component) => {
35
+ return component.typeOf === chevre.factory.priceSpecificationType.MovieTicketTypeChargeSpecification;
36
+ });
37
+ if (movieTicketTypeChargeSpecExists) {
38
+ offer.priceSpecification.priceComponent.forEach((component) => {
39
+ if (component.typeOf === chevre.factory.priceSpecificationType.UnitPriceSpecification) {
40
+ if (Array.isArray(component.appliesToMovieTicket)) {
41
+ component.appliesToMovieTicket.forEach((appliesToMovieTicket) => {
42
+ movieTickets.push({
43
+ identifier: appliesToMovieTicket.identifier,
44
+ paymentMethodType: appliesToMovieTicket.serviceOutput.typeOf,
45
+ offerId: offer.id
46
+ });
47
+ });
48
+ }
49
+ }
50
+ });
51
+ }
52
+ });
53
+ console.log('movieTickets found', movieTickets);
18
54
  }
19
55
 
20
56
  main()
@@ -0,0 +1,24 @@
1
+ // tslint:disable:no-console
2
+ import * as moment from 'moment-timezone';
3
+
4
+ const startDate = moment('2023-05-24T16:00:00Z')
5
+ .toDate();
6
+ const gracePeriodBeforeStartInDaysMin = {
7
+ timezone: 'Asia/Tokyo',
8
+ time: '18:00:00',
9
+ period: { value: 2 }
10
+ };
11
+ const returningDate = new Date();
12
+
13
+ const minDate: string = moment(startDate)
14
+ .tz(gracePeriodBeforeStartInDaysMin.timezone)
15
+ .startOf('days')
16
+ .subtract(gracePeriodBeforeStartInDaysMin.period.value, 'days')
17
+ .format('YYYY-MM-DD');
18
+ console.log('minDate:', minDate);
19
+
20
+ const returnMaxDate = moment(`${minDate}T${gracePeriodBeforeStartInDaysMin.time}`)
21
+ .tz(gracePeriodBeforeStartInDaysMin.timezone);
22
+ console.log(returnMaxDate);
23
+
24
+ console.log(returnMaxDate.isSameOrAfter(moment(returningDate)));
@@ -94,7 +94,11 @@ export declare class MongoRepository {
94
94
  /**
95
95
  * オファー展開の注文検索
96
96
  */
97
- searchWithUnwoundAcceptedOffer(params: factory.order.ISearchConditions, projection?: any): Promise<factory.order.IOrder[]>;
97
+ searchWithUnwoundAcceptedOffer(params: factory.order.ISearchConditions, projection?: {
98
+ [key: string]: any;
99
+ }): Promise<Omit<factory.order.IOrder[], 'acceptedOffers'> & {
100
+ acceptedOffers?: factory.order.IAcceptedOffer<factory.order.IItemOffered> | factory.order.IAcceptedOffer<factory.order.IItemOffered>[];
101
+ }>;
98
102
  /**
99
103
  * 特典口座情報が未保管であれば保管する
100
104
  */
@@ -118,5 +122,16 @@ export declare class MongoRepository {
118
122
  $in: string[];
119
123
  };
120
124
  }): Promise<string[]>;
125
+ /**
126
+ * 注文に含まれるacceptedOffersを検索する
127
+ */
128
+ searchAcceptedOffersByOrderNumbers(params: {
129
+ orderNumber: {
130
+ $in: string[];
131
+ };
132
+ }): Promise<{
133
+ id: string;
134
+ priceSpecification: factory.order.ITicketPriceSpecification;
135
+ }[]>;
121
136
  getCursor(conditions: any, projection: any): import("mongoose").Cursor<any, import("mongoose").QueryOptions<any>>;
122
137
  }
@@ -1002,12 +1002,12 @@ class MongoRepository {
1002
1002
  if (!Array.isArray(params.orderNumber.$in) || params.orderNumber.$in.length === 0) {
1003
1003
  return [];
1004
1004
  }
1005
- const reservationNumbers = yield this.orderModel.distinct('acceptedOffers.itemOffered.reservationNumber', {
1006
- orderNumber: params.orderNumber.$in
1005
+ return this.orderModel.distinct('acceptedOffers.itemOffered.reservationNumber', {
1006
+ 'acceptedOffers.itemOffered.reservationNumber': { $exists: true },
1007
+ orderNumber: { $in: params.orderNumber.$in }
1007
1008
  })
1008
1009
  .setOptions({ maxTimeMS: 10000 })
1009
1010
  .exec();
1010
- return [...new Set(reservationNumbers)];
1011
1011
  });
1012
1012
  }
1013
1013
  /**
@@ -1020,12 +1020,32 @@ class MongoRepository {
1020
1020
  }
1021
1021
  return this.orderModel.distinct('acceptedOffers.itemOffered.reservationFor.id', {
1022
1022
  'acceptedOffers.itemOffered.reservationFor.id': { $exists: true },
1023
- orderNumber: params.orderNumber.$in
1023
+ orderNumber: { $in: params.orderNumber.$in }
1024
1024
  })
1025
1025
  .setOptions({ maxTimeMS: 10000 })
1026
1026
  .exec();
1027
1027
  });
1028
1028
  }
1029
+ /**
1030
+ * 注文に含まれるacceptedOffersを検索する
1031
+ */
1032
+ searchAcceptedOffersByOrderNumbers(params) {
1033
+ return __awaiter(this, void 0, void 0, function* () {
1034
+ if (!Array.isArray(params.orderNumber.$in) || params.orderNumber.$in.length === 0) {
1035
+ return [];
1036
+ }
1037
+ const aggregate = this.orderModel.aggregate();
1038
+ aggregate.unwind('$acceptedOffers');
1039
+ aggregate.match({ orderNumber: { $in: params.orderNumber.$in } });
1040
+ aggregate.project({
1041
+ _id: 0,
1042
+ id: '$acceptedOffers.id',
1043
+ priceSpecification: '$acceptedOffers.priceSpecification'
1044
+ });
1045
+ return aggregate.option({ maxTimeMS: 10000 })
1046
+ .exec();
1047
+ });
1048
+ }
1029
1049
  getCursor(conditions, projection) {
1030
1050
  return this.orderModel.find(conditions, projection)
1031
1051
  .sort({ orderDate: factory.sortType.Descending })
@@ -133,31 +133,39 @@ exports.createReturnPaymentMethodActions = createReturnPaymentMethodActions;
133
133
  function createReturnPaymentMethodIssuedThroughMovieTicketActions(params) {
134
134
  return __awaiter(this, void 0, void 0, function* () {
135
135
  const order = params.order;
136
- const returnFeesMovieTicket = params.transaction.object.returnPolicy.returnFeesMovieTicket;
136
+ const returnFeesMovieTicketByTransaction = params.transaction.object.returnPolicy.returnFeesMovieTicket;
137
137
  return Promise.all(params.order.paymentMethods
138
138
  .filter((paymentMethod) => {
139
139
  return paymentMethod.issuedThrough.typeOf === factory.service.paymentService.PaymentServiceType.MovieTicket;
140
140
  })
141
- // 決済カード着券取消有無設定があれば適用
141
+ // 決済カード着券取消有無設定を適用
142
142
  .filter((paymentMethod) => {
143
- var _a;
143
+ // デフォルトで実行する
144
+ let returnPaymentMethod = true;
144
145
  const movieTicketIdentifier = paymentMethod.accountId;
145
- const returnFeesMovieTicketSetting = (_a = returnFeesMovieTicket === null || returnFeesMovieTicket === void 0 ? void 0 : returnFeesMovieTicket.find((r) => r.identifier === String(movieTicketIdentifier))) === null || _a === void 0 ? void 0 : _a.returnFees;
146
+ const returnFeesMovieTicketSettingsByIdentifier = returnFeesMovieTicketByTransaction === null || returnFeesMovieTicketByTransaction === void 0 ? void 0 : returnFeesMovieTicketByTransaction.filter((r) => {
147
+ var _a;
148
+ return r.identifier === String(movieTicketIdentifier)
149
+ && ((_a = r.serviceOutput) === null || _a === void 0 ? void 0 : _a.typeOf) === paymentMethod.typeOf;
150
+ });
146
151
  // 設定がなければスルー
147
- if (typeof returnFeesMovieTicketSetting !== 'string') {
148
- return true;
149
- }
150
- // 設定があれば適用
151
- switch (returnFeesMovieTicketSetting) {
152
- case factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn:
153
- // 取消実行する
154
- return true;
155
- case factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility:
156
- // 取消実行しない
157
- return false;
158
- default:
159
- throw new factory.errors.NotImplemented(`returnFees ${returnFeesMovieTicketSetting} not implemented`);
152
+ if (Array.isArray(returnFeesMovieTicketSettingsByIdentifier) && returnFeesMovieTicketSettingsByIdentifier.length > 0) {
153
+ returnFeesMovieTicketSettingsByIdentifier.forEach((returnFeesMovieTicketSetting) => {
154
+ const returnFeesEnumeration = returnFeesMovieTicketSetting.returnFees;
155
+ switch (returnFeesEnumeration) {
156
+ case factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn:
157
+ break;
158
+ // ひとつでも「取消を実行しない」に設定されていれば、実行しない
159
+ case factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility:
160
+ // 取消実行しない
161
+ returnPaymentMethod = false;
162
+ break;
163
+ default:
164
+ throw new factory.errors.NotImplemented(`returnFees ${returnFeesEnumeration} not implemented`);
165
+ }
166
+ });
160
167
  }
168
+ return returnPaymentMethod;
161
169
  })
162
170
  .map((p) => __awaiter(this, void 0, void 0, function* () {
163
171
  const potentialActionsOnRefund = yield createReturnPaymentMethodPotentialActions({
@@ -13,7 +13,7 @@ exports.exportTasksById = exports.confirm = exports.start = void 0;
13
13
  /**
14
14
  * 返品取引サービス
15
15
  */
16
- const moment = require("moment");
16
+ const moment = require("moment-timezone");
17
17
  const factory = require("../../factory");
18
18
  const factory_1 = require("./returnOrder/exportTasks/factory");
19
19
  const potentialActions_1 = require("./returnOrder/potentialActions");
@@ -25,7 +25,7 @@ function start(params) {
25
25
  // tslint:disable-next-line:max-func-body-length
26
26
  return (repos) => __awaiter(this, void 0, void 0, function* () {
27
27
  const now = new Date();
28
- const { eventIds, offerIds, orders } = yield fixOrders(params)(repos);
28
+ const { acceptedOffers, eventIds, offerIds, orders } = yield fixOrders(params)(repos);
29
29
  // sellerはorderから自動取得
30
30
  const seller = yield repos.seller.findById({ id: String(orders[0].seller.id) }, { additionalProperty: 0, paymentAccepted: 0 });
31
31
  yield validateOrder({ orders })(repos);
@@ -63,6 +63,7 @@ function start(params) {
63
63
  }
64
64
  const policiesByOffer = yield searchPoliciesByOffer({ offers })(repos);
65
65
  const appliedReturnPolicy = findApplicableReturnPolicy({
66
+ acceptedOffers,
66
67
  events,
67
68
  offerItemConditions,
68
69
  orders,
@@ -156,7 +157,10 @@ function fixOrders(params) {
156
157
  const eventIds = yield repos.order.searchReservationForIdsByOrderNumbers({
157
158
  orderNumber: { $in: [params.object.order[0].orderNumber] }
158
159
  });
159
- return { eventIds, offerIds, orders };
160
+ const acceptedOffers = yield repos.order.searchAcceptedOffersByOrderNumbers({
161
+ orderNumber: { $in: [params.object.order[0].orderNumber] }
162
+ });
163
+ return { acceptedOffers, eventIds, offerIds, orders };
160
164
  });
161
165
  }
162
166
  function validateOrder(params) {
@@ -232,7 +236,7 @@ function findApplicableReturnPolicy(params) {
232
236
  if (params.reason === factory.transaction.returnOrder.Reason.Customer) {
233
237
  // 適用可能なポリシーにフィルター
234
238
  applicalbleReturnPolicies = returnPolicies.filter((returnPolicy) => {
235
- var _a, _b, _c, _d, _e;
239
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
236
240
  let satisfyMerchantReturnDays = false;
237
241
  let offerItemCondition;
238
242
  const itemConditionId = (_a = returnPolicy.itemCondition) === null || _a === void 0 ? void 0 : _a.id;
@@ -264,6 +268,8 @@ function findApplicableReturnPolicy(params) {
264
268
  if (offerItemCondition !== undefined) {
265
269
  let satisfyGracePeriodMaxValue = true;
266
270
  let satisfyGracePeriodMinValue = true;
271
+ let satisfyGracePeriodInDaysMax = true;
272
+ let satisfyGracePeriodInDaysMin = true;
267
273
  // 全イベントについて猶予の確認ができれば適用
268
274
  const gracePeriodMaxValue = (_c = (_b = offerItemCondition.itemOffered.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservationFor.gracePeriodBeforeStart) === null || _c === void 0 ? void 0 : _c.maxValue;
269
275
  const gracePeriodMinValue = (_e = (_d = offerItemCondition.itemOffered.serviceOutput) === null || _d === void 0 ? void 0 : _d.reservationFor.gracePeriodBeforeStart) === null || _e === void 0 ? void 0 : _e.minValue;
@@ -281,7 +287,36 @@ function findApplicableReturnPolicy(params) {
281
287
  .add(gracePeriodMinValue, 'seconds'));
282
288
  });
283
289
  }
284
- satisfyItemCondition = satisfyGracePeriodMaxValue && satisfyGracePeriodMinValue;
290
+ const gracePeriodBeforeStartInDaysMax = (_g = (_f = offerItemCondition.itemOffered.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservationFor.gracePeriodBeforeStartInDays) === null || _g === void 0 ? void 0 : _g.max;
291
+ if (typeof (gracePeriodBeforeStartInDaysMax === null || gracePeriodBeforeStartInDaysMax === void 0 ? void 0 : gracePeriodBeforeStartInDaysMax.period.value) === 'number'
292
+ && typeof gracePeriodBeforeStartInDaysMax.time === 'string') {
293
+ satisfyGracePeriodInDaysMax = params.events.every((event) => {
294
+ const minDate = moment(event.startDate)
295
+ .tz(gracePeriodBeforeStartInDaysMax.timezone)
296
+ .startOf('days')
297
+ .subtract(gracePeriodBeforeStartInDaysMax.period.value, 'days')
298
+ .format('YYYY-MM-DD');
299
+ const returnMinDate = moment(`${minDate}T${gracePeriodBeforeStartInDaysMax.time}`)
300
+ .tz(gracePeriodBeforeStartInDaysMax.timezone);
301
+ return returnMinDate.isSameOrBefore(moment(returningDate));
302
+ });
303
+ }
304
+ const gracePeriodBeforeStartInDaysMin = (_j = (_h = offerItemCondition.itemOffered.serviceOutput) === null || _h === void 0 ? void 0 : _h.reservationFor.gracePeriodBeforeStartInDays) === null || _j === void 0 ? void 0 : _j.min;
305
+ if (typeof (gracePeriodBeforeStartInDaysMin === null || gracePeriodBeforeStartInDaysMin === void 0 ? void 0 : gracePeriodBeforeStartInDaysMin.period.value) === 'number'
306
+ && typeof gracePeriodBeforeStartInDaysMin.time === 'string') {
307
+ satisfyGracePeriodInDaysMin = params.events.every((event) => {
308
+ const minDate = moment(event.startDate)
309
+ .tz(gracePeriodBeforeStartInDaysMin.timezone)
310
+ .startOf('days')
311
+ .subtract(gracePeriodBeforeStartInDaysMin.period.value, 'days')
312
+ .format('YYYY-MM-DD');
313
+ const returnMaxDate = moment(`${minDate}T${gracePeriodBeforeStartInDaysMin.time}`)
314
+ .tz(gracePeriodBeforeStartInDaysMin.timezone);
315
+ return returnMaxDate.isSameOrAfter(moment(returningDate));
316
+ });
317
+ }
318
+ satisfyItemCondition = satisfyGracePeriodMaxValue && satisfyGracePeriodMinValue
319
+ && satisfyGracePeriodInDaysMax && satisfyGracePeriodInDaysMin;
285
320
  }
286
321
  return satisfyMerchantReturnDays && satisfyItemCondition;
287
322
  });
@@ -309,7 +344,11 @@ function findApplicableReturnPolicy(params) {
309
344
  throw new factory.errors.Argument('Seller', 'has no applicable return policies');
310
345
  }
311
346
  // オファーの返品ポリシーから返品手数料タイプを決定する
312
- const { returnFees } = validateOffersReturnPolicy({ offers: params.offers, policiesByOffer: params.policiesByOffer });
347
+ const { returnFees, returnFeesMovieTicket } = validateOffersReturnPolicy({
348
+ acceptedOffers: params.acceptedOffers,
349
+ offers: params.offers,
350
+ policiesByOffer: params.policiesByOffer
351
+ });
313
352
  // restockingFeeが最低のポリシーを自動選択
314
353
  let appliedReturnPolicy = applicalbleReturnPolicies[0];
315
354
  applicalbleReturnPolicies.forEach((returnPolicy) => {
@@ -328,6 +367,7 @@ function findApplicableReturnPolicy(params) {
328
367
  merchantReturnDays: appliedReturnPolicy.merchantReturnDays,
329
368
  restockingFee: appliedReturnPolicy.restockingFee,
330
369
  returnFees,
370
+ returnFeesMovieTicket,
331
371
  typeOf: 'MerchantReturnPolicy'
332
372
  };
333
373
  }
@@ -368,8 +408,41 @@ function validateOffersReturnPolicy(params) {
368
408
  else {
369
409
  throw new factory.errors.NotImplemented('returnFees not defined');
370
410
  }
371
- // 決済カード取消有無はどうか?
372
- return { returnFees };
411
+ // 決済カード取消ポリシーを確定(2023-05-23~)
412
+ const returnFeesMovieTicket = [];
413
+ params.acceptedOffers.forEach((acceptedOffer) => {
414
+ const unitPriceOffer = params.offers.find((offer) => offer.id === acceptedOffer.id);
415
+ if (unitPriceOffer === undefined) {
416
+ throw new factory.errors.NotFound(`UnitPriceOffer ${acceptedOffer.id}`);
417
+ }
418
+ if (!Array.isArray(unitPriceOffer.hasMerchantReturnPolicy) || unitPriceOffer.hasMerchantReturnPolicy.length === 0) {
419
+ throw new factory.errors.NotFound(`offer.hasMerchantReturnPolicy ${acceptedOffer.id}`);
420
+ }
421
+ const hasMerchantReturnPolicy = unitPriceOffer.hasMerchantReturnPolicy[0];
422
+ const policyByOffer = params.policiesByOffer.find((policy) => policy.id === hasMerchantReturnPolicy.id);
423
+ if (policyByOffer === undefined) {
424
+ throw new factory.errors.NotFound(`MerchantReturnPolicy acceptedOffer:${acceptedOffer.id}`);
425
+ }
426
+ const movieTicketTypeChargeSpecExists = acceptedOffer.priceSpecification.priceComponent.some((component) => {
427
+ return component.typeOf === factory.priceSpecificationType.MovieTicketTypeChargeSpecification;
428
+ });
429
+ if (movieTicketTypeChargeSpecExists) {
430
+ acceptedOffer.priceSpecification.priceComponent.forEach((component) => {
431
+ if (component.typeOf === factory.priceSpecificationType.UnitPriceSpecification) {
432
+ if (Array.isArray(component.appliesToMovieTicket)) {
433
+ component.appliesToMovieTicket.forEach((appliesToMovieTicket) => {
434
+ returnFeesMovieTicket.push({
435
+ identifier: String(appliesToMovieTicket.identifier),
436
+ returnFees: policyByOffer.customerRemorseReturnFeesMovieTicket,
437
+ serviceOutput: { typeOf: appliesToMovieTicket.serviceOutput.typeOf }
438
+ });
439
+ });
440
+ }
441
+ }
442
+ });
443
+ }
444
+ });
445
+ return { returnFees, returnFeesMovieTicket };
373
446
  }
374
447
  function validateAppliedReturnPolicy(params) {
375
448
  var _a;
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "dependencies": {
12
- "@chevre/factory": "4.313.0-alpha.5",
12
+ "@chevre/factory": "4.313.0-alpha.8",
13
13
  "@cinerino/sdk": "3.156.0",
14
14
  "@motionpicture/coa-service": "9.2.0",
15
15
  "@motionpicture/gmo-service": "5.2.0",
@@ -117,5 +117,5 @@
117
117
  "postversion": "git push origin --tags",
118
118
  "prepublishOnly": "npm run clean && npm run build && npm test && npm run doc"
119
119
  },
120
- "version": "21.2.0-alpha.63"
120
+ "version": "21.2.0-alpha.65"
121
121
  }