@unchainedshop/platform 2.5.8 → 2.5.9

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.
Files changed (43) hide show
  1. package/lib/templates/order-parser/formatAddress.d.ts +2 -0
  2. package/lib/templates/order-parser/formatAddress.js +14 -0
  3. package/lib/templates/order-parser/formatAddress.js.map +1 -0
  4. package/lib/templates/order-parser/formatPrice.d.ts +5 -0
  5. package/lib/templates/order-parser/formatPrice.js +6 -0
  6. package/lib/templates/order-parser/formatPrice.js.map +1 -0
  7. package/lib/templates/order-parser/getOrderPositionsData.d.ts +13 -0
  8. package/lib/templates/{utils → order-parser}/getOrderPositionsData.js +8 -8
  9. package/lib/templates/order-parser/getOrderPositionsData.js.map +1 -0
  10. package/lib/templates/order-parser/getOrderSummaryData.d.ts +40 -0
  11. package/lib/templates/order-parser/getOrderSummaryData.js +61 -0
  12. package/lib/templates/order-parser/getOrderSummaryData.js.map +1 -0
  13. package/lib/templates/order-parser/index.d.ts +4 -0
  14. package/lib/templates/order-parser/index.js +42 -0
  15. package/lib/templates/order-parser/index.js.map +1 -0
  16. package/lib/templates/resolveErrorReportTemplate.js +9 -1
  17. package/lib/templates/resolveErrorReportTemplate.js.map +1 -1
  18. package/lib/templates/resolveForwardDeliveryTemplate.js +11 -41
  19. package/lib/templates/resolveForwardDeliveryTemplate.js.map +1 -1
  20. package/lib/templates/resolveOrderConfirmationTemplate.js +9 -61
  21. package/lib/templates/resolveOrderConfirmationTemplate.js.map +1 -1
  22. package/lib/templates/resolveOrderRejectionTemplate.js +15 -29
  23. package/lib/templates/resolveOrderRejectionTemplate.js.map +1 -1
  24. package/package.json +12 -12
  25. package/src/templates/order-parser/formatAddress.ts +15 -0
  26. package/src/templates/order-parser/formatPrice.ts +6 -0
  27. package/src/templates/{utils → order-parser}/getOrderPositionsData.ts +9 -10
  28. package/src/templates/order-parser/getOrderSummaryData.ts +76 -0
  29. package/src/templates/order-parser/index.ts +44 -0
  30. package/src/templates/resolveErrorReportTemplate.ts +10 -1
  31. package/src/templates/resolveForwardDeliveryTemplate.ts +11 -44
  32. package/src/templates/resolveOrderConfirmationTemplate.ts +10 -73
  33. package/src/templates/resolveOrderRejectionTemplate.ts +16 -30
  34. package/lib/templates/utils/formatWorkItems.d.ts +0 -2
  35. package/lib/templates/utils/formatWorkItems.js +0 -10
  36. package/lib/templates/utils/formatWorkItems.js.map +0 -1
  37. package/lib/templates/utils/getOrderAttachmentsData.d.ts +0 -8
  38. package/lib/templates/utils/getOrderAttachmentsData.js +0 -21
  39. package/lib/templates/utils/getOrderAttachmentsData.js.map +0 -1
  40. package/lib/templates/utils/getOrderPositionsData.d.ts +0 -6
  41. package/lib/templates/utils/getOrderPositionsData.js.map +0 -1
  42. package/src/templates/utils/formatWorkItems.ts +0 -10
  43. package/src/templates/utils/getOrderAttachmentsData.ts +0 -40
