@chevre/domain 22.10.0-alpha.9 → 22.10.0
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.
- package/example/src/chevre/adminIdentities.ts +8 -8
- package/example/src/chevre/assetTransaction/processReserve.ts +4 -1
- package/example/src/chevre/concurrentLock/lockOfferRateLimit.ts +64 -0
- package/example/src/chevre/concurrentLock/lockTransactionProcess.ts +44 -0
- package/example/src/chevre/createTaskIfNotExistByAlternateName.ts +1 -1
- package/example/src/chevre/findOneAvailableHours.ts +11 -11
- package/example/src/chevre/identity/getCommonClients.ts +126 -0
- package/example/src/chevre/identity/migrateClients2oauth.ts +200 -0
- package/example/src/chevre/issuer/adminMemberProgramTiers.ts +55 -0
- package/example/src/chevre/maintenance/checkTransactionStatuses.ts +105 -0
- package/example/src/chevre/migrateIdentities.ts +24 -37
- package/example/src/chevre/reIndex.ts +1 -1
- package/example/src/chevre/roles/addPermissionIfNotExists.ts +27 -0
- package/example/src/chevre/roles/addRoleMembers.ts +75 -0
- package/example/src/chevre/saveWebSite.ts +14 -17
- package/example/src/chevre/stockHolder/checkRedisKeyCount.ts +43 -22
- package/example/src/chevre/transactionNumber/publishConfimationNumber.ts +37 -0
- package/example/src/chevre/transactionNumber/publishOrderNumber.ts +40 -0
- package/example/src/chevre/transactionNumber/setUseMongo4confirmationNumberFrom.ts +45 -0
- package/example/src/chevre/transactionNumber/setUseMongo4orderNumberFrom.ts +41 -0
- package/example/src/chevre/transactionNumber/setUseMongo4transactionNumberFrom.ts +41 -0
- package/example/src/redisMulti.ts +63 -0
- package/example/src/signPayload.ts +1 -1
- package/lib/chevre/eventEmitter/task.d.ts +36 -6
- package/lib/chevre/eventEmitter/task.js +5 -4
- package/lib/chevre/eventEmitter.d.ts +2 -2
- package/lib/chevre/eventEmitter.js +2 -2
- package/lib/chevre/repo/concurrentLock.d.ts +14 -0
- package/lib/chevre/repo/concurrentLock.js +48 -0
- package/lib/chevre/repo/concurrentLockAbstract.d.ts +42 -0
- package/lib/chevre/repo/concurrentLockAbstract.js +9 -0
- package/lib/chevre/repo/confirmationNumber.d.ts +17 -4
- package/lib/chevre/repo/confirmationNumber.js +89 -32
- package/lib/chevre/repo/identity.d.ts +42 -5
- package/lib/chevre/repo/identity.js +35 -4
- package/lib/chevre/repo/issuer.d.ts +10 -2
- package/lib/chevre/repo/member.js +2 -2
- package/lib/chevre/repo/memberProgram.d.ts +43 -2
- package/lib/chevre/repo/memberProgram.js +79 -8
- package/lib/chevre/repo/mongoose/schemas/issuer.d.ts +3 -1
- package/lib/chevre/repo/mongoose/schemas/issuer.js +10 -0
- package/lib/chevre/repo/mongoose/schemas/offer/event.js +30 -2
- package/lib/chevre/repo/mongoose/schemas/role.d.ts +2 -3
- package/lib/chevre/repo/mongoose/schemas/role.js +11 -1
- package/lib/chevre/repo/mongoose/schemas/setting.d.ts +3 -0
- package/lib/chevre/repo/mongoose/schemas/setting.js +4 -1
- package/lib/chevre/repo/mongoose/schemas/transactionNumber.d.ts +39 -0
- package/lib/chevre/repo/mongoose/schemas/transactionNumber.js +101 -0
- package/lib/chevre/repo/orderNumber.d.ts +15 -4
- package/lib/chevre/repo/orderNumber.js +71 -24
- package/lib/chevre/repo/passport.d.ts +1 -1
- package/lib/chevre/repo/passport.js +31 -13
- package/lib/chevre/repo/rateLimit/offer.d.ts +7 -2
- package/lib/chevre/repo/rateLimit/offer.js +41 -40
- package/lib/chevre/repo/role.d.ts +18 -4
- package/lib/chevre/repo/role.js +53 -4
- package/lib/chevre/repo/serviceOutputIdentifier.d.ts +8 -4
- package/lib/chevre/repo/serviceOutputIdentifier.js +54 -22
- package/lib/chevre/repo/stockHolder.d.ts +0 -2
- package/lib/chevre/repo/stockHolder.js +24 -31
- package/lib/chevre/repo/task.d.ts +10 -25
- package/lib/chevre/repo/task.js +65 -36
- package/lib/chevre/repo/transactionNumber.d.ts +15 -4
- package/lib/chevre/repo/transactionNumber.js +67 -22
- package/lib/chevre/repo/transactionNumberCounter.d.ts +28 -0
- package/lib/chevre/repo/transactionNumberCounter.js +128 -0
- package/lib/chevre/repo/transactionProcess.d.ts +7 -4
- package/lib/chevre/repo/transactionProcess.js +34 -13
- package/lib/chevre/service/aggregation/event/aggregateOffers.js +1 -0
- package/lib/chevre/service/assetTransaction/reserve/start.js +9 -1
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest.js +1 -1
- package/lib/chevre/service/code.js +1 -1
- package/lib/chevre/service/offer/event/checkAvailability.d.ts +1 -1
- package/lib/chevre/service/offer/event/checkAvailability.js +1 -0
- package/lib/chevre/service/offer/product.js +0 -40
- package/lib/chevre/service/payment/any.d.ts +0 -2
- package/lib/chevre/service/payment/any.js +1 -0
- package/lib/chevre/service/reserve/cancelReservation.d.ts +3 -0
- package/lib/chevre/service/reserve/cancelReservation.js +5 -1
- package/lib/chevre/service/task/acceptCOAOffer.js +2 -2
- package/lib/chevre/service/task/authorizePayment.js +4 -4
- package/lib/chevre/service/task/givePointAward.js +1 -1
- package/lib/chevre/service/task/moneyTransfer.js +1 -1
- package/lib/chevre/service/task/publishPaymentUrl.js +2 -2
- package/lib/chevre/service/task/refund.js +1 -1
- package/lib/chevre/service/task/returnMoneyTransfer.js +1 -1
- package/lib/chevre/service/task/returnPayTransaction.js +1 -1
- package/lib/chevre/service/task/returnPointAward.js +1 -1
- package/lib/chevre/service/task/returnReserveTransaction.js +1 -1
- package/lib/chevre/service/task.d.ts +8 -17
- package/lib/chevre/service/task.js +14 -5
- package/lib/chevre/service/transaction/placeOrder/start/validateStartRequest.js +2 -2
- package/lib/chevre/service/transaction/returnOrder/preStart/factory.d.ts +20 -0
- package/lib/chevre/service/transaction/returnOrder/preStart/factory.js +2 -0
- package/lib/chevre/service/transaction/returnOrder/preStart/findApplicableReturnPolicy.d.ts +23 -0
- package/lib/chevre/service/transaction/returnOrder/preStart/findApplicableReturnPolicy.js +323 -0
- package/lib/chevre/service/transaction/returnOrder/preStart/getReturnPolicyByProject.d.ts +13 -0
- package/lib/chevre/service/transaction/returnOrder/preStart/getReturnPolicyByProject.js +132 -0
- package/lib/chevre/service/transaction/returnOrder/preStart.js +2 -391
- package/package.json +3 -3
- package/example/src/chevre/migrateMembers2identities.ts +0 -109
- package/example/src/chevre/publishConfimationNumber.ts +0 -27
|
@@ -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
|
+
}
|