@chevre/domain 22.10.0-alpha.12 → 22.10.0-alpha.13

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.
@@ -11,7 +11,7 @@ mongoose.Model.on('index', (...args) => {
11
11
  async function main() {
12
12
  await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
13
13
 
14
- await chevre.repository.EventOffer.createInstance(mongoose.connection);
14
+ await chevre.repository.Issuer.createInstance(mongoose.connection);
15
15
  console.log('success!');
16
16
  }
17
17
 
@@ -81,13 +81,14 @@ function countRedisKeyByProject(params: {
81
81
  console.log(i, 'events checked');
82
82
  console.log(redisKeyCount, 'redisKeys found');
83
83
 
84
- return { checkedCount: i, redisKeyCount };
84
+ return { checkedCount: i, redisKeyCount, eventsWithRedis };
85
85
  };
86
86
  }
87
87
 
88
88
  // tslint:disable-next-line:max-func-body-length
89
89
  async function main() {
90
90
  const eventRepo = await chevre.repository.Event.createInstance(mongoose.connection);
91
+ const projectRepo = await chevre.repository.Project.createInstance(mongoose.connection);
91
92
  const settingRepo = await chevre.repository.Setting.createInstance(mongoose.connection);
92
93
  const stockHolderRepo = await chevre.repository.StockHolder.createInstance(
93
94
  client,
@@ -96,10 +97,21 @@ async function main() {
96
97
 
97
98
  const setting = await settingRepo.findOne(
98
99
  { project: { id: { $eq: '*' } } },
99
- ['useMongoAsStockHolderProjects']
100
+ ['useMongoAsStockHolderProjects', 'useMongoAsStockHolder']
100
101
  );
101
- const useMongoAsStockHolderProjects =
102
+ const useMongoAsStockHolder = setting?.useMongoAsStockHolder === true;
103
+ let useMongoAsStockHolderProjects =
102
104
  (Array.isArray(setting?.useMongoAsStockHolderProjects)) ? setting?.useMongoAsStockHolderProjects : [];
105
+ if (useMongoAsStockHolder) {
106
+ // 全プロジェクト
107
+ useMongoAsStockHolderProjects = (await projectRepo.projectFields(
108
+ {
109
+ // id: { $eq: 'xxx' }
110
+ },
111
+ ['id']
112
+ )).map(({ id }) => id);
113
+ }
114
+
103
115
  const results: {
104
116
  project: { id: string };
105
117
  checkedCount: number;
@@ -122,15 +134,16 @@ async function main() {
122
134
  checkedCount,
123
135
  redisKeyCount
124
136
  });
137
+ // console.log(eventsWithRedis);
125
138
  }
126
139
 
127
140
  const header = util.format(
128
141
  '| %s | %s | %s | %s |\n| %s | %s | %s | %s |',
129
- `project `.slice(0, 24),
142
+ `project `.slice(0, 40),
130
143
  `now `.slice(0, 24),
131
144
  `checkedCount `.slice(0, 24),
132
145
  `redisKeyCount `.slice(0, 24),
133
- `------------------------ `.slice(0, 24),
146
+ `---------------------------------------- `.slice(0, 40),
134
147
  `------------------------ `.slice(0, 24),
135
148
  `------------------------ `.slice(0, 24),
136
149
  `------------------------ `.slice(0, 24)
@@ -142,7 +155,7 @@ async function main() {
142
155
  results.map((result) => {
143
156
  return util.format(
144
157
  '| %s | %s | %s | %s |',
145
- `${result.project.id} `.slice(0, 24),
158
+ `${result.project.id} `.slice(0, 40),
146
159
  `${now.toISOString()} `.slice(0, 24),
147
160
  `${result.checkedCount} `.slice(0, 24),
148
161
  `${result.redisKeyCount} `.slice(0, 24)
@@ -153,20 +166,22 @@ async function main() {
153
166
  console.log(text);
154
167
 
155
168
  // backlogへ通知
156
- console.log('notifying on backlog...');
157
- await fetch(
158
- BACKLOG_NOTIFY_URL,
159
- {
160
- method: 'POST',
161
- headers: new Headers({ 'Content-Type': 'application/json' }),
162
- body: JSON.stringify({
163
- content: text,
164
- notifiedUserId: []
165
- // notifiedUserId: users.map((user) => user.id)
166
- })
167
- }
168
- );
169
- console.log('posted to backlog.');
169
+ if (typeof BACKLOG_API_KEY === 'string') {
170
+ console.log('notifying on backlog...');
171
+ await fetch(
172
+ BACKLOG_NOTIFY_URL,
173
+ {
174
+ method: 'POST',
175
+ headers: new Headers({ 'Content-Type': 'application/json' }),
176
+ body: JSON.stringify({
177
+ content: text,
178
+ notifiedUserId: []
179
+ // notifiedUserId: users.map((user) => user.id)
180
+ })
181
+ }
182
+ );
183
+ console.log('posted to backlog.');
184
+ }
170
185
  }
171
186
 
172
187
  main()
@@ -0,0 +1,20 @@
1
+ import * as factory from '../../../../factory';
2
+ /**
3
+ * 販売者に設定された利用可能な販売者返品ポリシー
4
+ */
5
+ type IAvailableSellerReturnPolicy = Pick<factory.sellerReturnPolicy.ISellerReturnPolicy, 'applicablePaymentMethod' | 'identifier' | 'itemCondition' | 'merchantReturnDays' | 'restockingFee' | 'typeOf'>;
6
+ /**
7
+ * プロジェクトのカスタム返品ポリシー
8
+ * リモートから取得
9
+ */
10
+ type ICustomSellerReturnPolicy = Pick<factory.sellerReturnPolicy.ISellerReturnPolicy, 'identifier' | 'restockingFee' | 'typeOf'> & {
11
+ /**
12
+ * support itemCondition(2025-05-17~)
13
+ */
14
+ itemCondition?: factory.offerItemCondition.OfferItemCondition;
15
+ applicablePaymentMethod?: never;
16
+ merchantReturnDays?: never;
17
+ };
18
+ type IFixedAcceptedOffer = Pick<factory.order.IAcceptedOffer<factory.order.IItemOffered>, 'id' | 'priceSpecification' | 'itemOffered'>;
19
+ type IFixedOrder = Pick<factory.order.IOrder, 'confirmationNumber' | 'dateReturned' | 'orderDate' | 'orderNumber' | 'orderStatus' | 'paymentMethods' | 'price' | 'project' | 'seller' | 'typeOf'>;
20
+ export { IAvailableSellerReturnPolicy, ICustomSellerReturnPolicy, IFixedAcceptedOffer, IFixedOrder };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,23 @@
1
+ import * as factory from '../../../../factory';
2
+ import { IAvailableSellerReturnPolicy, IFixedAcceptedOffer, IFixedOrder } from './factory';
3
+ /**
4
+ * 採用可能な販売者の返品ポリシーをひとつ選択する
5
+ * restockingFeeが最低のポリシーを自動選択
6
+ */
7
+ declare function findApplicableReturnPolicy(params: {
8
+ acceptedOffers: IFixedAcceptedOffer[];
9
+ events: {
10
+ id: string;
11
+ startDate: Date;
12
+ }[];
13
+ offerItemConditions: Pick<factory.offerItemCondition.IOfferItemCondition, 'id' | 'identifier' | 'itemOffered' | 'typeOf'>[];
14
+ orders: IFixedOrder[];
15
+ returningDate: Date;
16
+ reason: factory.transaction.returnOrder.Reason;
17
+ returnPolicies: IAvailableSellerReturnPolicy[];
18
+ returnPolicySettingsByProject?: factory.project.IHasMerchantReturnPolicy;
19
+ offers: factory.unitPriceOffer.IUnitPriceOffer[];
20
+ policiesByOffer: factory.unitPriceOffer.IOfferMerchantReturnPolicy[];
21
+ usedReservationExists: boolean;
22
+ }): Promise<factory.action.transfer.returnAction.order.IReturnPolicy>;
23
+ export { findApplicableReturnPolicy };
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.findApplicableReturnPolicy = findApplicableReturnPolicy;
13
+ const createDebug = require("debug");
14
+ const moment = require("moment-timezone");
15
+ const factory = require("../../../../factory");
16
+ const getReturnPolicyByProject_1 = require("./getReturnPolicyByProject");
17
+ const debug = createDebug('chevre-domain:service');
18
+ /**
19
+ * 採用可能な販売者の返品ポリシーをひとつ選択する
20
+ * restockingFeeが最低のポリシーを自動選択
21
+ */
22
+ // tslint:disable-next-line:max-func-body-length
23
+ function findApplicableReturnPolicy(params) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ var _a, _b, _c;
26
+ if (params.reason === factory.transaction.returnOrder.Reason.Seller) {
27
+ // 販売者都合の場合、手数料なしの返金返品ポリシーを適用
28
+ return {
29
+ typeOf: 'MerchantReturnPolicy',
30
+ returnFees: factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn
31
+ // no identifier in this case
32
+ };
33
+ }
34
+ const returnPolicies = params.returnPolicies;
35
+ let applicalbleReturnPolicies = [];
36
+ if (params.reason === factory.transaction.returnOrder.Reason.Customer) {
37
+ // プロジェクトの返品ポリシー設定を考慮(2023-11-14~)
38
+ const returnPolicySameAsByPoject = (_a = params.returnPolicySettingsByProject) === null || _a === void 0 ? void 0 : _a.sameAs;
39
+ if (typeof returnPolicySameAsByPoject === 'string' && returnPolicySameAsByPoject.length > 0) {
40
+ const returnPolicyByProject = yield (0, getReturnPolicyByProject_1.getReturnPolicyByProject)({
41
+ identifier: String((_b = params.returnPolicySettingsByProject) === null || _b === void 0 ? void 0 : _b.identifier),
42
+ sameAs: returnPolicySameAsByPoject,
43
+ order: Object.assign(Object.assign({}, params.orders[0]), { acceptedOffers: params.acceptedOffers })
44
+ });
45
+ applicalbleReturnPolicies.push(returnPolicyByProject);
46
+ }
47
+ else {
48
+ applicalbleReturnPolicies = returnPolicies;
49
+ }
50
+ }
51
+ // 適用可能なポリシーにフィルター
52
+ applicalbleReturnPolicies = applicalbleReturnPolicies.filter((returnPolicy) => {
53
+ return isSellerReturnPolicyApplicable({
54
+ returnPolicy,
55
+ events: params.events,
56
+ offerItemConditions: params.offerItemConditions,
57
+ orders: params.orders,
58
+ returningDate: params.returningDate,
59
+ usedReservationExists: params.usedReservationExists
60
+ });
61
+ });
62
+ // 販売者にポリシーが存在しなければ返品不可
63
+ if (applicalbleReturnPolicies.length === 0) {
64
+ throw new factory.errors.Argument('Seller', 'has no applicable return policies');
65
+ }
66
+ // オファーの返品ポリシーから返品手数料タイプを決定する
67
+ const { returnFees, returnFeesMovieTicket } = validateOffersReturnPolicy({
68
+ acceptedOffers: params.acceptedOffers,
69
+ offers: params.offers,
70
+ policiesByOffer: params.policiesByOffer
71
+ });
72
+ // restockingFeeが最低のポリシーを自動選択
73
+ let appliedReturnPolicy = applicalbleReturnPolicies[0];
74
+ applicalbleReturnPolicies.forEach((returnPolicy) => {
75
+ var _a, _b;
76
+ const appliedReturnPolicyRestockingFeeValue = (_a = appliedReturnPolicy.restockingFee) === null || _a === void 0 ? void 0 : _a.value;
77
+ const restockingFeeValue = (_b = returnPolicy.restockingFee) === null || _b === void 0 ? void 0 : _b.value;
78
+ const appliedReturnPolicyRestockingFee = (typeof appliedReturnPolicyRestockingFeeValue === 'number')
79
+ ? appliedReturnPolicyRestockingFeeValue
80
+ : 0;
81
+ const restockingFeeAsNumber = (typeof restockingFeeValue === 'number') ? restockingFeeValue : 0;
82
+ if (restockingFeeAsNumber < appliedReturnPolicyRestockingFee) {
83
+ appliedReturnPolicy = returnPolicy;
84
+ }
85
+ });
86
+ let appliedItemConditionAsStr;
87
+ let appliedItemCondition;
88
+ let appliedItemConditionId;
89
+ if (typeof appliedReturnPolicy.itemCondition === 'string') {
90
+ appliedItemConditionAsStr = appliedReturnPolicy.itemCondition;
91
+ }
92
+ else {
93
+ appliedItemConditionId = (_c = appliedReturnPolicy.itemCondition) === null || _c === void 0 ? void 0 : _c.id;
94
+ }
95
+ if (typeof appliedItemConditionId === 'string') {
96
+ const appliedItemConditionFromDB = params.offerItemConditions.find((o) => o.id === appliedItemConditionId);
97
+ if (appliedItemConditionFromDB === undefined) {
98
+ throw new factory.errors.NotFound('OfferItemCondition');
99
+ }
100
+ appliedItemCondition = Object.assign({ identifier: appliedItemConditionFromDB.identifier, itemOffered: appliedItemConditionFromDB.itemOffered, typeOf: appliedItemConditionFromDB.typeOf }, (typeof appliedItemConditionFromDB.id === 'string') ? { id: appliedItemConditionFromDB.id } : undefined);
101
+ }
102
+ const { restockingFee, typeOf, identifier, merchantReturnDays } = appliedReturnPolicy;
103
+ return Object.assign(Object.assign(Object.assign(Object.assign({ restockingFee,
104
+ returnFees, // offerのreturnPolicyから決定する
105
+ returnFeesMovieTicket,
106
+ typeOf }, (typeof identifier === 'string') ? { identifier } : undefined), (typeof merchantReturnDays === 'number') ? { merchantReturnDays } : undefined), (typeof (appliedItemCondition === null || appliedItemCondition === void 0 ? void 0 : appliedItemCondition.typeOf) === 'string') ? { itemCondition: appliedItemCondition } : undefined), (typeof appliedItemConditionAsStr === 'string') ? { itemCondition: appliedItemConditionAsStr } : undefined);
107
+ });
108
+ }
109
+ /**
110
+ * 販売者返品ポリシーが採用可能かどうか検証する
111
+ * アイテムコンディションも含めて検証する
112
+ */
113
+ // tslint:disable-next-line:cyclomatic-complexity max-func-body-length
114
+ function isSellerReturnPolicyApplicable(params) {
115
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
116
+ const returnPolicy = params.returnPolicy;
117
+ const returningDate = moment(params.returningDate);
118
+ let satisfyMerchantReturnDays = false;
119
+ let satisfyApplicablePaymentMethod = false;
120
+ let offerItemConditionAsStr;
121
+ let offerItemCondition;
122
+ if (typeof returnPolicy.itemCondition === 'string') {
123
+ offerItemConditionAsStr = returnPolicy.itemCondition;
124
+ }
125
+ else {
126
+ const itemConditionId = (_a = returnPolicy.itemCondition) === null || _a === void 0 ? void 0 : _a.id;
127
+ if (typeof itemConditionId === 'string') {
128
+ offerItemCondition = params.offerItemConditions.find((o) => o.id === itemConditionId);
129
+ if (offerItemCondition === undefined) {
130
+ throw new factory.errors.NotFound('OfferItemCondition');
131
+ }
132
+ }
133
+ }
134
+ const merchantReturnDays = returnPolicy.merchantReturnDays;
135
+ if (typeof merchantReturnDays === 'number') {
136
+ // 返品適用日数を確認する
137
+ const everyOrderApplicable = params.orders.every((order) => {
138
+ const mustBeReturnedUntil = moment(order.orderDate)
139
+ .add(merchantReturnDays, 'days');
140
+ return mustBeReturnedUntil.isSameOrAfter(returningDate);
141
+ });
142
+ // 全注文について日数の確認ができれば適用
143
+ if (everyOrderApplicable) {
144
+ satisfyMerchantReturnDays = true;
145
+ }
146
+ }
147
+ else {
148
+ // 日数制限なし
149
+ satisfyMerchantReturnDays = true;
150
+ }
151
+ // 適用決済方法検証(2023-08-08~)
152
+ const applicablePaymentMethod = returnPolicy.applicablePaymentMethod;
153
+ if (Array.isArray(applicablePaymentMethod)) {
154
+ const everyOrderApplicable = params.orders.every((order) => {
155
+ // 全決済方法区分がapplicablePaymentMethodに含まれれば適用
156
+ return order.paymentMethods.every((invoice) => {
157
+ var _a;
158
+ return typeof ((_a = invoice.paymentMethod) === null || _a === void 0 ? void 0 : _a.identifier) === 'string'
159
+ && applicablePaymentMethod.includes(invoice.paymentMethod.identifier);
160
+ });
161
+ });
162
+ // 全注文について確認ができれば適用
163
+ if (everyOrderApplicable) {
164
+ satisfyApplicablePaymentMethod = true;
165
+ }
166
+ }
167
+ else {
168
+ satisfyApplicablePaymentMethod = true;
169
+ }
170
+ // アイテムコンディション検証
171
+ let satisfyItemCondition = true;
172
+ if (typeof offerItemConditionAsStr === 'string') {
173
+ if (offerItemConditionAsStr === factory.offerItemCondition.OfferItemCondition.NewCondition) {
174
+ let satisfyOnlyUnused = true;
175
+ if (params.usedReservationExists) {
176
+ satisfyOnlyUnused = false;
177
+ }
178
+ debug('usedReservationExists:', params.usedReservationExists, 'satisfyOnlyUnused:', satisfyOnlyUnused, 'itemCondition:', offerItemConditionAsStr);
179
+ satisfyItemCondition = satisfyOnlyUnused;
180
+ }
181
+ }
182
+ else {
183
+ if (offerItemCondition !== undefined) {
184
+ let satisfyGracePeriodMaxValue = true;
185
+ let satisfyGracePeriodMinValue = true;
186
+ // 全イベントについて猶予の確認ができれば適用
187
+ const gracePeriodMaxValue = (_c = (_b = offerItemCondition.itemOffered.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservationFor.gracePeriodBeforeStart) === null || _c === void 0 ? void 0 : _c.maxValue;
188
+ const gracePeriodMinValue = (_e = (_d = offerItemCondition.itemOffered.serviceOutput) === null || _d === void 0 ? void 0 : _d.reservationFor.gracePeriodBeforeStart) === null || _e === void 0 ? void 0 : _e.minValue;
189
+ if (typeof gracePeriodMaxValue === 'number') {
190
+ satisfyGracePeriodMaxValue = params.events.every((event) => {
191
+ return moment(event.startDate)
192
+ .isSameOrBefore(moment(params.returningDate)
193
+ .add(gracePeriodMaxValue, 'seconds'));
194
+ });
195
+ }
196
+ if (typeof gracePeriodMinValue === 'number') {
197
+ satisfyGracePeriodMinValue = params.events.every((event) => {
198
+ debug('isSellerReturnPolicyApplicable: comparing by gracePeriodMinValue...', 'gracePeriodMinValue:', gracePeriodMinValue, event.startDate, '>', moment(params.returningDate)
199
+ .add(gracePeriodMinValue, 'seconds'), '?');
200
+ return moment(event.startDate)
201
+ .isAfter(moment(params.returningDate)
202
+ .add(gracePeriodMinValue, 'seconds'));
203
+ });
204
+ }
205
+ let satisfyGracePeriodInDaysMax = true;
206
+ let satisfyGracePeriodInDaysMin = true;
207
+ const gracePeriodBeforeStartInDaysMax = (_g = (_f = offerItemCondition.itemOffered.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservationFor.gracePeriodBeforeStartInDays) === null || _g === void 0 ? void 0 : _g.max;
208
+ if (typeof (gracePeriodBeforeStartInDaysMax === null || gracePeriodBeforeStartInDaysMax === void 0 ? void 0 : gracePeriodBeforeStartInDaysMax.period.value) === 'number'
209
+ && typeof gracePeriodBeforeStartInDaysMax.time === 'string') {
210
+ satisfyGracePeriodInDaysMax = params.events.every((event) => {
211
+ const maxDate = moment(event.startDate)
212
+ .tz(gracePeriodBeforeStartInDaysMax.timezone)
213
+ .startOf('days')
214
+ .subtract(gracePeriodBeforeStartInDaysMax.period.value, 'days')
215
+ .format('YYYY-MM-DD');
216
+ const returnMinDate = moment.tz(`${maxDate}T${gracePeriodBeforeStartInDaysMax.time}`, gracePeriodBeforeStartInDaysMax.timezone);
217
+ debug('returnMinDate:', returnMinDate, 'returningDate:', returningDate);
218
+ return returnMinDate.isSameOrBefore(moment(returningDate));
219
+ });
220
+ }
221
+ debug('gracePeriodBeforeStartInDaysMax:', gracePeriodBeforeStartInDaysMax);
222
+ const gracePeriodBeforeStartInDaysMin = (_j = (_h = offerItemCondition.itemOffered.serviceOutput) === null || _h === void 0 ? void 0 : _h.reservationFor.gracePeriodBeforeStartInDays) === null || _j === void 0 ? void 0 : _j.min;
223
+ if (typeof (gracePeriodBeforeStartInDaysMin === null || gracePeriodBeforeStartInDaysMin === void 0 ? void 0 : gracePeriodBeforeStartInDaysMin.period.value) === 'number'
224
+ && typeof gracePeriodBeforeStartInDaysMin.time === 'string') {
225
+ satisfyGracePeriodInDaysMin = params.events.every((event) => {
226
+ const minDate = moment(event.startDate)
227
+ .tz(gracePeriodBeforeStartInDaysMin.timezone)
228
+ .startOf('days')
229
+ .subtract(gracePeriodBeforeStartInDaysMin.period.value, 'days')
230
+ .format('YYYY-MM-DD');
231
+ const returnMaxDate = moment.tz(`${minDate}T${gracePeriodBeforeStartInDaysMin.time}`, gracePeriodBeforeStartInDaysMin.timezone);
232
+ debug('returnMaxDate:', returnMaxDate, 'returningDate:', returningDate);
233
+ return returnMaxDate.isAfter(moment(returningDate));
234
+ });
235
+ }
236
+ debug('satisfyGracePeriodInDaysMin:', satisfyGracePeriodInDaysMin);
237
+ let satisfyOnlyUnused = true;
238
+ if (((_k = offerItemCondition.itemOffered.serviceOutput) === null || _k === void 0 ? void 0 : _k.onlyUnused) === true) {
239
+ if (params.usedReservationExists) {
240
+ satisfyOnlyUnused = false;
241
+ }
242
+ }
243
+ debug('usedReservationExists:', params.usedReservationExists, 'satisfyOnlyUnused:', satisfyOnlyUnused);
244
+ satisfyItemCondition = satisfyGracePeriodMaxValue && satisfyGracePeriodMinValue
245
+ && satisfyGracePeriodInDaysMax && satisfyGracePeriodInDaysMin && satisfyOnlyUnused;
246
+ }
247
+ }
248
+ return satisfyMerchantReturnDays && satisfyApplicablePaymentMethod && satisfyItemCondition;
249
+ }
250
+ /**
251
+ * 注文中のオファーの返品ポリシーを検証
252
+ */
253
+ function validateOffersReturnPolicy(params) {
254
+ // オファーに返品ポリシーが設定されているか?
255
+ const everyOffersHaveReturnPolicy = params.offers.every((offer) => {
256
+ return Array.isArray(offer.hasMerchantReturnPolicy) && offer.hasMerchantReturnPolicy.length > 0;
257
+ });
258
+ if (!everyOffersHaveReturnPolicy) {
259
+ throw new factory.errors.NotFound('offer.hasMerchantReturnPolicy');
260
+ }
261
+ let returnFees;
262
+ // 返品手数料設定はどうか?
263
+ const somePolicyWithReturnFeesCustomerResponsibility = params.policiesByOffer.some((policy) => {
264
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
265
+ });
266
+ const somePolicyWithRestockingFees = params.policiesByOffer.some((policy) => {
267
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
268
+ });
269
+ const everyPolicyWithFreeReturn = params.policiesByOffer.every((policy) => {
270
+ return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
271
+ });
272
+ if (somePolicyWithReturnFeesCustomerResponsibility) {
273
+ // ひとつでも返金なしがあれば返金なし
274
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
275
+ }
276
+ else if (somePolicyWithRestockingFees) {
277
+ // ひとつでも手数料あり返金があれば手数料あり返金
278
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
279
+ }
280
+ else if (everyPolicyWithFreeReturn) {
281
+ // 全ポリシーが手数料なしであれば手数料なし返金
282
+ returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
283
+ }
284
+ else {
285
+ throw new factory.errors.NotImplemented('returnFees not defined');
286
+ }
287
+ // 決済カード取消ポリシーを確定(2023-05-23~)
288
+ const returnFeesMovieTicket = [];
289
+ params.acceptedOffers.forEach((acceptedOffer) => {
290
+ var _a, _b;
291
+ const unitPriceOffer = params.offers.find((offer) => offer.id === acceptedOffer.id);
292
+ if (unitPriceOffer === undefined) {
293
+ throw new factory.errors.NotFound(`UnitPriceOffer ${acceptedOffer.id}`);
294
+ }
295
+ if (!Array.isArray(unitPriceOffer.hasMerchantReturnPolicy) || unitPriceOffer.hasMerchantReturnPolicy.length === 0) {
296
+ throw new factory.errors.NotFound(`offer.hasMerchantReturnPolicy ${acceptedOffer.id}`);
297
+ }
298
+ const hasMerchantReturnPolicy = unitPriceOffer.hasMerchantReturnPolicy[0];
299
+ const policyByOffer = params.policiesByOffer.find((policy) => policy.id === hasMerchantReturnPolicy.id);
300
+ if (policyByOffer === undefined) {
301
+ throw new factory.errors.NotFound(`MerchantReturnPolicy acceptedOffer:${acceptedOffer.id}`);
302
+ }
303
+ const movieTicketTypeChargeSpecExists = (_a = acceptedOffer.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent.some((component) => {
304
+ return component.typeOf === factory.priceSpecificationType.MovieTicketTypeChargeSpecification;
305
+ });
306
+ if (movieTicketTypeChargeSpecExists === true) {
307
+ (_b = acceptedOffer.priceSpecification) === null || _b === void 0 ? void 0 : _b.priceComponent.forEach((component) => {
308
+ if (component.typeOf === factory.priceSpecificationType.UnitPriceSpecification) {
309
+ if (Array.isArray(component.appliesToMovieTicket)) {
310
+ component.appliesToMovieTicket.forEach((appliesToMovieTicket) => {
311
+ returnFeesMovieTicket.push({
312
+ identifier: String(appliesToMovieTicket.identifier),
313
+ returnFees: policyByOffer.customerRemorseReturnFeesMovieTicket,
314
+ serviceOutput: { typeOf: appliesToMovieTicket.serviceOutput.typeOf }
315
+ });
316
+ });
317
+ }
318
+ }
319
+ });
320
+ }
321
+ });
322
+ return { returnFees, returnFeesMovieTicket };
323
+ }
@@ -0,0 +1,13 @@
1
+ import * as factory from '../../../../factory';
2
+ import { ICustomSellerReturnPolicy, IFixedAcceptedOffer } from './factory';
3
+ /**
4
+ * プロジェクトのカスタム返品ポリシーをリモートから取得する
5
+ */
6
+ declare function getReturnPolicyByProject(params: {
7
+ identifier: string;
8
+ sameAs: string;
9
+ order: Pick<factory.order.IOrder, 'orderDate' | 'orderNumber' | 'price'> & {
10
+ acceptedOffers: IFixedAcceptedOffer[];
11
+ };
12
+ }): Promise<ICustomSellerReturnPolicy>;
13
+ export { getReturnPolicyByProject };
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.getReturnPolicyByProject = getReturnPolicyByProject;
24
+ const http_status_1 = require("http-status");
25
+ const factory = require("../../../../factory");
26
+ function createOrder4returnPolicy(params) {
27
+ return {
28
+ orderDate: params.order.orderDate,
29
+ orderNumber: params.order.orderNumber,
30
+ price: params.order.price,
31
+ acceptedOffers: params.order.acceptedOffers.map((o) => {
32
+ var _a;
33
+ if (o.itemOffered.typeOf === factory.reservationType.EventReservation) {
34
+ const reservation = o.itemOffered;
35
+ const priceComponent = (_a = o.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent;
36
+ return {
37
+ itemOffered: {
38
+ additionalProperty: reservation.additionalProperty,
39
+ reservationFor: {
40
+ doorTime: reservation.reservationFor.doorTime,
41
+ endDate: reservation.reservationFor.endDate,
42
+ startDate: reservation.reservationFor.startDate
43
+ // superEvent: reservation.reservationFor.superEvent
44
+ },
45
+ reservedTicket: {
46
+ ticketedSeat: reservation.reservedTicket.ticketedSeat
47
+ }
48
+ },
49
+ priceSpecification: {
50
+ priceComponent: (Array.isArray(priceComponent))
51
+ ? priceComponent.map((component) => {
52
+ const { accounting, name, priceCurrency, valueAddedTaxIncluded } = component, postingComponent = __rest(component, ["accounting", "name", "priceCurrency", "valueAddedTaxIncluded"]);
53
+ return postingComponent;
54
+ })
55
+ : []
56
+ }
57
+ };
58
+ }
59
+ else {
60
+ return {
61
+ priceSpecification: o.priceSpecification
62
+ };
63
+ }
64
+ })
65
+ };
66
+ }
67
+ const TIMEOUT = 5000;
68
+ /**
69
+ * プロジェクトのカスタム返品ポリシーをリモートから取得する
70
+ */
71
+ function getReturnPolicyByProject(params) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ var _a;
74
+ // implement with fetch(2024-01-20~)
75
+ try {
76
+ const { identifier, sameAs } = params;
77
+ const res = yield fetch(sameAs, {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json'
81
+ },
82
+ body: JSON.stringify({
83
+ order: createOrder4returnPolicy({ order: params.order })
84
+ }),
85
+ // body data type must match "Content-Type" header
86
+ signal: AbortSignal.timeout(TIMEOUT)
87
+ });
88
+ let body;
89
+ try {
90
+ body = (yield res.json());
91
+ }
92
+ catch (error) {
93
+ // no op
94
+ }
95
+ let returnPolicy;
96
+ switch (res.status) {
97
+ case http_status_1.OK:
98
+ case http_status_1.CREATED:
99
+ case http_status_1.ACCEPTED:
100
+ case http_status_1.NO_CONTENT:
101
+ const restockingFeeValue = (_a = body === null || body === void 0 ? void 0 : body.restockingFee) === null || _a === void 0 ? void 0 : _a.value;
102
+ if (typeof restockingFeeValue !== 'number') {
103
+ throw new factory.errors.Internal('invalid return policy');
104
+ }
105
+ else {
106
+ const itemCondition = body === null || body === void 0 ? void 0 : body.itemCondition;
107
+ if (itemCondition !== undefined) {
108
+ if (itemCondition !== factory.offerItemCondition.OfferItemCondition.NewCondition) {
109
+ throw new factory.errors.Argument('', `unknown itemCondition: ${itemCondition}`);
110
+ }
111
+ }
112
+ returnPolicy = Object.assign({ typeOf: 'MerchantReturnPolicy', restockingFee: {
113
+ currency: factory.priceCurrency.JPY,
114
+ typeOf: 'MonetaryAmount',
115
+ value: restockingFeeValue
116
+ }, identifier }, (typeof itemCondition === 'string') ? { itemCondition } : undefined // support itemCondition(2025-05-17~)
117
+ );
118
+ }
119
+ break;
120
+ case http_status_1.NOT_FOUND:
121
+ throw new factory.errors.Argument('', `custom return policy returned statusCode: ${res.status}`);
122
+ // break;
123
+ default:
124
+ throw new factory.errors.Internal(`ProjectReturnPolicy unavailable. statusCode: ${res.status} body: ${body}`);
125
+ }
126
+ return returnPolicy;
127
+ }
128
+ catch (err) {
129
+ throw err;
130
+ }
131
+ });
132
+ }
@@ -8,23 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __rest = (this && this.__rest) || function (s, e) {
12
- var t = {};
13
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
- t[p] = s[p];
15
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
- t[p[i]] = s[p[i]];
19
- }
20
- return t;
21
- };
22
11
  Object.defineProperty(exports, "__esModule", { value: true });
23
12
  exports.preStart = preStart;
24
13
  const createDebug = require("debug");
25
- const http_status_1 = require("http-status");
26
- const moment = require("moment-timezone");
27
14
  const factory = require("../../../factory");
15
+ const findApplicableReturnPolicy_1 = require("./preStart/findApplicableReturnPolicy");
28
16
  const debug = createDebug('chevre-domain:service');
29
17
  /**
30
18
  * 返品取引開始前処理
@@ -87,7 +75,7 @@ function preStart(params) {
87
75
  id: seller.project.id,
88
76
  inclusion: ['hasMerchantReturnPolicy']
89
77
  });
90
- const appliedReturnPolicy = yield findApplicableReturnPolicy(Object.assign({ acceptedOffers,
78
+ const appliedReturnPolicy = yield (0, findApplicableReturnPolicy_1.findApplicableReturnPolicy)(Object.assign({ acceptedOffers,
91
79
  events,
92
80
  offerItemConditions,
93
81
  orders, returningDate: now, reason: params.object.reason, returnPolicies,
@@ -247,383 +235,6 @@ function searchPoliciesByOffer(params) {
247
235
  return policiesByOffer;
248
236
  });
249
237
  }
250
- function createOrder4returnPolicy(params) {
251
- return {
252
- orderDate: params.order.orderDate,
253
- orderNumber: params.order.orderNumber,
254
- price: params.order.price,
255
- acceptedOffers: params.order.acceptedOffers.map((o) => {
256
- var _a;
257
- if (o.itemOffered.typeOf === factory.reservationType.EventReservation) {
258
- const reservation = o.itemOffered;
259
- const priceComponent = (_a = o.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent;
260
- return {
261
- itemOffered: {
262
- additionalProperty: reservation.additionalProperty,
263
- reservationFor: {
264
- doorTime: reservation.reservationFor.doorTime,
265
- endDate: reservation.reservationFor.endDate,
266
- startDate: reservation.reservationFor.startDate
267
- // superEvent: reservation.reservationFor.superEvent
268
- },
269
- reservedTicket: {
270
- ticketedSeat: reservation.reservedTicket.ticketedSeat
271
- }
272
- },
273
- priceSpecification: {
274
- priceComponent: (Array.isArray(priceComponent))
275
- ? priceComponent.map((component) => {
276
- const { accounting, name, priceCurrency, valueAddedTaxIncluded } = component, postingComponent = __rest(component, ["accounting", "name", "priceCurrency", "valueAddedTaxIncluded"]);
277
- return postingComponent;
278
- })
279
- : []
280
- }
281
- };
282
- }
283
- else {
284
- return {
285
- priceSpecification: o.priceSpecification
286
- };
287
- }
288
- })
289
- };
290
- }
291
- const TIMEOUT = 5000;
292
- function getReturnPolicyByProject(params) {
293
- return __awaiter(this, void 0, void 0, function* () {
294
- var _a;
295
- // implement with fetch(2024-01-20~)
296
- try {
297
- const { identifier, sameAs } = params;
298
- const res = yield fetch(sameAs, {
299
- method: 'POST',
300
- headers: {
301
- 'Content-Type': 'application/json'
302
- },
303
- body: JSON.stringify({
304
- order: createOrder4returnPolicy({ order: params.order })
305
- }),
306
- // body data type must match "Content-Type" header
307
- signal: AbortSignal.timeout(TIMEOUT)
308
- });
309
- let body;
310
- try {
311
- body = (yield res.json());
312
- }
313
- catch (error) {
314
- // no op
315
- }
316
- let returnPolicy;
317
- switch (res.status) {
318
- case http_status_1.OK:
319
- case http_status_1.CREATED:
320
- case http_status_1.ACCEPTED:
321
- case http_status_1.NO_CONTENT:
322
- if (typeof ((_a = body === null || body === void 0 ? void 0 : body.restockingFee) === null || _a === void 0 ? void 0 : _a.value) !== 'number') {
323
- throw new factory.errors.Internal('invalid return policy');
324
- }
325
- else {
326
- returnPolicy = {
327
- typeOf: 'MerchantReturnPolicy',
328
- restockingFee: {
329
- currency: factory.priceCurrency.JPY,
330
- typeOf: 'MonetaryAmount',
331
- value: body.restockingFee.value
332
- },
333
- // keep identifier(2024-06-26~)
334
- identifier
335
- };
336
- }
337
- break;
338
- case http_status_1.NOT_FOUND:
339
- throw new factory.errors.Argument('', `custom return policy returned statusCode: ${res.status}`);
340
- // break;
341
- default:
342
- throw new factory.errors.Internal(`ProjectReturnPolicy unavailable. statusCode: ${res.status} body: ${body}`);
343
- }
344
- return returnPolicy;
345
- }
346
- catch (err) {
347
- throw err;
348
- }
349
- });
350
- }
351
- /**
352
- * 販売者の返品ポリシーを確認する
353
- */
354
- // tslint:disable-next-line:max-func-body-length
355
- function findApplicableReturnPolicy(params) {
356
- return __awaiter(this, void 0, void 0, function* () {
357
- var _a, _b, _c;
358
- if (params.reason === factory.transaction.returnOrder.Reason.Seller) {
359
- // 販売者都合の場合、手数料なしの返金返品ポリシーを適用
360
- return {
361
- typeOf: 'MerchantReturnPolicy',
362
- returnFees: factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn
363
- // no identifier in this case
364
- };
365
- }
366
- const returnPolicies = params.returnPolicies;
367
- let applicalbleReturnPolicies = [];
368
- if (params.reason === factory.transaction.returnOrder.Reason.Customer) {
369
- // プロジェクトの返品ポリシー設定を考慮(2023-11-14~)
370
- const returnPolicySameAsByPoject = (_a = params.returnPolicySettingsByProject) === null || _a === void 0 ? void 0 : _a.sameAs;
371
- if (typeof returnPolicySameAsByPoject === 'string' && returnPolicySameAsByPoject.length > 0) {
372
- const returnPolicyByProject = yield getReturnPolicyByProject({
373
- identifier: String((_b = params.returnPolicySettingsByProject) === null || _b === void 0 ? void 0 : _b.identifier),
374
- sameAs: returnPolicySameAsByPoject,
375
- order: Object.assign(Object.assign({}, params.orders[0]), { acceptedOffers: params.acceptedOffers })
376
- });
377
- applicalbleReturnPolicies.push(returnPolicyByProject);
378
- }
379
- else {
380
- // 適用可能なポリシーにフィルター
381
- // tslint:disable-next-line:max-func-body-length
382
- applicalbleReturnPolicies = returnPolicies.filter((returnPolicy) => {
383
- return isSellerReturnPolicyApplicable({
384
- returnPolicy,
385
- events: params.events,
386
- offerItemConditions: params.offerItemConditions,
387
- orders: params.orders,
388
- returningDate: params.returningDate,
389
- usedReservationExists: params.usedReservationExists
390
- });
391
- });
392
- }
393
- }
394
- // 販売者にポリシーが存在しなければ返品不可
395
- if (applicalbleReturnPolicies.length === 0) {
396
- throw new factory.errors.Argument('Seller', 'has no applicable return policies');
397
- }
398
- // オファーの返品ポリシーから返品手数料タイプを決定する
399
- const { returnFees, returnFeesMovieTicket } = validateOffersReturnPolicy({
400
- acceptedOffers: params.acceptedOffers,
401
- offers: params.offers,
402
- policiesByOffer: params.policiesByOffer
403
- });
404
- // restockingFeeが最低のポリシーを自動選択
405
- let appliedReturnPolicy = applicalbleReturnPolicies[0];
406
- applicalbleReturnPolicies.forEach((returnPolicy) => {
407
- var _a, _b;
408
- const appliedReturnPolicyRestockingFeeValue = (_a = appliedReturnPolicy.restockingFee) === null || _a === void 0 ? void 0 : _a.value;
409
- const restockingFeeValue = (_b = returnPolicy.restockingFee) === null || _b === void 0 ? void 0 : _b.value;
410
- const appliedReturnPolicyRestockingFee = (typeof appliedReturnPolicyRestockingFeeValue === 'number')
411
- ? appliedReturnPolicyRestockingFeeValue
412
- : 0;
413
- const restockingFeeAsNumber = (typeof restockingFeeValue === 'number') ? restockingFeeValue : 0;
414
- if (restockingFeeAsNumber < appliedReturnPolicyRestockingFee) {
415
- appliedReturnPolicy = returnPolicy;
416
- }
417
- });
418
- let appliedItemCondition;
419
- const appliedItemConditionId = (_c = appliedReturnPolicy.itemCondition) === null || _c === void 0 ? void 0 : _c.id;
420
- if (typeof appliedItemConditionId === 'string') {
421
- const appliedItemConditionFromDB = params.offerItemConditions.find((o) => o.id === appliedItemConditionId);
422
- if (appliedItemConditionFromDB === undefined) {
423
- throw new factory.errors.NotFound('OfferItemCondition');
424
- }
425
- appliedItemCondition = Object.assign({ identifier: appliedItemConditionFromDB.identifier, itemOffered: appliedItemConditionFromDB.itemOffered, typeOf: appliedItemConditionFromDB.typeOf }, (typeof appliedItemConditionFromDB.id === 'string') ? { id: appliedItemConditionFromDB.id } : undefined);
426
- }
427
- const { restockingFee, typeOf, identifier, merchantReturnDays } = appliedReturnPolicy;
428
- return Object.assign(Object.assign(Object.assign({ restockingFee,
429
- returnFees, // offerのreturnPolicyから決定する
430
- returnFeesMovieTicket,
431
- typeOf }, (typeof identifier === 'string') ? { identifier } : undefined), (typeof merchantReturnDays === 'number') ? { merchantReturnDays } : undefined), (typeof (appliedItemCondition === null || appliedItemCondition === void 0 ? void 0 : appliedItemCondition.typeOf) === 'string') ? { itemCondition: appliedItemCondition } : undefined);
432
- });
433
- }
434
- // tslint:disable-next-line:cyclomatic-complexity max-func-body-length
435
- function isSellerReturnPolicyApplicable(params) {
436
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
437
- const returnPolicy = params.returnPolicy;
438
- const returningDate = moment(params.returningDate);
439
- let satisfyMerchantReturnDays = false;
440
- let satisfyApplicablePaymentMethod = false;
441
- let offerItemCondition;
442
- const itemConditionId = (_a = returnPolicy.itemCondition) === null || _a === void 0 ? void 0 : _a.id;
443
- if (typeof itemConditionId === 'string') {
444
- offerItemCondition = params.offerItemConditions.find((o) => o.id === itemConditionId);
445
- if (offerItemCondition === undefined) {
446
- throw new factory.errors.NotFound('OfferItemCondition');
447
- }
448
- }
449
- const merchantReturnDays = returnPolicy.merchantReturnDays;
450
- if (typeof merchantReturnDays === 'number') {
451
- // 返品適用日数を確認する
452
- const everyOrderApplicable = params.orders.every((order) => {
453
- const mustBeReturnedUntil = moment(order.orderDate)
454
- .add(merchantReturnDays, 'days');
455
- return mustBeReturnedUntil.isSameOrAfter(returningDate);
456
- });
457
- // 全注文について日数の確認ができれば適用
458
- if (everyOrderApplicable) {
459
- satisfyMerchantReturnDays = true;
460
- }
461
- }
462
- else {
463
- // 日数制限なし
464
- satisfyMerchantReturnDays = true;
465
- }
466
- // 適用決済方法検証(2023-08-08~)
467
- const applicablePaymentMethod = returnPolicy.applicablePaymentMethod;
468
- if (Array.isArray(applicablePaymentMethod)) {
469
- const everyOrderApplicable = params.orders.every((order) => {
470
- // 全決済方法区分がapplicablePaymentMethodに含まれれば適用
471
- return order.paymentMethods.every((invoice) => {
472
- var _a;
473
- return typeof ((_a = invoice.paymentMethod) === null || _a === void 0 ? void 0 : _a.identifier) === 'string'
474
- && applicablePaymentMethod.includes(invoice.paymentMethod.identifier);
475
- });
476
- });
477
- // 全注文について確認ができれば適用
478
- if (everyOrderApplicable) {
479
- satisfyApplicablePaymentMethod = true;
480
- }
481
- }
482
- else {
483
- satisfyApplicablePaymentMethod = true;
484
- }
485
- // イベント開始猶予を検証する(2023-05-22~)
486
- let satisfyItemCondition = true;
487
- if (offerItemCondition !== undefined) {
488
- let satisfyGracePeriodMaxValue = true;
489
- let satisfyGracePeriodMinValue = true;
490
- // 全イベントについて猶予の確認ができれば適用
491
- const gracePeriodMaxValue = (_c = (_b = offerItemCondition.itemOffered.serviceOutput) === null || _b === void 0 ? void 0 : _b.reservationFor.gracePeriodBeforeStart) === null || _c === void 0 ? void 0 : _c.maxValue;
492
- const gracePeriodMinValue = (_e = (_d = offerItemCondition.itemOffered.serviceOutput) === null || _d === void 0 ? void 0 : _d.reservationFor.gracePeriodBeforeStart) === null || _e === void 0 ? void 0 : _e.minValue;
493
- if (typeof gracePeriodMaxValue === 'number') {
494
- satisfyGracePeriodMaxValue = params.events.every((event) => {
495
- return moment(event.startDate)
496
- .isSameOrBefore(moment(params.returningDate)
497
- .add(gracePeriodMaxValue, 'seconds'));
498
- });
499
- }
500
- if (typeof gracePeriodMinValue === 'number') {
501
- satisfyGracePeriodMinValue = params.events.every((event) => {
502
- debug('isSellerReturnPolicyApplicable: comparing by gracePeriodMinValue...', 'gracePeriodMinValue:', gracePeriodMinValue, event.startDate, '>', moment(params.returningDate)
503
- .add(gracePeriodMinValue, 'seconds'), '?');
504
- return moment(event.startDate)
505
- .isAfter(moment(params.returningDate)
506
- .add(gracePeriodMinValue, 'seconds'));
507
- });
508
- }
509
- let satisfyGracePeriodInDaysMax = true;
510
- let satisfyGracePeriodInDaysMin = true;
511
- const gracePeriodBeforeStartInDaysMax = (_g = (_f = offerItemCondition.itemOffered.serviceOutput) === null || _f === void 0 ? void 0 : _f.reservationFor.gracePeriodBeforeStartInDays) === null || _g === void 0 ? void 0 : _g.max;
512
- if (typeof (gracePeriodBeforeStartInDaysMax === null || gracePeriodBeforeStartInDaysMax === void 0 ? void 0 : gracePeriodBeforeStartInDaysMax.period.value) === 'number'
513
- && typeof gracePeriodBeforeStartInDaysMax.time === 'string') {
514
- satisfyGracePeriodInDaysMax = params.events.every((event) => {
515
- const maxDate = moment(event.startDate)
516
- .tz(gracePeriodBeforeStartInDaysMax.timezone)
517
- .startOf('days')
518
- .subtract(gracePeriodBeforeStartInDaysMax.period.value, 'days')
519
- .format('YYYY-MM-DD');
520
- const returnMinDate = moment.tz(`${maxDate}T${gracePeriodBeforeStartInDaysMax.time}`, gracePeriodBeforeStartInDaysMax.timezone);
521
- debug('returnMinDate:', returnMinDate, 'returningDate:', returningDate);
522
- return returnMinDate.isSameOrBefore(moment(returningDate));
523
- });
524
- }
525
- debug('gracePeriodBeforeStartInDaysMax:', gracePeriodBeforeStartInDaysMax);
526
- const gracePeriodBeforeStartInDaysMin = (_j = (_h = offerItemCondition.itemOffered.serviceOutput) === null || _h === void 0 ? void 0 : _h.reservationFor.gracePeriodBeforeStartInDays) === null || _j === void 0 ? void 0 : _j.min;
527
- if (typeof (gracePeriodBeforeStartInDaysMin === null || gracePeriodBeforeStartInDaysMin === void 0 ? void 0 : gracePeriodBeforeStartInDaysMin.period.value) === 'number'
528
- && typeof gracePeriodBeforeStartInDaysMin.time === 'string') {
529
- satisfyGracePeriodInDaysMin = params.events.every((event) => {
530
- const minDate = moment(event.startDate)
531
- .tz(gracePeriodBeforeStartInDaysMin.timezone)
532
- .startOf('days')
533
- .subtract(gracePeriodBeforeStartInDaysMin.period.value, 'days')
534
- .format('YYYY-MM-DD');
535
- const returnMaxDate = moment.tz(`${minDate}T${gracePeriodBeforeStartInDaysMin.time}`, gracePeriodBeforeStartInDaysMin.timezone);
536
- debug('returnMaxDate:', returnMaxDate, 'returningDate:', returningDate);
537
- return returnMaxDate.isAfter(moment(returningDate));
538
- });
539
- }
540
- debug('satisfyGracePeriodInDaysMin:', satisfyGracePeriodInDaysMin);
541
- let satisfyOnlyUnused = true;
542
- if (((_k = offerItemCondition.itemOffered.serviceOutput) === null || _k === void 0 ? void 0 : _k.onlyUnused) === true) {
543
- if (params.usedReservationExists) {
544
- satisfyOnlyUnused = false;
545
- }
546
- }
547
- debug('usedReservationExists:', params.usedReservationExists, 'satisfyOnlyUnused:', satisfyOnlyUnused);
548
- satisfyItemCondition = satisfyGracePeriodMaxValue && satisfyGracePeriodMinValue
549
- && satisfyGracePeriodInDaysMax && satisfyGracePeriodInDaysMin && satisfyOnlyUnused;
550
- }
551
- return satisfyMerchantReturnDays && satisfyApplicablePaymentMethod && satisfyItemCondition;
552
- }
553
- /**
554
- * 注文中のオファーの返品ポリシーを検証
555
- */
556
- function validateOffersReturnPolicy(params) {
557
- // オファーに返品ポリシーが設定されているか?
558
- const everyOffersHaveReturnPolicy = params.offers.every((offer) => {
559
- return Array.isArray(offer.hasMerchantReturnPolicy) && offer.hasMerchantReturnPolicy.length > 0;
560
- });
561
- if (!everyOffersHaveReturnPolicy) {
562
- throw new factory.errors.NotFound('offer.hasMerchantReturnPolicy');
563
- }
564
- let returnFees;
565
- // 返品手数料設定はどうか?
566
- const somePolicyWithReturnFeesCustomerResponsibility = params.policiesByOffer.some((policy) => {
567
- return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
568
- });
569
- const somePolicyWithRestockingFees = params.policiesByOffer.some((policy) => {
570
- return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
571
- });
572
- const everyPolicyWithFreeReturn = params.policiesByOffer.every((policy) => {
573
- return policy.customerRemorseReturnFees === factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
574
- });
575
- if (somePolicyWithReturnFeesCustomerResponsibility) {
576
- // ひとつでも返金なしがあれば返金なし
577
- returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.ReturnFeesCustomerResponsibility;
578
- }
579
- else if (somePolicyWithRestockingFees) {
580
- // ひとつでも手数料あり返金があれば手数料あり返金
581
- returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.RestockingFees;
582
- }
583
- else if (everyPolicyWithFreeReturn) {
584
- // 全ポリシーが手数料なしであれば手数料なし返金
585
- returnFees = factory.merchantReturnPolicy.ReturnFeesEnumeration.FreeReturn;
586
- }
587
- else {
588
- throw new factory.errors.NotImplemented('returnFees not defined');
589
- }
590
- // 決済カード取消ポリシーを確定(2023-05-23~)
591
- const returnFeesMovieTicket = [];
592
- params.acceptedOffers.forEach((acceptedOffer) => {
593
- var _a, _b;
594
- const unitPriceOffer = params.offers.find((offer) => offer.id === acceptedOffer.id);
595
- if (unitPriceOffer === undefined) {
596
- throw new factory.errors.NotFound(`UnitPriceOffer ${acceptedOffer.id}`);
597
- }
598
- if (!Array.isArray(unitPriceOffer.hasMerchantReturnPolicy) || unitPriceOffer.hasMerchantReturnPolicy.length === 0) {
599
- throw new factory.errors.NotFound(`offer.hasMerchantReturnPolicy ${acceptedOffer.id}`);
600
- }
601
- const hasMerchantReturnPolicy = unitPriceOffer.hasMerchantReturnPolicy[0];
602
- const policyByOffer = params.policiesByOffer.find((policy) => policy.id === hasMerchantReturnPolicy.id);
603
- if (policyByOffer === undefined) {
604
- throw new factory.errors.NotFound(`MerchantReturnPolicy acceptedOffer:${acceptedOffer.id}`);
605
- }
606
- const movieTicketTypeChargeSpecExists = (_a = acceptedOffer.priceSpecification) === null || _a === void 0 ? void 0 : _a.priceComponent.some((component) => {
607
- return component.typeOf === factory.priceSpecificationType.MovieTicketTypeChargeSpecification;
608
- });
609
- if (movieTicketTypeChargeSpecExists === true) {
610
- (_b = acceptedOffer.priceSpecification) === null || _b === void 0 ? void 0 : _b.priceComponent.forEach((component) => {
611
- if (component.typeOf === factory.priceSpecificationType.UnitPriceSpecification) {
612
- if (Array.isArray(component.appliesToMovieTicket)) {
613
- component.appliesToMovieTicket.forEach((appliesToMovieTicket) => {
614
- returnFeesMovieTicket.push({
615
- identifier: String(appliesToMovieTicket.identifier),
616
- returnFees: policyByOffer.customerRemorseReturnFeesMovieTicket,
617
- serviceOutput: { typeOf: appliesToMovieTicket.serviceOutput.typeOf }
618
- });
619
- });
620
- }
621
- }
622
- });
623
- }
624
- });
625
- return { returnFees, returnFeesMovieTicket };
626
- }
627
238
  function validateAppliedReturnPolicy(params) {
628
239
  var _a;
629
240
  const appliedReturnPolicy = params.merchantReturnPolicy;
package/package.json CHANGED
@@ -11,8 +11,8 @@
11
11
  "dependencies": {
12
12
  "@aws-sdk/client-cognito-identity-provider": "3.600.0",
13
13
  "@aws-sdk/credential-providers": "3.600.0",
14
- "@chevre/factory": "4.394.0-alpha.3",
15
- "@cinerino/sdk": "10.21.0-alpha.38",
14
+ "@chevre/factory": "4.394.0-alpha.5",
15
+ "@cinerino/sdk": "10.21.0-alpha.41",
16
16
  "@motionpicture/coa-service": "9.6.0",
17
17
  "@motionpicture/gmo-service": "5.3.0",
18
18
  "@sendgrid/client": "8.1.4",
@@ -113,5 +113,5 @@
113
113
  "postversion": "git push origin --tags",
114
114
  "prepublishOnly": "npm run clean && npm run build && npm test && npm run doc"
115
115
  },
116
- "version": "22.10.0-alpha.12"
116
+ "version": "22.10.0-alpha.13"
117
117
  }