@unchainedshop/plugins 5.0.0-alpha.2 → 5.0.0-alpha.3
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/lib/events/aws-eventbridge.d.ts +7 -1
- package/lib/events/aws-eventbridge.js +5 -11
- package/lib/events/redis.d.ts +3 -1
- package/lib/events/redis.js +5 -5
- package/lib/files/gridfs/api.js +1 -1
- package/lib/files/gridfs/handler-express.js +1 -1
- package/lib/payment/datatrans-v2/adapter.js +12 -9
- package/lib/payment/datatrans-v2/build3DSCardholder.d.ts +12 -0
- package/lib/payment/datatrans-v2/build3DSCardholder.js +44 -0
- package/lib/payment/paypal-checkout.js +17 -5
- package/lib/payment/stripe/stripe.js +1 -1
- package/lib/presets/base.js +4 -0
- package/lib/presets/countries/eu.d.ts +1 -0
- package/lib/presets/countries/eu.js +7 -0
- package/lib/presets/countries/uk.d.ts +1 -0
- package/lib/presets/countries/uk.js +7 -0
- package/lib/presets/countries/us.d.ts +1 -0
- package/lib/presets/countries/us.js +7 -0
- package/lib/pricing/delivery-eu-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-eu-tax/adapter.js +55 -0
- package/lib/pricing/delivery-eu-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-eu-tax/index.js +10 -0
- package/lib/pricing/delivery-eu-tax.d.ts +2 -0
- package/lib/pricing/delivery-eu-tax.js +55 -0
- package/lib/pricing/delivery-swiss-tax/adapter.js +7 -26
- package/lib/pricing/delivery-swiss-tax.js +7 -26
- package/lib/pricing/delivery-uk-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-uk-tax/adapter.js +43 -0
- package/lib/pricing/delivery-uk-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-uk-tax/index.js +10 -0
- package/lib/pricing/delivery-uk-tax.d.ts +2 -0
- package/lib/pricing/delivery-uk-tax.js +43 -0
- package/lib/pricing/delivery-us-sales-tax/adapter.d.ts +3 -0
- package/lib/pricing/delivery-us-sales-tax/adapter.js +58 -0
- package/lib/pricing/delivery-us-sales-tax/index.d.ts +4 -0
- package/lib/pricing/delivery-us-sales-tax/index.js +10 -0
- package/lib/pricing/delivery-us-sales-tax.d.ts +2 -0
- package/lib/pricing/delivery-us-sales-tax.js +58 -0
- package/lib/pricing/product-eu-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-eu-tax/adapter.js +56 -0
- package/lib/pricing/product-eu-tax/index.d.ts +4 -0
- package/lib/pricing/product-eu-tax/index.js +10 -0
- package/lib/pricing/product-eu-tax.d.ts +2 -0
- package/lib/pricing/product-eu-tax.js +56 -0
- package/lib/pricing/product-quotation-price.d.ts +2 -0
- package/lib/pricing/product-quotation-price.js +40 -0
- package/lib/pricing/product-swiss-tax/adapter.js +7 -26
- package/lib/pricing/product-swiss-tax.js +7 -26
- package/lib/pricing/product-uk-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-uk-tax/adapter.js +57 -0
- package/lib/pricing/product-uk-tax/index.d.ts +4 -0
- package/lib/pricing/product-uk-tax/index.js +10 -0
- package/lib/pricing/product-uk-tax.d.ts +2 -0
- package/lib/pricing/product-uk-tax.js +57 -0
- package/lib/pricing/product-us-sales-tax/adapter.d.ts +3 -0
- package/lib/pricing/product-us-sales-tax/adapter.js +52 -0
- package/lib/pricing/product-us-sales-tax/index.d.ts +4 -0
- package/lib/pricing/product-us-sales-tax/index.js +10 -0
- package/lib/pricing/product-us-sales-tax.d.ts +2 -0
- package/lib/pricing/product-us-sales-tax.js +52 -0
- package/lib/pricing/tax/applyTaxRateToTaxableRows.d.ts +23 -0
- package/lib/pricing/tax/applyTaxRateToTaxableRows.js +30 -0
- package/lib/pricing/tax/ch-tax-rates.json +24 -0
- package/lib/pricing/tax/ch.js +6 -30
- package/lib/pricing/tax/eraRates.d.ts +10 -0
- package/lib/pricing/tax/eraRates.js +15 -0
- package/lib/pricing/tax/eu-tax-rates.json +797 -0
- package/lib/pricing/tax/eu.d.ts +12 -0
- package/lib/pricing/tax/eu.js +38 -0
- package/lib/pricing/tax/uk-tax-rates.json +18 -0
- package/lib/pricing/tax/uk.d.ts +10 -0
- package/lib/pricing/tax/uk.js +23 -0
- package/lib/pricing/tax/us-tax-rates.json +334 -0
- package/lib/pricing/tax/us.d.ts +11 -0
- package/lib/pricing/tax/us.js +20 -0
- package/lib/pricing/utils/isDeliveryAddressInCountry.d.ts +1 -1
- package/lib/pricing/utils/isDeliveryAddressInCountry.js +3 -8
- package/lib/pricing/utils/resolveDeliveryLocation.d.ts +10 -0
- package/lib/pricing/utils/resolveDeliveryLocation.js +9 -0
- package/lib/quotations/manual/adapter.js +6 -1
- package/lib/quotations/manual.js +6 -1
- package/lib/worker/gc-guests/adapter.d.ts +9 -0
- package/lib/worker/gc-guests/adapter.js +56 -0
- package/lib/worker/gc-guests/index.d.ts +4 -0
- package/lib/worker/gc-guests/index.js +13 -0
- package/lib/worker/gc-guests.d.ts +8 -0
- package/lib/worker/gc-guests.js +55 -0
- package/lib/worker/invalidate-carts/adapter.d.ts +9 -0
- package/lib/worker/invalidate-carts/adapter.js +52 -0
- package/lib/worker/invalidate-carts/index.d.ts +4 -0
- package/lib/worker/invalidate-carts/index.js +13 -0
- package/lib/worker/invalidate-carts.d.ts +8 -0
- package/lib/worker/invalidate-carts.js +51 -0
- package/lib/worker/zombie-killer/adapter.d.ts +2 -0
- package/lib/worker/zombie-killer/adapter.js +26 -3
- package/lib/worker/zombie-killer/index.js +4 -1
- package/lib/worker/zombie-killer.d.ts +1 -0
- package/lib/worker/zombie-killer.js +24 -3
- package/package.json +24 -7
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { EmitAdapter } from '@unchainedshop/events';
|
|
2
|
+
export declare const EventBridgeEventEmitter: ({ region, source, busName }: {
|
|
3
|
+
region: any;
|
|
4
|
+
source: any;
|
|
5
|
+
busName: any;
|
|
6
|
+
}) => Promise<EmitAdapter>;
|
|
7
|
+
export default EventBridgeEventEmitter;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { setEmitAdapter } from '@unchainedshop/events';
|
|
2
1
|
import { createLogger } from '@unchainedshop/logger';
|
|
3
2
|
const logger = createLogger('unchained:eventbridge');
|
|
4
|
-
const EventBridgeEventEmitter = async ({ region, source, busName }) => {
|
|
3
|
+
export const EventBridgeEventEmitter = async ({ region, source, busName }) => {
|
|
5
4
|
const { EventBridgeClient, PutEventsCommand } = await import('@aws-sdk/client-eventbridge');
|
|
6
5
|
const ebClient = new EventBridgeClient({ region });
|
|
7
6
|
return {
|
|
@@ -24,14 +23,9 @@ const EventBridgeEventEmitter = async ({ region, source, busName }) => {
|
|
|
24
23
|
subscribe: () => {
|
|
25
24
|
throw new Error("You can't subscribe to EventBridge connected Events");
|
|
26
25
|
},
|
|
26
|
+
shutdown: () => {
|
|
27
|
+
ebClient.destroy();
|
|
28
|
+
},
|
|
27
29
|
};
|
|
28
30
|
};
|
|
29
|
-
|
|
30
|
-
if (EVENT_BRIDGE_REGION && EVENT_BRIDGE_SOURCE && EVENT_BRIDGE_BUS_NAME) {
|
|
31
|
-
const eventBridgeAdapter = await EventBridgeEventEmitter({
|
|
32
|
-
source: EVENT_BRIDGE_SOURCE,
|
|
33
|
-
region: EVENT_BRIDGE_REGION,
|
|
34
|
-
busName: EVENT_BRIDGE_BUS_NAME,
|
|
35
|
-
});
|
|
36
|
-
setEmitAdapter(eventBridgeAdapter);
|
|
37
|
-
}
|
|
31
|
+
export default EventBridgeEventEmitter;
|
package/lib/events/redis.d.ts
CHANGED
package/lib/events/redis.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createClient } from '@redis/client';
|
|
2
|
-
import { setEmitAdapter } from '@unchainedshop/events';
|
|
3
2
|
const { REDIS_PORT = '6379', REDIS_HOST, REDIS_DB = '0' } = process.env;
|
|
4
3
|
const subscribedEvents = new Set();
|
|
5
|
-
const RedisEventEmitter = () => {
|
|
4
|
+
export const RedisEventEmitter = () => {
|
|
6
5
|
const redisPublisher = createClient({
|
|
7
6
|
url: `redis://${REDIS_HOST}:${REDIS_PORT}`,
|
|
8
7
|
database: parseInt(REDIS_DB, 10),
|
|
@@ -21,8 +20,9 @@ const RedisEventEmitter = () => {
|
|
|
21
20
|
subscribedEvents.add(eventName);
|
|
22
21
|
}
|
|
23
22
|
},
|
|
23
|
+
shutdown: async () => {
|
|
24
|
+
await Promise.allSettled([redisPublisher.close(), redisSubscriber.close()]);
|
|
25
|
+
},
|
|
24
26
|
};
|
|
25
27
|
};
|
|
26
|
-
|
|
27
|
-
setEmitAdapter(RedisEventEmitter());
|
|
28
|
-
}
|
|
28
|
+
export default RedisEventEmitter;
|
package/lib/files/gridfs/api.js
CHANGED
|
@@ -87,7 +87,7 @@ export const gridfsRouteHandler = async (request, context) => {
|
|
|
87
87
|
const signature = url.searchParams.get('s');
|
|
88
88
|
const expiryTimestamp = url.searchParams.get('e');
|
|
89
89
|
const fileDocument = await modules.files.findFile({
|
|
90
|
-
url: `${GRIDFS_PUT_SERVER_PATH}/${directoryName}/${fileName}`,
|
|
90
|
+
url: `${GRIDFS_PUT_SERVER_PATH}/${directoryName}/${encodeURIComponent(fileName)}`,
|
|
91
91
|
});
|
|
92
92
|
if (!fileDocument) {
|
|
93
93
|
logger.error('File not found', { fileName });
|
|
@@ -59,7 +59,7 @@ const gridfsHandler = async (req, res) => {
|
|
|
59
59
|
if (req.method === 'GET') {
|
|
60
60
|
const { s: signature, e: expiryTimestamp } = req.query;
|
|
61
61
|
const fileDocument = await modules.files.findFile({
|
|
62
|
-
url: `${GRIDFS_PUT_SERVER_PATH}/${directoryName}/${fileName}`,
|
|
62
|
+
url: `${GRIDFS_PUT_SERVER_PATH}/${directoryName}/${encodeURIComponent(fileName)}`,
|
|
63
63
|
});
|
|
64
64
|
if (fileDocument?.meta?.isPrivate) {
|
|
65
65
|
const expiry = parseInt(expiryTimestamp, 10);
|
|
@@ -2,6 +2,7 @@ import { createLogger } from '@unchainedshop/logger';
|
|
|
2
2
|
import createDatatransAPI from "./api/index.js";
|
|
3
3
|
import parseRegistrationData from "./parseRegistrationData.js";
|
|
4
4
|
import roundedAmountFromOrder from "./roundedAmountFromOrder.js";
|
|
5
|
+
import build3DSCardholder, { withCardCardholder, withSecureFieldsCardholder, } from "./build3DSCardholder.js";
|
|
5
6
|
import { PaymentAdapter, PaymentError, PaymentPricingRowCategory, PaymentPricingSheet, OrderPricingSheet, } from '@unchainedshop/core';
|
|
6
7
|
const logger = createLogger('unchained:datatrans');
|
|
7
8
|
const { DATATRANS_SECRET, DATATRANS_SIGN_KEY, DATATRANS_API_ENDPOINT = 'https://api.sandbox.datatrans.com', DATATRANS_MERCHANT_ID, } = process.env;
|
|
@@ -221,22 +222,18 @@ export const Datatrans = {
|
|
|
221
222
|
const price = order
|
|
222
223
|
? roundedAmountFromOrder(order)
|
|
223
224
|
: {};
|
|
225
|
+
const cardholder = build3DSCardholder(order);
|
|
224
226
|
if (useSecureFields) {
|
|
225
227
|
const result = await api().secureFields({
|
|
226
|
-
...arbitraryFields,
|
|
228
|
+
...withSecureFieldsCardholder(arbitraryFields, cardholder),
|
|
227
229
|
currency: price.currencyCode || 'CHF',
|
|
228
|
-
refno,
|
|
229
|
-
refno2,
|
|
230
|
-
customer: {
|
|
231
|
-
id: userId,
|
|
232
|
-
},
|
|
233
230
|
amount: price.amount,
|
|
234
231
|
});
|
|
235
232
|
throwIfResponseError(result);
|
|
236
233
|
return JSON.stringify(result);
|
|
237
234
|
}
|
|
238
235
|
const result = await api().init({
|
|
239
|
-
...arbitraryFields,
|
|
236
|
+
...withCardCardholder(arbitraryFields, cardholder),
|
|
240
237
|
currency: price.currencyCode || 'CHF',
|
|
241
238
|
refno,
|
|
242
239
|
refno2,
|
|
@@ -349,11 +346,17 @@ export const Datatrans = {
|
|
|
349
346
|
if (status === 'authenticated') {
|
|
350
347
|
if (authorizeAuthenticated) {
|
|
351
348
|
checkIfTransactionAmountValid(transactionId, transaction);
|
|
349
|
+
const { orderPayment, order } = context;
|
|
350
|
+
const userId = order?.userId || context?.userId;
|
|
351
|
+
const refno = orderPayment
|
|
352
|
+
? Buffer.from(orderPayment._id, 'hex').toString('base64')
|
|
353
|
+
: transaction.refno;
|
|
354
|
+
const refno2 = userId || transaction.refno2;
|
|
352
355
|
await authorizeAuth({
|
|
353
356
|
...(authorizeAuthenticated || {}),
|
|
354
357
|
transactionId,
|
|
355
|
-
refno
|
|
356
|
-
refno2
|
|
358
|
+
refno,
|
|
359
|
+
refno2,
|
|
357
360
|
});
|
|
358
361
|
status = 'authorized';
|
|
359
362
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Order } from '@unchainedshop/core-orders';
|
|
2
|
+
export interface Cardholder {
|
|
3
|
+
cardholderName?: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
homePhone?: {
|
|
6
|
+
cc: string;
|
|
7
|
+
subscriber: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export default function build3DSCardholder(order?: Order): Cardholder | undefined;
|
|
11
|
+
export declare const withCardCardholder: (arbitraryFields: any, cardholder?: Cardholder) => any;
|
|
12
|
+
export declare const withSecureFieldsCardholder: (arbitraryFields: any, cardholder?: Cardholder) => any;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { phoneNumberToParts } from '@unchainedshop/utils';
|
|
2
|
+
export default function build3DSCardholder(order) {
|
|
3
|
+
if (!order)
|
|
4
|
+
return undefined;
|
|
5
|
+
const { billingAddress, contact } = order;
|
|
6
|
+
const cardholderName = [billingAddress?.firstName, billingAddress?.lastName].filter(Boolean).join(' ');
|
|
7
|
+
const homePhone = phoneNumberToParts(contact?.telNumber, billingAddress?.countryCode);
|
|
8
|
+
const cardholder = {};
|
|
9
|
+
if (cardholderName)
|
|
10
|
+
cardholder.cardholderName = cardholderName;
|
|
11
|
+
if (contact?.emailAddress)
|
|
12
|
+
cardholder.email = contact.emailAddress;
|
|
13
|
+
if (homePhone)
|
|
14
|
+
cardholder.homePhone = homePhone;
|
|
15
|
+
if (Object.keys(cardholder).length === 0)
|
|
16
|
+
return undefined;
|
|
17
|
+
return cardholder;
|
|
18
|
+
}
|
|
19
|
+
const mergeCardholder = (container, cardholder) => {
|
|
20
|
+
const threeDS = container?.['3D'] || {};
|
|
21
|
+
return {
|
|
22
|
+
...container,
|
|
23
|
+
'3D': {
|
|
24
|
+
...threeDS,
|
|
25
|
+
cardholder: {
|
|
26
|
+
...cardholder,
|
|
27
|
+
...(threeDS.cardholder || {}),
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export const withCardCardholder = (arbitraryFields, cardholder) => {
|
|
33
|
+
if (!cardholder)
|
|
34
|
+
return arbitraryFields;
|
|
35
|
+
return {
|
|
36
|
+
...arbitraryFields,
|
|
37
|
+
card: mergeCardholder(arbitraryFields?.card, cardholder),
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export const withSecureFieldsCardholder = (arbitraryFields, cardholder) => {
|
|
41
|
+
if (!cardholder)
|
|
42
|
+
return arbitraryFields;
|
|
43
|
+
return mergeCardholder(arbitraryFields, cardholder);
|
|
44
|
+
};
|
|
@@ -58,19 +58,31 @@ const PaypalCheckout = {
|
|
|
58
58
|
throw new Error('You have to provide orderID in paymentContext');
|
|
59
59
|
}
|
|
60
60
|
try {
|
|
61
|
-
const request = new checkoutNodeJssdk.orders.OrdersGetRequest(orderID);
|
|
62
61
|
const client = new checkoutNodeJssdk.core.PayPalHttpClient(environment());
|
|
63
|
-
const
|
|
62
|
+
const getRequest = new checkoutNodeJssdk.orders.OrdersGetRequest(orderID);
|
|
63
|
+
let paypalResult = (await client.execute(getRequest)).result;
|
|
64
|
+
if (paypalResult.status === 'APPROVED') {
|
|
65
|
+
const captureRequest = new checkoutNodeJssdk.orders.OrdersCaptureRequest(orderID);
|
|
66
|
+
captureRequest.requestBody({});
|
|
67
|
+
paypalResult = (await client.execute(captureRequest)).result;
|
|
68
|
+
}
|
|
69
|
+
if (paypalResult.status !== 'COMPLETED') {
|
|
70
|
+
throw new Error(`PayPal order not completed (status: ${paypalResult.status})`);
|
|
71
|
+
}
|
|
72
|
+
const capture = paypalResult.purchase_units?.[0]?.payments?.captures?.find((c) => c.status === 'COMPLETED');
|
|
73
|
+
if (!capture) {
|
|
74
|
+
throw new Error('PayPal order has no completed capture');
|
|
75
|
+
}
|
|
64
76
|
const pricing = OrderPricingSheet({
|
|
65
77
|
calculation: order.calculation,
|
|
66
78
|
currencyCode: order.currencyCode,
|
|
67
79
|
});
|
|
68
80
|
const ourTotal = roundToDecimals(pricing.total({ useNetPrice: false }).amount / 100, 2);
|
|
69
|
-
const
|
|
70
|
-
if (ourTotal ===
|
|
81
|
+
const paidTotal = roundToDecimals(capture.amount.value, 2);
|
|
82
|
+
if (ourTotal === paidTotal && capture.amount.currency_code === order.currencyCode) {
|
|
71
83
|
return order;
|
|
72
84
|
}
|
|
73
|
-
logger.warn('Missmatch PAYPAL ORDER', JSON.stringify(
|
|
85
|
+
logger.warn('Missmatch PAYPAL ORDER', JSON.stringify(paypalResult, null, 2));
|
|
74
86
|
logger.debug('OUR ORDER', order);
|
|
75
87
|
logger.debug('OUR PRICE', pricing);
|
|
76
88
|
throw new Error(`Payment mismatch`);
|
package/lib/presets/base.js
CHANGED
|
@@ -19,6 +19,8 @@ import { LicensedEnrollmentsPlugin } from "../enrollments/licensed/index.js";
|
|
|
19
19
|
import { NodeEventEmitter } from "../events/node-event-emitter.js";
|
|
20
20
|
import { BulkImportPlugin } from "../worker/bulk-import/index.js";
|
|
21
21
|
import { ZombieKillerPlugin } from "../worker/zombie-killer/index.js";
|
|
22
|
+
import { GCGuestsPlugin } from "../worker/gc-guests/index.js";
|
|
23
|
+
import { InvalidateCartsPlugin } from "../worker/invalidate-carts/index.js";
|
|
22
24
|
import { MessagePlugin } from "../worker/message/index.js";
|
|
23
25
|
import { ExternalPlugin } from "../worker/external/index.js";
|
|
24
26
|
import { HttpRequestPlugin } from "../worker/http-request/index.js";
|
|
@@ -46,6 +48,8 @@ export function registerBasePlugins() {
|
|
|
46
48
|
setEmitAdapter(NodeEventEmitter());
|
|
47
49
|
pluginRegistry.register(BulkImportPlugin);
|
|
48
50
|
pluginRegistry.register(ZombieKillerPlugin);
|
|
51
|
+
pluginRegistry.register(GCGuestsPlugin);
|
|
52
|
+
pluginRegistry.register(InvalidateCartsPlugin);
|
|
49
53
|
pluginRegistry.register(MessagePlugin);
|
|
50
54
|
pluginRegistry.register(ExternalPlugin);
|
|
51
55
|
pluginRegistry.register(HttpRequestPlugin);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerEuTaxPlugins(): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProductEuTaxPlugin } from "../../pricing/product-eu-tax/index.js";
|
|
2
|
+
import { DeliveryEuTaxPlugin } from "../../pricing/delivery-eu-tax/index.js";
|
|
3
|
+
import { pluginRegistry } from '@unchainedshop/core';
|
|
4
|
+
export function registerEuTaxPlugins() {
|
|
5
|
+
pluginRegistry.register(ProductEuTaxPlugin);
|
|
6
|
+
pluginRegistry.register(DeliveryEuTaxPlugin);
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerUkTaxPlugins(): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProductUkTaxPlugin } from "../../pricing/product-uk-tax/index.js";
|
|
2
|
+
import { DeliveryUkTaxPlugin } from "../../pricing/delivery-uk-tax/index.js";
|
|
3
|
+
import { pluginRegistry } from '@unchainedshop/core';
|
|
4
|
+
export function registerUkTaxPlugins() {
|
|
5
|
+
pluginRegistry.register(ProductUkTaxPlugin);
|
|
6
|
+
pluginRegistry.register(DeliveryUkTaxPlugin);
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerUsSalesTaxPlugins(): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProductUsSalesTaxPlugin } from "../../pricing/product-us-sales-tax/index.js";
|
|
2
|
+
import { DeliveryUsSalesTaxPlugin } from "../../pricing/delivery-us-sales-tax/index.js";
|
|
3
|
+
import { pluginRegistry } from '@unchainedshop/core';
|
|
4
|
+
export function registerUsSalesTaxPlugins() {
|
|
5
|
+
pluginRegistry.register(ProductUsSalesTaxPlugin);
|
|
6
|
+
pluginRegistry.register(DeliveryUsSalesTaxPlugin);
|
|
7
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { isEuMemberCountry, resolveEuTaxCategoryFromDeliveryProvider, resolveEuTaxRate, } from "../tax/eu.js";
|
|
3
|
+
import resolveDeliveryLocation from "../utils/resolveDeliveryLocation.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryEuTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-eu-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply EU VAT on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
});
|
|
21
|
+
return isEuMemberCountry(countryCode);
|
|
22
|
+
},
|
|
23
|
+
actions: (params) => {
|
|
24
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
25
|
+
const { context } = params;
|
|
26
|
+
return {
|
|
27
|
+
...pricingAdapter,
|
|
28
|
+
calculate: async () => {
|
|
29
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
30
|
+
order: context.order,
|
|
31
|
+
orderDelivery: context.orderDelivery,
|
|
32
|
+
countryCode: context.countryCode,
|
|
33
|
+
});
|
|
34
|
+
const category = resolveEuTaxCategoryFromDeliveryProvider(context.provider);
|
|
35
|
+
const taxRate = resolveEuTaxRate({
|
|
36
|
+
countryCode,
|
|
37
|
+
category,
|
|
38
|
+
referenceDate: context.order?.ordered,
|
|
39
|
+
});
|
|
40
|
+
if (taxRate === null)
|
|
41
|
+
return pricingAdapter.calculate();
|
|
42
|
+
DeliveryPricingAdapter.log(`DeliveryEuTax -> Tax Multiplicator: ${taxRate}`);
|
|
43
|
+
applyTaxRateToTaxableRows({
|
|
44
|
+
calculationSheet: params.calculationSheet,
|
|
45
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
46
|
+
taxRate,
|
|
47
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
48
|
+
adapterKey: DeliveryEuTax.key,
|
|
49
|
+
});
|
|
50
|
+
return pricingAdapter.calculate();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
export default DeliveryEuTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliveryEuTax } from "./adapter.js";
|
|
3
|
+
export const DeliveryEuTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-eu-tax',
|
|
5
|
+
label: 'Delivery EU Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliveryEuTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliveryEuTaxPlugin;
|
|
10
|
+
export { DeliveryEuTax } from "./adapter.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, DeliveryPricingDirector, } from '@unchainedshop/core';
|
|
2
|
+
import { isEuMemberCountry, resolveEuTaxCategoryFromDeliveryProvider, resolveEuTaxRate, } from "./tax/eu.js";
|
|
3
|
+
import resolveDeliveryLocation from "./utils/resolveDeliveryLocation.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "./tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryEuTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-eu-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply EU VAT on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
});
|
|
21
|
+
return isEuMemberCountry(countryCode);
|
|
22
|
+
},
|
|
23
|
+
actions: (params) => {
|
|
24
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
25
|
+
const { context } = params;
|
|
26
|
+
return {
|
|
27
|
+
...pricingAdapter,
|
|
28
|
+
calculate: async () => {
|
|
29
|
+
const { countryCode } = resolveDeliveryLocation({
|
|
30
|
+
order: context.order,
|
|
31
|
+
orderDelivery: context.orderDelivery,
|
|
32
|
+
countryCode: context.countryCode,
|
|
33
|
+
});
|
|
34
|
+
const category = resolveEuTaxCategoryFromDeliveryProvider(context.provider);
|
|
35
|
+
const taxRate = resolveEuTaxRate({
|
|
36
|
+
countryCode,
|
|
37
|
+
category,
|
|
38
|
+
referenceDate: context.order?.ordered,
|
|
39
|
+
});
|
|
40
|
+
if (taxRate === null)
|
|
41
|
+
return pricingAdapter.calculate();
|
|
42
|
+
DeliveryPricingAdapter.log(`DeliveryEuTax -> Tax Multiplicator: ${taxRate}`);
|
|
43
|
+
applyTaxRateToTaxableRows({
|
|
44
|
+
calculationSheet: params.calculationSheet,
|
|
45
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
46
|
+
taxRate,
|
|
47
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
48
|
+
adapterKey: DeliveryEuTax.key,
|
|
49
|
+
});
|
|
50
|
+
return pricingAdapter.calculate();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
DeliveryPricingDirector.registerAdapter(DeliveryEuTax);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
2
|
import { resolveTaxCategoryFromDeliveryProvider, SwissTaxCategories } from "../tax/ch.js";
|
|
3
3
|
import isDeliveryAddressInCountry from "../utils/isDeliveryAddressInCountry.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
4
5
|
export const DeliverySwissTax = {
|
|
5
6
|
...DeliveryPricingAdapter,
|
|
6
7
|
key: 'shop.unchained.pricing.delivery-swiss-tax',
|
|
@@ -27,32 +28,12 @@ export const DeliverySwissTax = {
|
|
|
27
28
|
const taxCategory = resolveTaxCategoryFromDeliveryProvider(context.provider) || SwissTaxCategories.DEFAULT;
|
|
28
29
|
const taxRate = taxCategory.rate(context.order?.ordered);
|
|
29
30
|
DeliveryPricingAdapter.log(`DeliverySwissTax -> Tax Multiplicator: ${taxRate}`);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
isTaxable: false,
|
|
37
|
-
isNetPrice: false,
|
|
38
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
39
|
-
});
|
|
40
|
-
pricingAdapter.resultSheet().addTax({
|
|
41
|
-
amount: taxAmount,
|
|
42
|
-
rate: taxRate,
|
|
43
|
-
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
44
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
const taxAmount = row.amount * taxRate;
|
|
49
|
-
pricingAdapter.resultSheet().addTax({
|
|
50
|
-
amount: taxAmount,
|
|
51
|
-
rate: taxRate,
|
|
52
|
-
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
53
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
54
|
-
});
|
|
55
|
-
}
|
|
31
|
+
applyTaxRateToTaxableRows({
|
|
32
|
+
calculationSheet: params.calculationSheet,
|
|
33
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
34
|
+
taxRate,
|
|
35
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
36
|
+
adapterKey: DeliverySwissTax.key,
|
|
56
37
|
});
|
|
57
38
|
return pricingAdapter.calculate();
|
|
58
39
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, DeliveryPricingDirector, } from '@unchainedshop/core';
|
|
2
2
|
import { resolveTaxCategoryFromDeliveryProvider, SwissTaxCategories } from "./tax/ch.js";
|
|
3
3
|
import isDeliveryAddressInCountry from "./utils/isDeliveryAddressInCountry.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "./tax/applyTaxRateToTaxableRows.js";
|
|
4
5
|
export const DeliverySwissTax = {
|
|
5
6
|
...DeliveryPricingAdapter,
|
|
6
7
|
key: 'shop.unchained.pricing.delivery-swiss-tax',
|
|
@@ -27,32 +28,12 @@ export const DeliverySwissTax = {
|
|
|
27
28
|
const taxCategory = resolveTaxCategoryFromDeliveryProvider(context.provider) || SwissTaxCategories.DEFAULT;
|
|
28
29
|
const taxRate = taxCategory.rate(context.order?.ordered);
|
|
29
30
|
DeliveryPricingAdapter.log(`DeliverySwissTax -> Tax Multiplicator: ${taxRate}`);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
isTaxable: false,
|
|
37
|
-
isNetPrice: false,
|
|
38
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
39
|
-
});
|
|
40
|
-
pricingAdapter.resultSheet().addTax({
|
|
41
|
-
amount: taxAmount,
|
|
42
|
-
rate: taxRate,
|
|
43
|
-
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
44
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
const taxAmount = row.amount * taxRate;
|
|
49
|
-
pricingAdapter.resultSheet().addTax({
|
|
50
|
-
amount: taxAmount,
|
|
51
|
-
rate: taxRate,
|
|
52
|
-
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
53
|
-
meta: { adapter: DeliverySwissTax.key },
|
|
54
|
-
});
|
|
55
|
-
}
|
|
31
|
+
applyTaxRateToTaxableRows({
|
|
32
|
+
calculationSheet: params.calculationSheet,
|
|
33
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
34
|
+
taxRate,
|
|
35
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
36
|
+
adapterKey: DeliverySwissTax.key,
|
|
56
37
|
});
|
|
57
38
|
return pricingAdapter.calculate();
|
|
58
39
|
},
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DeliveryPricingRowCategory, DeliveryPricingAdapter, } from '@unchainedshop/core';
|
|
2
|
+
import { resolveUkTaxCategoryFromDeliveryProvider, UkTaxCategories, UK_VAT_COUNTRY_CODES, } from "../tax/uk.js";
|
|
3
|
+
import isDeliveryAddressInCountry from "../utils/isDeliveryAddressInCountry.js";
|
|
4
|
+
import { applyTaxRateToTaxableRows } from "../tax/applyTaxRateToTaxableRows.js";
|
|
5
|
+
export const DeliveryUkTax = {
|
|
6
|
+
...DeliveryPricingAdapter,
|
|
7
|
+
key: 'shop.unchained.pricing.delivery-uk-tax',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
label: 'Apply UK VAT on Delivery Fees',
|
|
10
|
+
orderIndex: 80,
|
|
11
|
+
isActivatedFor: (context) => {
|
|
12
|
+
if (!context.order)
|
|
13
|
+
return false;
|
|
14
|
+
if (!context.orderDelivery)
|
|
15
|
+
return false;
|
|
16
|
+
return isDeliveryAddressInCountry({
|
|
17
|
+
order: context.order,
|
|
18
|
+
orderDelivery: context.orderDelivery,
|
|
19
|
+
countryCode: context.countryCode,
|
|
20
|
+
}, UK_VAT_COUNTRY_CODES);
|
|
21
|
+
},
|
|
22
|
+
actions: (params) => {
|
|
23
|
+
const pricingAdapter = DeliveryPricingAdapter.actions(params);
|
|
24
|
+
const { context } = params;
|
|
25
|
+
return {
|
|
26
|
+
...pricingAdapter,
|
|
27
|
+
calculate: async () => {
|
|
28
|
+
const taxCategory = resolveUkTaxCategoryFromDeliveryProvider(context.provider) || UkTaxCategories.STANDARD;
|
|
29
|
+
const taxRate = taxCategory.rate(context.order?.ordered);
|
|
30
|
+
DeliveryPricingAdapter.log(`DeliveryUkTax -> Tax Multiplicator: ${taxRate}`);
|
|
31
|
+
applyTaxRateToTaxableRows({
|
|
32
|
+
calculationSheet: params.calculationSheet,
|
|
33
|
+
resultSheet: pricingAdapter.resultSheet(),
|
|
34
|
+
taxRate,
|
|
35
|
+
baseCategory: DeliveryPricingRowCategory.Delivery,
|
|
36
|
+
adapterKey: DeliveryUkTax.key,
|
|
37
|
+
});
|
|
38
|
+
return pricingAdapter.calculate();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export default DeliveryUkTax;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {} from '@unchainedshop/core';
|
|
2
|
+
import { DeliveryUkTax } from "./adapter.js";
|
|
3
|
+
export const DeliveryUkTaxPlugin = {
|
|
4
|
+
key: 'shop.unchained.pricing.delivery-uk-tax',
|
|
5
|
+
label: 'Delivery UK Tax Plugin',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
adapters: [DeliveryUkTax],
|
|
8
|
+
};
|
|
9
|
+
export default DeliveryUkTaxPlugin;
|
|
10
|
+
export { DeliveryUkTax } from "./adapter.js";
|