@@ -0,0 +1,2 @@
1
+ import { Address } from '@unchainedshop/types/common.js';
2
+ export declare const formatAddress: (address: Address) => string;
@@ -0,0 +1,14 @@
1
+ export const formatAddress = (address) => {
2
+ return [
3
+ [address.firstName, address.lastName].filter(Boolean).join(' '),
4
+ address.company,
5
+ address.addressLine,
6
+ address.addressLine2,
7
+ [address.postalCode, address.city].filter(Boolean).join(' '),
8
+ address.regionCode,
9
+ [address.countryCode].filter(Boolean).join(''),
10
+ ]
11
+ .filter(Boolean)
12
+ .join('\n');
13
+ };
14
+ //# sourceMappingURL=formatAddress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatAddress.js","sourceRoot":"","sources":["../../../src/templates/order-parser/formatAddress.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAgB,EAAE,EAAE;IAChD,OAAO;QACL,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/D,OAAO,CAAC,OAAO;QACf,OAAO,CAAC,WAAW;QACnB,OAAO,CAAC,YAAY;QACpB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC5D,OAAO,CAAC,UAAU;QAClB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;KAC/C;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const formatPrice: ({ amount, currency }: {
2
+ amount: number;
3
+ currency: string;
4
+ }) => string;
5
+ export default formatPrice;
@@ -0,0 +1,6 @@
1
+ export const formatPrice = ({ amount, currency }) => {
2
+ const fixedPrice = amount / 100;
3
+ return `${currency} ${fixedPrice}`;
4
+ };
5
+ export default formatPrice;
6
+ //# sourceMappingURL=formatPrice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatPrice.js","sourceRoot":"","sources":["../../../src/templates/order-parser/formatPrice.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAwC,EAAE,EAAE;IACxF,MAAM,UAAU,GAAG,MAAM,GAAG,GAAG,CAAC;IAChC,OAAO,GAAG,QAAQ,IAAI,UAAU,EAAE,CAAC;AACrC,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Locale } from '@unchainedshop/types/common.js';
2
+ import { UnchainedCore } from '@unchainedshop/types/core.js';
3
+ import { Order } from '@unchainedshop/types/orders.js';
4
+ export declare const getOrderPositionsData: (order: Order, params: {
5
+ locale?: Locale;
6
+ }, context: UnchainedCore) => Promise<{
7
+ productId: string;
8
+ configuration: import("@unchainedshop/types/common.js").Configuration;
9
+ originalProductTexts: import("@unchainedshop/types/products.js").ProductText;
10
+ productTexts: import("@unchainedshop/types/products.js").ProductText;
11
+ quantity: number;
12
+ total: string;
13
+ }[]>;
@@ -1,13 +1,10 @@
1
+ import formatPrice from './formatPrice.js';
1
2
  export const getOrderPositionsData = async (order, params, context) => {
2
3
  const { modules } = context;
3
4
  const orderPositions = await modules.orders.positions.findOrderPositions({
4
5
  orderId: order._id,
5
6
  });
6
- const formatPrice = (price) => {
7
- const fixedPrice = price / 100;
8
- return `${order.currency} ${fixedPrice}`;
9
- };
10
- await Promise.all(orderPositions.map(async (orderPosition) => {
7
+ return Promise.all(orderPositions.map(async (orderPosition) => {
11
8
  const productTexts = await modules.products.texts.findLocalizedText({
12
9
  productId: orderPosition.productId,
13
10
  locale: params.locale?.normalized,
@@ -16,13 +13,16 @@ export const getOrderPositionsData = async (order, params, context) => {
16
13
  productId: orderPosition.originalProductId,
17
14
  locale: params.locale?.normalized,
18
15
  });
19
- const productTitle = productTexts?.title; // deprecated
20
16
  const positionPricing = modules.orders.positions.pricingSheet(orderPosition, order.currency, context);
21
- const total = formatPrice(positionPricing.sum());
17
+ const total = formatPrice({
18
+ amount: positionPricing.sum(),
19
+ currency: order.currency,
20
+ });
22
21
  const { quantity } = positionPricing;
23
22
  return {
23
+ productId: orderPosition.productId,
24
+ configuration: orderPosition.configuration,
24
25
  originalProductTexts,
25
- product: productTitle,
26
26
  productTexts,
27
27
  quantity,
28
28
  total,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getOrderPositionsData.js","sourceRoot":"","sources":["../../../src/templates/order-parser/getOrderPositionsData.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,KAAY,EACZ,MAA2B,EAC3B,OAAsB,EACtB,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC;QACvE,OAAO,EAAE,KAAK,CAAC,GAAG;KACnB,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,GAAG,CAChB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;QACzC,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAClE,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QACH,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC1E,SAAS,EAAE,aAAa,CAAC,iBAAiB;YAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAC3D,aAAa,EACb,KAAK,CAAC,QAAQ,EACd,OAAO,CACR,CAAC;QACF,MAAM,KAAK,GAAG,WAAW,CAAC;YACxB,MAAM,EAAE,eAAe,CAAC,GAAG,EAAE;YAC7B,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;QAEH,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,CAAC;QACrC,OAAO;YACL,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,aAAa,EAAE,aAAa,CAAC,aAAa;YAC1C,oBAAoB;YACpB,YAAY;YACZ,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { UnchainedCore } from '@unchainedshop/types/core.js';
2
+ import { Order } from '@unchainedshop/types/orders.js';
3
+ import { Locale } from '@unchainedshop/types/common.js';
4
+ export declare const getOrderSummaryData: (order: Order, params: {
5
+ locale?: Locale;
6
+ }, context: UnchainedCore) => Promise<{
7
+ rawPrices: {
8
+ items: {
9
+ amount: number;
10
+ currency: string;
11
+ };
12
+ taxes: {
13
+ amount: number;
14
+ currency: string;
15
+ };
16
+ delivery: {
17
+ amount: number;
18
+ currency: string;
19
+ };
20
+ payment: {
21
+ amount: number;
22
+ currency: string;
23
+ };
24
+ gross: {
25
+ amount: number;
26
+ currency: string;
27
+ };
28
+ };
29
+ prices: {
30
+ items: string;
31
+ taxes: string;
32
+ delivery: string;
33
+ payment: string;
34
+ gross: string;
35
+ };
36
+ payment: string;
37
+ delivery: string;
38
+ deliveryAddress: string;
39
+ billingAddress: string;
40
+ }>;
@@ -0,0 +1,61 @@
1
+ import { OrderPricingRowCategory } from '@unchainedshop/types/orders.pricing.js';
2
+ import formatPrice from './formatPrice.js';
3
+ import { formatAddress } from './formatAddress.js';
4
+ export const getOrderSummaryData = async (order, params, context) => {
5
+ const { modules } = context;
6
+ const orderDelivery = await modules.orders.deliveries.findDelivery({
7
+ orderDeliveryId: order.deliveryId,
8
+ });
9
+ const orderPayment = await modules.orders.payments.findOrderPayment({
10
+ orderPaymentId: order.paymentId,
11
+ });
12
+ const paymentProvider = await modules.payment.paymentProviders.findProvider({
13
+ paymentProviderId: orderPayment.paymentProviderId,
14
+ });
15
+ const deliveryProvider = await modules.delivery.findProvider({
16
+ deliveryProviderId: orderDelivery.deliveryProviderId,
17
+ });
18
+ const deliveryAddress = formatAddress(orderDelivery?.context?.deliveryAddress || order.billingAddress);
19
+ const billingAddress = formatAddress(order.billingAddress);
20
+ const orderPricing = modules.orders.pricingSheet(order);
21
+ const paymentTotal = orderPricing.total({
22
+ category: OrderPricingRowCategory.Payment,
23
+ useNetPrice: false,
24
+ });
25
+ const deliveryTotal = orderPricing.total({
26
+ category: OrderPricingRowCategory.Delivery,
27
+ useNetPrice: false,
28
+ });
29
+ const taxesTotal = orderPricing.total({
30
+ category: OrderPricingRowCategory.Taxes,
31
+ useNetPrice: false,
32
+ });
33
+ const itemsTotal = orderPricing.total({
34
+ category: OrderPricingRowCategory.Items,
35
+ useNetPrice: false,
36
+ });
37
+ const total = orderPricing.total({ useNetPrice: false });
38
+ const payment = paymentProvider.adapterKey;
39
+ const delivery = deliveryProvider.adapterKey;
40
+ return {
41
+ rawPrices: {
42
+ items: itemsTotal,
43
+ taxes: taxesTotal,
44
+ delivery: deliveryTotal,
45
+ payment: paymentTotal,
46
+ gross: total,
47
+ },
48
+ prices: {
49
+ items: formatPrice(itemsTotal),
50
+ taxes: formatPrice(taxesTotal),
51
+ delivery: formatPrice(deliveryTotal),
52
+ payment: formatPrice(paymentTotal),
53
+ gross: formatPrice(total),
54
+ },
55
+ payment,
56
+ delivery,
57
+ deliveryAddress,
58
+ billingAddress,
59
+ };
60
+ };
61
+ //# sourceMappingURL=getOrderSummaryData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getOrderSummaryData.js","sourceRoot":"","sources":["../../../src/templates/order-parser/getOrderSummaryData.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAEjF,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,KAAY,EACZ,MAA2B,EAC3B,OAAsB,EACtB,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC;QACjE,eAAe,EAAE,KAAK,CAAC,UAAU;KAClC,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAClE,cAAc,EAAE,KAAK,CAAC,SAAS;KAChC,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC;QAC1E,iBAAiB,EAAE,YAAY,CAAC,iBAAiB;KAClD,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC3D,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;KACrD,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,aAAa,CAAC,aAAa,EAAE,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IACvG,MAAM,cAAc,GAAG,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC;QACtC,QAAQ,EAAE,uBAAuB,CAAC,OAAO;QACzC,WAAW,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC;QACvC,QAAQ,EAAE,uBAAuB,CAAC,QAAQ;QAC1C,WAAW,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC;QACpC,QAAQ,EAAE,uBAAuB,CAAC,KAAK;QACvC,WAAW,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC;QACpC,QAAQ,EAAE,uBAAuB,CAAC,KAAK;QACvC,WAAW,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC;IAC3C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC;IAE7C,OAAO;QACL,SAAS,EAAE;YACT,KAAK,EAAE,UAAU;YACjB,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,aAAa;YACvB,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,KAAK;SACb;QACD,MAAM,EAAE;YACN,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC;YAC9B,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC;YAC9B,QAAQ,EAAE,WAAW,CAAC,aAAa,CAAC;YACpC,OAAO,EAAE,WAAW,CAAC,YAAY,CAAC;YAClC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC;SAC1B;QACD,OAAO;QACP,QAAQ;QACR,eAAe;QACf,cAAc;KACf,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const transformOrderToText: ({ order, locale }: {
2
+ order: any;
3
+ locale: any;
4
+ }, context: any) => Promise<any>;
@@ -0,0 +1,42 @@
1
+ import { getOrderPositionsData } from './getOrderPositionsData.js';
2
+ import { getOrderSummaryData } from './getOrderSummaryData.js';
3
+ const textTemplate = `Order number: {{orderNumber}}
4
+ Ordered: {{orderDate}}
5
+ Payment method: {{summary.payment}}
6
+ Delivery method: {{summary.delivery}}
7
+
8
+ Delivery address:
9
+ {{summary.deliveryAddress}}
10
+
11
+ Billing address:
12
+ {{summary.billingAddress}}
13
+
14
+ Order Details:
15
+
16
+ Items:
17
+ {{#positions}}
18
+ * {{quantity}} {{productTexts.title}}: {{total}}
19
+ {{/positions}}
20
+
21
+ {{#summary.rawPrices.delivery.amount}}
22
+ Delivery Fees: {{summary.prices.delivery}}
23
+ {{/summary.rawPrices.delivery.amount}}
24
+ {{#summary.rawPrices.payment.amount}}
25
+ Payment Fees: {{summary.prices.payment}}
26
+ {{/summary.rawPrices.payment.amount}}
27
+ Total: {{summary.prices.gross}}
28
+ {{#summary.rawPrices.taxes.amount}}
29
+ (VAT included: {{summary.prices.taxes}})
30
+ {{/summary.rawPrices.taxes.amount}}
31
+ `;
32
+ export const transformOrderToText = async ({ order, locale }, context) => {
33
+ const { modules } = context;
34
+ const data = {
35
+ orderDate: new Date(order.ordered).toLocaleString(),
36
+ orderNumber: order.orderNumber,
37
+ summary: await getOrderSummaryData(order, { locale }, context),
38
+ positions: await getOrderPositionsData(order, { locale }, context),
39
+ };
40
+ return modules.messaging.renderToText(textTemplate, data);
41
+ };
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/order-parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BpB,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;IACvE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE;QACnD,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,MAAM,mBAAmB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC;QAC9D,SAAS,EAAE,MAAM,qBAAqB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC;KACnE,CAAC;IAEF,OAAO,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC5D,CAAC,CAAC"}
@@ -1,5 +1,13 @@
1
- import formatWorkItems from './utils/formatWorkItems.js';
1
+ import util from 'util';
2
2
  const { EMAIL_FROM = 'noreply@unchained.local', EMAIL_ERROR_REPORT_RECIPIENT = 'support@unchained.local', EMAIL_WEBSITE_NAME = 'Unchained', ROOT_URL, } = process.env;
3
+ const formatWorkItems = (workItems) => {
4
+ return workItems
5
+ .map(({ _id, type, started, error }) => {
6
+ const stringifiedErrors = util.inspect(error, false, 10, false);
7
+ return `${new Date(started).toLocaleString()} ${type} (${_id}): ${stringifiedErrors}`;
8
+ })
9
+ .join('\n');
10
+ };
3
11
  const textTemplate = `
4
12
  -------------------------
5
13
  Unchained Endpoint: {{endpoint}}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveErrorReportTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveErrorReportTemplate.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAEzD,MAAM,EACJ,UAAU,GAAG,yBAAyB,EACtC,4BAA4B,GAAG,yBAAyB,EACxD,kBAAkB,GAAG,WAAW,EAChC,QAAQ,GACT,GAAG,OAAO,CAAC,GAAG,CAAC;AAEhB,MAAM,YAAY,GAAG;;;;;;;CAOpB,CAAC;AAEF,MAAM,0BAA0B,GAAqB,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE;IACpF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE5B,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,UAAU,IAAI,yBAAyB;gBAC7C,EAAE,EAAE,4BAA4B;gBAChC,OAAO,EAAE,GAAG,kBAAkB,gBAAgB;gBAC9C,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE;oBACjD,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC;oBACnC,IAAI,EAAE,kBAAkB;iBACzB,CAAC;aACH;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,eAAe,0BAA0B,CAAC"}
1
+ {"version":3,"file":"resolveErrorReportTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveErrorReportTemplate.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,EACJ,UAAU,GAAG,yBAAyB,EACtC,4BAA4B,GAAG,yBAAyB,EACxD,kBAAkB,GAAG,WAAW,EAChC,QAAQ,GACT,GAAG,OAAO,CAAC,GAAG,CAAC;AAEhB,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,EAAE;IACpC,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACrC,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAChE,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,IAAI,IAAI,KAAK,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACxF,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;;;CAOpB,CAAC;AAEF,MAAM,0BAA0B,GAAqB,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE;IACpF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE5B,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,UAAU,IAAI,yBAAyB;gBAC7C,EAAE,EAAE,4BAA4B;gBAChC,OAAO,EAAE,GAAG,kBAAkB,gBAAgB;gBAC9C,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE;oBACjD,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC;oBACnC,IAAI,EAAE,kBAAkB;iBACzB,CAAC;aACH;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,eAAe,0BAA0B,CAAC"}
@@ -1,67 +1,37 @@
1
1
  import { systemLocale } from '@unchainedshop/utils';
2
- import { getOrderAttachmentsData } from './utils/getOrderAttachmentsData.js';
3
- import { getOrderPositionsData } from './utils/getOrderPositionsData.js';
4
- const { EMAIL_FROM, EMAIL_WEBSITE_NAME, ROOT_URL } = process.env;
2
+ import { transformOrderToText } from './order-parser/index.js';
3
+ const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
5
4
  const textTemplate = `
6
- {{subject}}\n
7
- \n
8
- Order number: {{orderNumber}}\n
9
- Order date: {{orderDate}}\n
10
- Link: {{adminUILink}}\n
11
- \n
12
- Delivery address:\n
13
- -----------------\n
14
- {{address.firstName}} {{address.lastName}}\n
15
- {{address.company}}\n
16
- {{address.addressLine}}\n
17
- {{address.addressLine2}}\n
18
- {{address.postalCode}} {{address.city}}\n
19
- {{address.regionCode}}\n
20
- {{address.countryCode}}\n
21
- \n
22
- Articles:\n
23
- -----------------\n
24
- {{#items}}
25
- * {{sku}} - {{name}} CHF {{price}} {{quantity}}\n
26
- {{/items}}
5
+ New Order received:
6
+
7
+ {{orderDetails}}
8
+
9
+ {{shopName}}: {{shopUrl}}
27
10
  `;
28
11
  export const resolveForwardDeliveryTemplate = async ({ config, orderId }, context) => {
29
12
  const { modules } = context;
30
13
  const order = await modules.orders.findOrder({ orderId });
31
- const orderPricing = modules.orders.pricingSheet(order);
32
- const orderDate = new Date(order.ordered).toLocaleString();
33
- const attachments = await getOrderAttachmentsData(order, { fileType: 'DELIVERY_NOTE' }, context);
34
- const address = order.billingAddress;
35
14
  const configObject = config.reduce((acc, { key, value }) => {
36
15
  return {
37
16
  ...acc,
38
17
  [key]: value,
39
18
  };
40
19
  }, {});
41
- const subject = `${EMAIL_WEBSITE_NAME}: New Order / ${order.orderNumber}`;
42
- const adminUILink = `${ROOT_URL}/orders/view/?_id=${order._id}`;
20
+ const subject = `${EMAIL_WEBSITE_NAME} Order ${order.orderNumber}`;
43
21
  const data = {
44
- contact: order.contact || {},
45
- adminUILink,
46
- items: getOrderPositionsData(order, { locale: systemLocale }, context),
47
- orderDate,
48
- orderNumber: order.orderNumber,
49
22
  shopName: EMAIL_WEBSITE_NAME,
50
- subject,
51
- total: orderPricing.total({ useNetPrice: false }).amount / 100,
52
- ...configObject,
53
- address,
23
+ shopUrl: EMAIL_WEBSITE_URL,
24
+ orderDetails: await transformOrderToText({ order, locale: systemLocale }, context),
54
25
  };
55
26
  return [
56
27
  {
57
28
  type: 'EMAIL',
58
29
  input: {
59
- from: configObject.from || EMAIL_FROM || 'noreply@unchained.local',
30
+ from: `${EMAIL_WEBSITE_NAME} <${configObject.from || EMAIL_FROM || 'noreply@unchained.local'}>`,
60
31
  to: configObject.to || 'orders@unchained.local',
61
32
  cc: configObject.cc,
62
33
  subject,
63
34
  text: modules.messaging.renderToText(textTemplate, data),
64
- attachments,
65
35
  },
66
36
  },
67
37
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"resolveForwardDeliveryTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveForwardDeliveryTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAEjE,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAqB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE;IACrG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC;IAE3D,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;IAEjG,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC;IACrC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QACzD,OAAO;YACL,GAAG,GAAG;YACN,CAAC,GAAG,CAAC,EAAE,KAAK;SACb,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,GAAG,kBAAkB,iBAAiB,KAAK,CAAC,WAAW,EAAE,CAAC;IAE1E,MAAM,WAAW,GAAG,GAAG,QAAQ,qBAAqB,KAAK,CAAC,GAAG,EAAE,CAAC;IAEhE,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;QAC5B,WAAW;QACX,KAAK,EAAE,qBAAqB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC;QACtE,SAAS;QACT,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,kBAAkB;QAC5B,OAAO;QACP,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG;QAC9D,GAAG,YAAY;QACf,OAAO;KACR,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,YAAY,CAAC,IAAI,IAAI,UAAU,IAAI,yBAAyB;gBAClE,EAAE,EAAE,YAAY,CAAC,EAAE,IAAI,wBAAwB;gBAC/C,EAAE,EAAE,YAAY,CAAC,EAAE;gBACnB,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;gBACxD,WAAW;aACZ;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"resolveForwardDeliveryTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveForwardDeliveryTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE1E,MAAM,YAAY,GAAG;;;;;;CAMpB,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAqB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE;IACrG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QACzD,OAAO;YACL,GAAG,GAAG;YACN,CAAC,GAAG,CAAC,EAAE,KAAK;SACb,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,GAAG,kBAAkB,UAAU,KAAK,CAAC,WAAW,EAAE,CAAC;IAEnE,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,iBAAiB;QAC1B,YAAY,EAAE,MAAM,oBAAoB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC;KACnF,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,GAAG,kBAAkB,KAAK,YAAY,CAAC,IAAI,IAAI,UAAU,IAAI,yBAAyB,GAAG;gBAC/F,EAAE,EAAE,YAAY,CAAC,EAAE,IAAI,wBAAwB;gBAC/C,EAAE,EAAE,YAAY,CAAC,EAAE;gBACnB,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;aACzD;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -1,84 +1,32 @@
1
- import { OrderPricingRowCategory } from '@unchainedshop/types/orders.pricing.js';
2
- import { getOrderAttachmentsData } from './utils/getOrderAttachmentsData.js';
3
- import { getOrderPositionsData } from './utils/getOrderPositionsData.js';
1
+ import { transformOrderToText } from './order-parser/index.js';
4
2
  const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
5
3
  const textTemplate = `
6
- {{subject}}\n
7
- \n
8
- {{thankyou}}\n
9
- \n
10
- -----------------\n
11
- {{buttonText}}: {{url}}\n
12
- -----------------\n
4
+ Thank you very much for your order.
5
+
6
+ {{orderDetails}}
7
+
8
+ {{shopName}}: {{shopUrl}}
13
9
  `;
14
- const texts = {
15
- en: {
16
- buttonText: 'Follow purchase order status',
17
- thankyou: 'Thank you for your order on',
18
- subject: `${EMAIL_WEBSITE_NAME}: Order confirmation`,
19
- },
20
- de: {
21
- buttonText: 'Bestellstatus verfolgen',
22
- thankyou: 'Vielen Dank für deine Bestellung bei',
23
- subject: `${EMAIL_WEBSITE_NAME}: Bestellbestätigung`,
24
- },
25
- fr: {
26
- buttonText: 'Follow purchase order status',
27
- thankyou: 'Thank you for your order on',
28
- subject: `${EMAIL_WEBSITE_NAME}: Order confirmation`,
29
- },
30
- };
31
10
  export const resolveOrderConfirmationTemplate = async ({ orderId, locale }, context) => {
32
11
  const { modules } = context;
33
12
  const order = await modules.orders.findOrder({ orderId });
34
13
  if (order.status === 'PENDING') {
35
14
  return [];
36
15
  }
37
- const formatPrice = (price) => {
38
- const fixedPrice = price / 100;
39
- return `${order.currency} ${fixedPrice}`;
40
- };
41
- // TODO: If order.status is PENDING, we should only send the user
42
- // a notice that we have received the order but not confirming it
43
- const attachments = await getOrderAttachmentsData(order, { fileType: 'ORDER_CONFIRMATION' }, context);
44
- const orderPricing = modules.orders.pricingSheet(order);
45
- const { subject } = texts[locale.language];
16
+ const subject = `Order ${order.orderNumber}`;
46
17
  const data = {
47
- ...texts[locale.language],
48
18
  shopName: EMAIL_WEBSITE_NAME,
49
19
  shopUrl: EMAIL_WEBSITE_URL,
50
- subject,
51
- url: `${EMAIL_WEBSITE_URL}/order?_id=${order._id}`,
52
- summary: {
53
- items: formatPrice(orderPricing.total({
54
- category: OrderPricingRowCategory.Items,
55
- useNetPrice: false,
56
- }).amount),
57
- taxes: formatPrice(orderPricing.total({
58
- category: OrderPricingRowCategory.Taxes,
59
- useNetPrice: false,
60
- }).amount),
61
- delivery: formatPrice(orderPricing.total({
62
- category: OrderPricingRowCategory.Delivery,
63
- useNetPrice: false,
64
- }).amount),
65
- payment: formatPrice(orderPricing.total({
66
- category: OrderPricingRowCategory.Payment,
67
- useNetPrice: false,
68
- }).amount),
69
- gross: formatPrice(orderPricing.total({ useNetPrice: false }).amount),
70
- },
71
- positions: getOrderPositionsData(order, { locale }, context),
20
+ orderDetails: await transformOrderToText({ order, locale }, context),
72
21
  };
73
22
  return [
74
23
  {
75
24
  type: 'EMAIL',
76
25
  input: {
77
- from: EMAIL_FROM || 'orders@unchained.local',
26
+ from: `${EMAIL_WEBSITE_NAME} <${EMAIL_FROM || 'noreply@unchained.local'}>`,
78
27
  to: order.contact.emailAddress,
79
28
  subject,
80
29
  text: modules.messaging.renderToText(textTemplate, data),
81
- attachments,
82
30
  },
83
31
  },
84
32
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"resolveOrderConfirmationTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveOrderConfirmationTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE1E,MAAM,YAAY,GAAG;;;;;;;;CAQpB,CAAC;AAEF,MAAM,KAAK,GAAG;IACZ,EAAE,EAAE;QACF,UAAU,EAAE,8BAA8B;QAC1C,QAAQ,EAAE,6BAA6B;QACvC,OAAO,EAAE,GAAG,kBAAkB,sBAAsB;KACrD;IACD,EAAE,EAAE;QACF,UAAU,EAAE,yBAAyB;QACrC,QAAQ,EAAE,sCAAsC;QAChD,OAAO,EAAE,GAAG,kBAAkB,sBAAsB;KACrD;IACD,EAAE,EAAE;QACF,UAAU,EAAE,8BAA8B;QAC1C,QAAQ,EAAE,6BAA6B;QACvC,OAAO,EAAE,GAAG,kBAAkB,sBAAsB;KACrD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAqB,KAAK,EACrE,EAAE,OAAO,EAAE,MAAM,EAAE,EACnB,OAAO,EACP,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE;QAC9B,OAAO,EAAE,CAAC;KACX;IAED,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE;QACpC,MAAM,UAAU,GAAG,KAAK,GAAG,GAAG,CAAC;QAC/B,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;IAC3C,CAAC,CAAC;IAEF,iEAAiE;IACjE,iEAAiE;IACjE,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;IAEtG,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG;QACX,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QACzB,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,iBAAiB;QAC1B,OAAO;QACP,GAAG,EAAE,GAAG,iBAAiB,cAAc,KAAK,CAAC,GAAG,EAAE;QAClD,OAAO,EAAE;YACP,KAAK,EAAE,WAAW,CAChB,YAAY,CAAC,KAAK,CAAC;gBACjB,QAAQ,EAAE,uBAAuB,CAAC,KAAK;gBACvC,WAAW,EAAE,KAAK;aACnB,CAAC,CAAC,MAAM,CACV;YACD,KAAK,EAAE,WAAW,CAChB,YAAY,CAAC,KAAK,CAAC;gBACjB,QAAQ,EAAE,uBAAuB,CAAC,KAAK;gBACvC,WAAW,EAAE,KAAK;aACnB,CAAC,CAAC,MAAM,CACV;YACD,QAAQ,EAAE,WAAW,CACnB,YAAY,CAAC,KAAK,CAAC;gBACjB,QAAQ,EAAE,uBAAuB,CAAC,QAAQ;gBAC1C,WAAW,EAAE,KAAK;aACnB,CAAC,CAAC,MAAM,CACV;YACD,OAAO,EAAE,WAAW,CAClB,YAAY,CAAC,KAAK,CAAC;gBACjB,QAAQ,EAAE,uBAAuB,CAAC,OAAO;gBACzC,WAAW,EAAE,KAAK;aACnB,CAAC,CAAC,MAAM,CACV;YACD,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;SACtE;QACD,SAAS,EAAE,qBAAqB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC;KAC7D,CAAC;IACF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,UAAU,IAAI,wBAAwB;gBAC5C,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY;gBAC9B,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;gBACxD,WAAW;aACZ;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"resolveOrderConfirmationTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveOrderConfirmationTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE1E,MAAM,YAAY,GAAG;;;;;;CAMpB,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAqB,KAAK,EACrE,EAAE,OAAO,EAAE,MAAM,EAAE,EACnB,OAAO,EACP,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE;QAC9B,OAAO,EAAE,CAAC;KACX;IAED,MAAM,OAAO,GAAG,SAAS,KAAK,CAAC,WAAW,EAAE,CAAC;IAE7C,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,iBAAiB;QAC1B,YAAY,EAAE,MAAM,oBAAoB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC;KACrE,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,GAAG,kBAAkB,KAAK,UAAU,IAAI,yBAAyB,GAAG;gBAC1E,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY;gBAC9B,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;aACzD;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -1,47 +1,33 @@
1
+ import { transformOrderToText } from './order-parser/index.js';
1
2
  const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
2
3
  const textTemplate = `
3
- {{subject}}\n
4
- \n
5
- {{rejection}}\n
6
- \n
7
- -----------------\n
8
- {{buttonText}}: {{url}}\n
9
- -----------------\n
4
+ I'm sorry we can't confirm your order.
5
+
6
+ This can happen when the payment was not successful or the order was manually canceled because of product availability or fullfillment issues.
7
+
8
+ The order in question is:
9
+
10
+ {{orderDetails}}
11
+
12
+ {{shopName}}: {{shopUrl}}
10
13
  `;
11
- const texts = {
12
- en: {
13
- buttonText: 'Details are available at',
14
- rejection: 'Your order was cancelled.',
15
- subject: `${EMAIL_WEBSITE_NAME}: Order cancelled`,
16
- },
17
- de: {
18
- buttonText: 'Details abrufen',
19
- rejection: 'Deine Bestellung wurde storniert',
20
- subject: `${EMAIL_WEBSITE_NAME}: Bestellung storniert`,
21
- },
22
- fr: {
23
- buttonText: 'Details are available at',
24
- rejection: 'Your order was cancelled.',
25
- subject: `${EMAIL_WEBSITE_NAME}: Order cancelled`,
26
- },
27
- };
28
14
  export const resolveOrderRejectionTemplate = async ({ orderId, locale }, context) => {
29
15
  const { modules } = context;
30
16
  const order = await modules.orders.findOrder({ orderId });
31
17
  if (order.status !== 'REJECTED') {
32
18
  return [];
33
19
  }
34
- const { subject } = texts[locale.language];
20
+ const subject = `Order rejected ${order.orderNumber}`;
35
21
  const data = {
36
- ...texts[locale.language],
37
- subject,
38
- url: `${EMAIL_WEBSITE_URL}/order?_id=${order._id}`,
22
+ shopName: EMAIL_WEBSITE_NAME,
23
+ shopUrl: EMAIL_WEBSITE_URL,
24
+ orderDetails: await transformOrderToText({ order, locale }, context),
39
25
  };
40
26
  return [
41
27
  {
42
28
  type: 'EMAIL',
43
29
  input: {
44
- from: EMAIL_FROM || 'orders@unchained.local',
30
+ from: `${EMAIL_WEBSITE_NAME} <${EMAIL_FROM || 'noreply@unchained.local'}>`,
45
31
  to: order.contact.emailAddress,
46
32
  subject,
47
33
  text: modules.messaging.renderToText(textTemplate, data),
@@ -1 +1 @@
1
- {"version":3,"file":"resolveOrderRejectionTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveOrderRejectionTemplate.ts"],"names":[],"mappings":"AAEA,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE1E,MAAM,YAAY,GAAG;;;;;;;;CAQpB,CAAC;AAEF,MAAM,KAAK,GAAG;IACZ,EAAE,EAAE;QACF,UAAU,EAAE,0BAA0B;QACtC,SAAS,EAAE,2BAA2B;QACtC,OAAO,EAAE,GAAG,kBAAkB,mBAAmB;KAClD;IACD,EAAE,EAAE;QACF,UAAU,EAAE,iBAAiB;QAC7B,SAAS,EAAE,kCAAkC;QAC7C,OAAO,EAAE,GAAG,kBAAkB,wBAAwB;KACvD;IACD,EAAE,EAAE;QACF,UAAU,EAAE,0BAA0B;QACtC,SAAS,EAAE,2BAA2B;QACtC,OAAO,EAAE,GAAG,kBAAkB,mBAAmB;KAClD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAqB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;IACpG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE;QAC/B,OAAO,EAAE,CAAC;KACX;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG;QACX,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QACzB,OAAO;QACP,GAAG,EAAE,GAAG,iBAAiB,cAAc,KAAK,CAAC,GAAG,EAAE;KACnD,CAAC;IACF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,UAAU,IAAI,wBAAwB;gBAC5C,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY;gBAC9B,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;aACzD;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"resolveOrderRejectionTemplate.js","sourceRoot":"","sources":["../../src/templates/resolveOrderRejectionTemplate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAE1E,MAAM,YAAY,GAAG;;;;;;;;;;CAUpB,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAqB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;IACpG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE;QAC/B,OAAO,EAAE,CAAC;KACX;IAED,MAAM,OAAO,GAAG,kBAAkB,KAAK,CAAC,WAAW,EAAE,CAAC;IAEtD,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,kBAAkB;QAC5B,OAAO,EAAE,iBAAiB;QAC1B,YAAY,EAAE,MAAM,oBAAoB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC;KACrE,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,GAAG,kBAAkB,KAAK,UAAU,IAAI,yBAAyB,GAAG;gBAC1E,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY;gBAC9B,OAAO;gBACP,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;aACzD;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/platform",
3
- "version": "2.5.8",
3
+ "version": "2.5.9",
4
4
  "main": "lib/platform-index.js",
5
5
  "exports": {
6
6
  ".": "./lib/platform-index.js",
@@ -31,22 +31,22 @@
31
31
  },
32
32
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
33
  "dependencies": {
34
- "@unchainedshop/api": "^2.5.8",
35
- "@unchainedshop/core": "^2.5.8",
36
- "@unchainedshop/events": "^2.5.8",
37
- "@unchainedshop/file-upload": "^2.5.8",
38
- "@unchainedshop/logger": "^2.5.8",
39
- "@unchainedshop/mongodb": "^2.5.8",
40
- "@unchainedshop/plugins": "^2.5.8",
41
- "@unchainedshop/roles": "^2.5.8",
42
- "@unchainedshop/utils": "^2.5.8",
34
+ "@unchainedshop/api": "^2.5.9",
35
+ "@unchainedshop/core": "^2.5.9",
36
+ "@unchainedshop/events": "^2.5.9",
37
+ "@unchainedshop/file-upload": "^2.5.9",
38
+ "@unchainedshop/logger": "^2.5.9",
39
+ "@unchainedshop/mongodb": "^2.5.9",
40
+ "@unchainedshop/plugins": "^2.5.9",
41
+ "@unchainedshop/roles": "^2.5.9",
42
+ "@unchainedshop/utils": "^2.5.9",
43
43
  "event-iterator": "^2.0.0",
44
44
  "JSONStream": "^1.3.5",
45
45
  "moniker": "0.1.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node": "^18.18.8",
49
- "@unchainedshop/types": "^2.5.8",
48
+ "@types/node": "^20.9.0",
49
+ "@unchainedshop/types": "^2.5.9",
50
50
  "cross-env": "^7.0.3",
51
51
  "jest": "^29.7.0",
52
52
  "ts-jest": "^29.1.1",
@@ -0,0 +1,15 @@
1
+ import { Address } from '@unchainedshop/types/common.js';
2
+
3
+ export const formatAddress = (address: Address) => {
4
+ return [
5
+ [address.firstName, address.lastName].filter(Boolean).join(' '),
6
+ address.company,
7
+ address.addressLine,
8
+ address.addressLine2,
9
+ [address.postalCode, address.city].filter(Boolean).join(' '),
10
+ address.regionCode,
11
+ [address.countryCode].filter(Boolean).join(''),
12
+ ]
13
+ .filter(Boolean)
14
+ .join('\n');
15
+ };
@@ -0,0 +1,6 @@
1
+ export const formatPrice = ({ amount, currency }: { amount: number; currency: string }) => {
2
+ const fixedPrice = amount / 100;
3
+ return `${currency} ${fixedPrice}`;
4
+ };
5
+
6
+ export default formatPrice;
@@ -1,6 +1,7 @@
1
1
  import { Locale } from '@unchainedshop/types/common.js';
2
2
  import { UnchainedCore } from '@unchainedshop/types/core.js';
3
3
  import { Order } from '@unchainedshop/types/orders.js';
4
+ import formatPrice from './formatPrice.js';
4
5
 
5
6
  export const getOrderPositionsData = async (
6
7
  order: Order,
@@ -12,12 +13,7 @@ export const getOrderPositionsData = async (
12
13
  orderId: order._id,
13
14
  });
14
15
 
15
- const formatPrice = (price: number) => {
16
- const fixedPrice = price / 100;
17
- return `${order.currency} ${fixedPrice}`;
18
- };
19
-
20
- await Promise.all(
16
+ return Promise.all(
21
17
  orderPositions.map(async (orderPosition) => {
22
18
  const productTexts = await modules.products.texts.findLocalizedText({
23
19
  productId: orderPosition.productId,
@@ -28,18 +24,21 @@ export const getOrderPositionsData = async (
28
24
  locale: params.locale?.normalized,
29
25
  });
30
26
 
31
- const productTitle = productTexts?.title; // deprecated
32
-
33
27
  const positionPricing = modules.orders.positions.pricingSheet(
34
28
  orderPosition,
35
29
  order.currency,
36
30
  context,
37
31
  );
38
- const total = formatPrice(positionPricing.sum());
32
+ const total = formatPrice({
33
+ amount: positionPricing.sum(),
34
+ currency: order.currency,
35
+ });
36
+
39
37
  const { quantity } = positionPricing;
40
38
  return {
39
+ productId: orderPosition.productId,
40
+ configuration: orderPosition.configuration,
41
41
  originalProductTexts,
42
- product: productTitle,
43
42
  productTexts,
44
43
  quantity,
45
44
  total,
@@ -0,0 +1,76 @@
1
+ import { UnchainedCore } from '@unchainedshop/types/core.js';
2
+ import { Order } from '@unchainedshop/types/orders.js';
3
+ import { OrderPricingRowCategory } from '@unchainedshop/types/orders.pricing.js';
4
+ import { Locale } from '@unchainedshop/types/common.js';
5
+ import formatPrice from './formatPrice.js';
6
+ import { formatAddress } from './formatAddress.js';
7
+
8
+ export const getOrderSummaryData = async (
9
+ order: Order,
10
+ params: { locale?: Locale },
11
+ context: UnchainedCore,
12
+ ) => {
13
+ const { modules } = context;
14
+ const orderDelivery = await modules.orders.deliveries.findDelivery({
15
+ orderDeliveryId: order.deliveryId,
16
+ });
17
+ const orderPayment = await modules.orders.payments.findOrderPayment({
18
+ orderPaymentId: order.paymentId,
19
+ });
20
+ const paymentProvider = await modules.payment.paymentProviders.findProvider({
21
+ paymentProviderId: orderPayment.paymentProviderId,
22
+ });
23
+ const deliveryProvider = await modules.delivery.findProvider({
24
+ deliveryProviderId: orderDelivery.deliveryProviderId,
25
+ });
26
+
27
+ const deliveryAddress = formatAddress(orderDelivery?.context?.deliveryAddress || order.billingAddress);
28
+ const billingAddress = formatAddress(order.billingAddress);
29
+ const orderPricing = modules.orders.pricingSheet(order);
30
+
31
+ const paymentTotal = orderPricing.total({
32
+ category: OrderPricingRowCategory.Payment,
33
+ useNetPrice: false,
34
+ });
35
+
36
+ const deliveryTotal = orderPricing.total({
37
+ category: OrderPricingRowCategory.Delivery,
38
+ useNetPrice: false,
39
+ });
40
+
41
+ const taxesTotal = orderPricing.total({
42
+ category: OrderPricingRowCategory.Taxes,
43
+ useNetPrice: false,
44
+ });
45
+
46
+ const itemsTotal = orderPricing.total({
47
+ category: OrderPricingRowCategory.Items,
48
+ useNetPrice: false,
49
+ });
50
+
51
+ const total = orderPricing.total({ useNetPrice: false });
52
+
53
+ const payment = paymentProvider.adapterKey;
54
+ const delivery = deliveryProvider.adapterKey;
55
+
56
+ return {
57
+ rawPrices: {
58
+ items: itemsTotal,
59
+ taxes: taxesTotal,
60
+ delivery: deliveryTotal,
61
+ payment: paymentTotal,
62
+ gross: total,
63
+ },
64
+ prices: {
65
+ items: formatPrice(itemsTotal),
66
+ taxes: formatPrice(taxesTotal),
67
+ delivery: formatPrice(deliveryTotal),
68
+ payment: formatPrice(paymentTotal),
69
+ gross: formatPrice(total),
70
+ },
71
+ payment,
72
+ delivery,
73
+ deliveryAddress,
74
+ billingAddress,
75
+ };
76
+ };
@@ -0,0 +1,44 @@
1
+ import { getOrderPositionsData } from './getOrderPositionsData.js';
2
+ import { getOrderSummaryData } from './getOrderSummaryData.js';
3
+
4
+ const textTemplate = `Order number: {{orderNumber}}
5
+ Ordered: {{orderDate}}
6
+ Payment method: {{summary.payment}}
7
+ Delivery method: {{summary.delivery}}
8
+
9
+ Delivery address:
10
+ {{summary.deliveryAddress}}
11
+
12
+ Billing address:
13
+ {{summary.billingAddress}}
14
+
15
+ Order Details:
16
+
17
+ Items:
18
+ {{#positions}}
19
+ * {{quantity}} {{productTexts.title}}: {{total}}
20
+ {{/positions}}
21
+
22
+ {{#summary.rawPrices.delivery.amount}}
23
+ Delivery Fees: {{summary.prices.delivery}}
24
+ {{/summary.rawPrices.delivery.amount}}
25
+ {{#summary.rawPrices.payment.amount}}
26
+ Payment Fees: {{summary.prices.payment}}
27
+ {{/summary.rawPrices.payment.amount}}
28
+ Total: {{summary.prices.gross}}
29
+ {{#summary.rawPrices.taxes.amount}}
30
+ (VAT included: {{summary.prices.taxes}})
31
+ {{/summary.rawPrices.taxes.amount}}
32
+ `;
33
+
34
+ export const transformOrderToText = async ({ order, locale }, context) => {
35
+ const { modules } = context;
36
+ const data = {
37
+ orderDate: new Date(order.ordered).toLocaleString(),
38
+ orderNumber: order.orderNumber,
39
+ summary: await getOrderSummaryData(order, { locale }, context),
40
+ positions: await getOrderPositionsData(order, { locale }, context),
41
+ };
42
+
43
+ return modules.messaging.renderToText(textTemplate, data);
44
+ };
@@ -1,5 +1,5 @@
1
1
  import { TemplateResolver } from '@unchainedshop/types/messaging.js';
2
- import formatWorkItems from './utils/formatWorkItems.js';
2
+ import util from 'util';
3
3
 
4
4
  const {
5
5
  EMAIL_FROM = 'noreply@unchained.local',
@@ -8,6 +8,15 @@ const {
8
8
  ROOT_URL,
9
9
  } = process.env;
10
10
 
11
+ const formatWorkItems = (workItems) => {
12
+ return workItems
13
+ .map(({ _id, type, started, error }) => {
14
+ const stringifiedErrors = util.inspect(error, false, 10, false);
15
+ return `${new Date(started).toLocaleString()} ${type} (${_id}): ${stringifiedErrors}`;
16
+ })
17
+ .join('\n');
18
+ };
19
+
11
20
  const textTemplate = `
12
21
  -------------------------
13
22
  Unchained Endpoint: {{endpoint}}
@@ -1,44 +1,21 @@
1
1
  import { TemplateResolver } from '@unchainedshop/types/messaging.js';
2
2
  import { systemLocale } from '@unchainedshop/utils';
3
- import { getOrderAttachmentsData } from './utils/getOrderAttachmentsData.js';
4
- import { getOrderPositionsData } from './utils/getOrderPositionsData.js';
3
+ import { transformOrderToText } from './order-parser/index.js';
5
4
 
6
- const { EMAIL_FROM, EMAIL_WEBSITE_NAME, ROOT_URL } = process.env;
5
+ const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
7
6
 
8
7
  const textTemplate = `
9
- {{subject}}\n
10
- \n
11
- Order number: {{orderNumber}}\n
12
- Order date: {{orderDate}}\n
13
- Link: {{adminUILink}}\n
14
- \n
15
- Delivery address:\n
16
- -----------------\n
17
- {{address.firstName}} {{address.lastName}}\n
18
- {{address.company}}\n
19
- {{address.addressLine}}\n
20
- {{address.addressLine2}}\n
21
- {{address.postalCode}} {{address.city}}\n
22
- {{address.regionCode}}\n
23
- {{address.countryCode}}\n
24
- \n
25
- Articles:\n
26
- -----------------\n
27
- {{#items}}
28
- * {{sku}} - {{name}} CHF {{price}} {{quantity}}\n
29
- {{/items}}
8
+ New Order received:
9
+
10
+ {{orderDetails}}
11
+
12
+ {{shopName}}: {{shopUrl}}
30
13
  `;
31
14
 
32
15
  export const resolveForwardDeliveryTemplate: TemplateResolver = async ({ config, orderId }, context) => {
33
16
  const { modules } = context;
34
17
  const order = await modules.orders.findOrder({ orderId });
35
- const orderPricing = modules.orders.pricingSheet(order);
36
-
37
- const orderDate = new Date(order.ordered).toLocaleString();
38
18
 
39
- const attachments = await getOrderAttachmentsData(order, { fileType: 'DELIVERY_NOTE' }, context);
40
-
41
- const address = order.billingAddress;
42
19
  const configObject = config.reduce((acc, { key, value }) => {
43
20
  return {
44
21
  ...acc,
@@ -46,33 +23,23 @@ export const resolveForwardDeliveryTemplate: TemplateResolver = async ({ config,
46
23
  };
47
24
  }, {});
48
25
 
49
- const subject = `${EMAIL_WEBSITE_NAME}: New Order / ${order.orderNumber}`;
50
-
51
- const adminUILink = `${ROOT_URL}/orders/view/?_id=${order._id}`;
26
+ const subject = `${EMAIL_WEBSITE_NAME} Order ${order.orderNumber}`;
52
27
 
53
28
  const data = {
54
- contact: order.contact || {},
55
- adminUILink,
56
- items: getOrderPositionsData(order, { locale: systemLocale }, context),
57
- orderDate,
58
- orderNumber: order.orderNumber,
59
29
  shopName: EMAIL_WEBSITE_NAME,
60
- subject,
61
- total: orderPricing.total({ useNetPrice: false }).amount / 100,
62
- ...configObject,
63
- address,
30
+ shopUrl: EMAIL_WEBSITE_URL,
31
+ orderDetails: await transformOrderToText({ order, locale: systemLocale }, context),
64
32
  };
65
33
 
66
34
  return [
67
35
  {
68
36
  type: 'EMAIL',
69
37
  input: {
70
- from: configObject.from || EMAIL_FROM || 'noreply@unchained.local',
38
+ from: `${EMAIL_WEBSITE_NAME} <${configObject.from || EMAIL_FROM || 'noreply@unchained.local'}>`,
71
39
  to: configObject.to || 'orders@unchained.local',
72
40
  cc: configObject.cc,
73
41
  subject,
74
42
  text: modules.messaging.renderToText(textTemplate, data),
75
- attachments,
76
43
  },
77
44
  },
78
45
  ];
@@ -1,37 +1,15 @@
1
1
  import { TemplateResolver } from '@unchainedshop/types/messaging.js';
2
- import { OrderPricingRowCategory } from '@unchainedshop/types/orders.pricing.js';
3
- import { getOrderAttachmentsData } from './utils/getOrderAttachmentsData.js';
4
- import { getOrderPositionsData } from './utils/getOrderPositionsData.js';
2
+ import { transformOrderToText } from './order-parser/index.js';
5
3
 
6
4
  const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
7
5
 
8
6
  const textTemplate = `
9
- {{subject}}\n
10
- \n
11
- {{thankyou}}\n
12
- \n
13
- -----------------\n
14
- {{buttonText}}: {{url}}\n
15
- -----------------\n
16
- `;
7
+ Thank you very much for your order.
17
8
 
18
- const texts = {
19
- en: {
20
- buttonText: 'Follow purchase order status',
21
- thankyou: 'Thank you for your order on',
22
- subject: `${EMAIL_WEBSITE_NAME}: Order confirmation`,
23
- },
24
- de: {
25
- buttonText: 'Bestellstatus verfolgen',
26
- thankyou: 'Vielen Dank für deine Bestellung bei',
27
- subject: `${EMAIL_WEBSITE_NAME}: Bestellbestätigung`,
28
- },
29
- fr: {
30
- buttonText: 'Follow purchase order status',
31
- thankyou: 'Thank you for your order on',
32
- subject: `${EMAIL_WEBSITE_NAME}: Order confirmation`,
33
- },
34
- };
9
+ {{orderDetails}}
10
+
11
+ {{shopName}}: {{shopUrl}}
12
+ `;
35
13
 
36
14
  export const resolveOrderConfirmationTemplate: TemplateResolver = async (
37
15
  { orderId, locale },
@@ -44,63 +22,22 @@ export const resolveOrderConfirmationTemplate: TemplateResolver = async (
44
22
  return [];
45
23
  }
46
24
 
47
- const formatPrice = (price: number) => {
48
- const fixedPrice = price / 100;
49
- return `${order.currency} ${fixedPrice}`;
50
- };
51
-
52
- // TODO: If order.status is PENDING, we should only send the user
53
- // a notice that we have received the order but not confirming it
54
- const attachments = await getOrderAttachmentsData(order, { fileType: 'ORDER_CONFIRMATION' }, context);
55
-
56
- const orderPricing = modules.orders.pricingSheet(order);
57
-
58
- const { subject } = texts[locale.language];
25
+ const subject = `Order ${order.orderNumber}`;
59
26
 
60
27
  const data = {
61
- ...texts[locale.language],
62
28
  shopName: EMAIL_WEBSITE_NAME,
63
29
  shopUrl: EMAIL_WEBSITE_URL,
64
- subject,
65
- url: `${EMAIL_WEBSITE_URL}/order?_id=${order._id}`,
66
- summary: {
67
- items: formatPrice(
68
- orderPricing.total({
69
- category: OrderPricingRowCategory.Items,
70
- useNetPrice: false,
71
- }).amount,
72
- ),
73
- taxes: formatPrice(
74
- orderPricing.total({
75
- category: OrderPricingRowCategory.Taxes,
76
- useNetPrice: false,
77
- }).amount,
78
- ),
79
- delivery: formatPrice(
80
- orderPricing.total({
81
- category: OrderPricingRowCategory.Delivery,
82
- useNetPrice: false,
83
- }).amount,
84
- ),
85
- payment: formatPrice(
86
- orderPricing.total({
87
- category: OrderPricingRowCategory.Payment,
88
- useNetPrice: false,
89
- }).amount,
90
- ),
91
- gross: formatPrice(orderPricing.total({ useNetPrice: false }).amount),
92
- },
93
- positions: getOrderPositionsData(order, { locale }, context),
30
+ orderDetails: await transformOrderToText({ order, locale }, context),
94
31
  };
32
+
95
33
  return [
96
34
  {
97
35
  type: 'EMAIL',
98
36
  input: {
99
- from: EMAIL_FROM || 'orders@unchained.local',
37
+ from: `${EMAIL_WEBSITE_NAME} <${EMAIL_FROM || 'noreply@unchained.local'}>`,
100
38
  to: order.contact.emailAddress,
101
39
  subject,
102
40
  text: modules.messaging.renderToText(textTemplate, data),
103
- attachments,
104
41
  },
105
42
  },
106
43
  ];
@@ -1,34 +1,19 @@
1
1
  import { TemplateResolver } from '@unchainedshop/types/messaging.js';
2
+ import { transformOrderToText } from './order-parser/index.js';
2
3
 
3
4
  const { EMAIL_FROM, EMAIL_WEBSITE_NAME, EMAIL_WEBSITE_URL } = process.env;
4
5
 
5
6
  const textTemplate = `
6
- {{subject}}\n
7
- \n
8
- {{rejection}}\n
9
- \n
10
- -----------------\n
11
- {{buttonText}}: {{url}}\n
12
- -----------------\n
13
- `;
7
+ I'm sorry we can't confirm your order.
14
8
 
15
- const texts = {
16
- en: {
17
- buttonText: 'Details are available at',
18
- rejection: 'Your order was cancelled.',
19
- subject: `${EMAIL_WEBSITE_NAME}: Order cancelled`,
20
- },
21
- de: {
22
- buttonText: 'Details abrufen',
23
- rejection: 'Deine Bestellung wurde storniert',
24
- subject: `${EMAIL_WEBSITE_NAME}: Bestellung storniert`,
25
- },
26
- fr: {
27
- buttonText: 'Details are available at',
28
- rejection: 'Your order was cancelled.',
29
- subject: `${EMAIL_WEBSITE_NAME}: Order cancelled`,
30
- },
31
- };
9
+ This can happen when the payment was not successful or the order was manually canceled because of product availability or fullfillment issues.
10
+
11
+ The order in question is:
12
+
13
+ {{orderDetails}}
14
+
15
+ {{shopName}}: {{shopUrl}}
16
+ `;
32
17
 
33
18
  export const resolveOrderRejectionTemplate: TemplateResolver = async ({ orderId, locale }, context) => {
34
19
  const { modules } = context;
@@ -38,18 +23,19 @@ export const resolveOrderRejectionTemplate: TemplateResolver = async ({ orderId,
38
23
  return [];
39
24
  }
40
25
 
41
- const { subject } = texts[locale.language];
26
+ const subject = `Order rejected ${order.orderNumber}`;
42
27
 
43
28
  const data = {
44
- ...texts[locale.language],
45
- subject,
46
- url: `${EMAIL_WEBSITE_URL}/order?_id=${order._id}`,
29
+ shopName: EMAIL_WEBSITE_NAME,
30
+ shopUrl: EMAIL_WEBSITE_URL,
31
+ orderDetails: await transformOrderToText({ order, locale }, context),
47
32
  };
33
+
48
34
  return [
49
35
  {
50
36
  type: 'EMAIL',
51
37
  input: {
52
- from: EMAIL_FROM || 'orders@unchained.local',
38
+ from: `${EMAIL_WEBSITE_NAME} <${EMAIL_FROM || 'noreply@unchained.local'}>`,
53
39
  to: order.contact.emailAddress,
54
40
  subject,
55
41
  text: modules.messaging.renderToText(textTemplate, data),
@@ -1,2 +0,0 @@
1
- declare const _default: (workItems: any) => any;
2
- export default _default;
@@ -1,10 +0,0 @@
1
- import util from 'util';
2
- export default (workItems) => {
3
- return workItems
4
- .map(({ _id, type, started, error }) => {
5
- const stringifiedErrors = util.inspect(error, false, 10, false);
6
- return `${new Date(started).toLocaleString()} ${type} (${_id}): ${stringifiedErrors}`;
7
- })
8
- .join('\n');
9
- };
10
- //# sourceMappingURL=formatWorkItems.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatWorkItems.js","sourceRoot":"","sources":["../../../src/templates/utils/formatWorkItems.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,eAAe,CAAC,SAAS,EAAE,EAAE;IAC3B,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACrC,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAChE,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,IAAI,IAAI,KAAK,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACxF,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC"}
@@ -1,8 +0,0 @@
1
- import { UnchainedCore } from '@unchainedshop/types/core.js';
2
- import { Order } from '@unchainedshop/types/orders.js';
3
- export declare const getOrderAttachmentsData: (order: Order, params: {
4
- fileType: string;
5
- }, { modules }: UnchainedCore) => Promise<{
6
- filename: string;
7
- path: any;
8
- }[]>;
@@ -1,21 +0,0 @@
1
- export const getOrderAttachmentsData = async (order, params, { modules }) => {
2
- const attachments = [];
3
- const orderFiles = await modules.files.findFiles({ 'meta.orderId': order._id, 'meta.type': params.fileType }, { limit: 1 });
4
- attachments.concat(orderFiles);
5
- const payment = await modules.orders.payments.findOrderPayment({
6
- orderPaymentId: order.paymentId,
7
- }, { limit: 1 });
8
- if (modules.orders.payments.isBlockingOrderFullfillment(payment)) {
9
- const invoices = await modules.files.findFiles({ 'meta.orderId': order._id, 'meta.type': 'INVOICE' }, { limit: 1 });
10
- attachments.concat(invoices);
11
- }
12
- else {
13
- const receipts = await modules.files.findFiles({ 'meta.orderId': order._id, 'meta.type': 'RECEIPT' }, { limit: 1 });
14
- attachments.concat(receipts);
15
- }
16
- return attachments.map((file) => ({
17
- filename: `${order.orderNumber}_${file.name}`,
18
- path: file.path,
19
- }));
20
- };
21
- //# sourceMappingURL=getOrderAttachmentsData.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getOrderAttachmentsData.js","sourceRoot":"","sources":["../../../src/templates/utils/getOrderAttachmentsData.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,KAAY,EACZ,MAA4B,EAC5B,EAAE,OAAO,EAAiB,EAC1B,EAAE;IACF,MAAM,WAAW,GAAG,EAAE,CAAC;IAEvB,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,CAC9C,EAAE,cAAc,EAAE,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,EAC3D,EAAE,KAAK,EAAE,CAAC,EAAE,CACb,CAAC;IACF,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAC5D;QACE,cAAc,EAAE,KAAK,CAAC,SAAS;KAChC,EACD,EAAE,KAAK,EAAE,CAAC,EAAE,CACb,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,2BAA2B,CAAC,OAAO,CAAC,EAAE;QAChE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,CAC5C,EAAE,cAAc,EAAE,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,EACrD,EAAE,KAAK,EAAE,CAAC,EAAE,CACb,CAAC;QACF,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;KAC9B;SAAM;QACL,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,CAC5C,EAAE,cAAc,EAAE,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,EACrD,EAAE,KAAK,EAAE,CAAC,EAAE,CACb,CAAC;QACF,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;KAC9B;IAED,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAChC,QAAQ,EAAE,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE;QAC7C,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAC,CAAC;AACN,CAAC,CAAC"}
@@ -1,6 +0,0 @@
1
- import { Locale } from '@unchainedshop/types/common.js';
2
- import { UnchainedCore } from '@unchainedshop/types/core.js';
3
- import { Order } from '@unchainedshop/types/orders.js';
4
- export declare const getOrderPositionsData: (order: Order, params: {
5
- locale?: Locale;
6
- }, context: UnchainedCore) => Promise<void>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"getOrderPositionsData.js","sourceRoot":"","sources":["../../../src/templates/utils/getOrderPositionsData.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,KAAY,EACZ,MAA2B,EAC3B,OAAsB,EACtB,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC;QACvE,OAAO,EAAE,KAAK,CAAC,GAAG;KACnB,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE;QACpC,MAAM,UAAU,GAAG,KAAK,GAAG,GAAG,CAAC;QAC/B,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,UAAU,EAAE,CAAC;IAC3C,CAAC,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CACf,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;QACzC,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAClE,SAAS,EAAE,aAAa,CAAC,SAAS;YAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QACH,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC1E,SAAS,EAAE,aAAa,CAAC,iBAAiB;YAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU;SAClC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,YAAY,EAAE,KAAK,CAAC,CAAC,aAAa;QAEvD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAC3D,aAAa,EACb,KAAK,CAAC,QAAQ,EACd,OAAO,CACR,CAAC;QACF,MAAM,KAAK,GAAG,WAAW,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,CAAC;QACrC,OAAO;YACL,oBAAoB;YACpB,OAAO,EAAE,YAAY;YACrB,YAAY;YACZ,QAAQ;YACR,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC"}
@@ -1,10 +0,0 @@
1
- import util from 'util';
2
-
3
- export default (workItems) => {
4
- return workItems
5
- .map(({ _id, type, started, error }) => {
6
- const stringifiedErrors = util.inspect(error, false, 10, false);
7
- return `${new Date(started).toLocaleString()} ${type} (${_id}): ${stringifiedErrors}`;
8
- })
9
- .join('\n');
10
- };
@@ -1,40 +0,0 @@
1
- import { UnchainedCore } from '@unchainedshop/types/core.js';
2
- import { Order } from '@unchainedshop/types/orders.js';
3
-
4
- export const getOrderAttachmentsData = async (
5
- order: Order,
6
- params: { fileType: string },
7
- { modules }: UnchainedCore,
8
- ) => {
9
- const attachments = [];
10
-
11
- const orderFiles = await modules.files.findFiles(
12
- { 'meta.orderId': order._id, 'meta.type': params.fileType },
13
- { limit: 1 },
14
- );
15
- attachments.concat(orderFiles);
16
- const payment = await modules.orders.payments.findOrderPayment(
17
- {
18
- orderPaymentId: order.paymentId,
19
- },
20
- { limit: 1 },
21
- );
22
- if (modules.orders.payments.isBlockingOrderFullfillment(payment)) {
23
- const invoices = await modules.files.findFiles(
24
- { 'meta.orderId': order._id, 'meta.type': 'INVOICE' },
25
- { limit: 1 },
26
- );
27
- attachments.concat(invoices);
28
- } else {
29
- const receipts = await modules.files.findFiles(
30
- { 'meta.orderId': order._id, 'meta.type': 'RECEIPT' },
31
- { limit: 1 },
32
- );
33
- attachments.concat(receipts);
34
- }
35
-
36
- return attachments.map((file) => ({
37
- filename: `${order.orderNumber}_${file.name}`,
38
- path: file.path,
39
- }));
40
- };