@hartl-services/medusa-base 1.1.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +3 -1
- package/.medusa/server/src/admin/index.mjs +3 -1
- package/.medusa/server/src/api/customer-verification-request-throttle.js +50 -0
- package/.medusa/server/src/api/middlewares.js +31 -1
- package/.medusa/server/src/api/store/customer-verification/resend/route.js +17 -0
- package/.medusa/server/src/documents/utils/document-merchant.js +5 -5
- package/.medusa/server/src/email/application/handle-customer-verification-event.js +341 -0
- package/.medusa/server/src/email/application/resend-customer-verification.js +65 -0
- package/.medusa/server/src/email/application/start-customer-verification-snapshot.js +21 -0
- package/.medusa/server/src/email/application/throttle-verification-request.js +49 -0
- package/.medusa/server/src/email/customer-verification-snapshot.js +144 -0
- package/.medusa/server/src/email/domain/business-keys.js +12 -2
- package/.medusa/server/src/email/domain/customer-verification-resend.js +37 -0
- package/.medusa/server/src/email/domain/event-schemas.js +18 -2
- package/.medusa/server/src/email/plugin-features.js +9 -2
- package/.medusa/server/src/email/rendering/default-templates.js +20 -1
- package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +5 -1
- package/.medusa/server/src/email/types/email-kinds.js +14 -2
- package/.medusa/server/src/email/types/template-data.js +9 -1
- package/.medusa/server/src/modules/documents/domain/merchant.js +2 -33
- package/.medusa/server/src/modules/documents/domain/options.js +1 -7
- package/.medusa/server/src/modules/email/migrations/Migration20261001090000.js +16 -0
- package/.medusa/server/src/modules/email/service.js +30 -8
- package/.medusa/server/src/public/shop-master-data.js +6 -6
- package/.medusa/server/src/shop-config/build-food-shop-config.js +17 -6
- package/.medusa/server/src/shop-config/options.js +1 -15
- package/.medusa/server/src/subscribers/customer-verification.js +23 -0
- package/.medusa/server/src/workflows/documents/issue-cancellation-after-refund.js +2 -3
- package/.medusa/server/src/workflows/documents/issue-document.js +3 -4
- package/.medusa/server/src/workflows/documents/issue-packing-list.js +2 -2
- package/.medusa/server/src/workflows/email/dispatch-email-message.js +4 -2
- package/README.md +154 -49
- package/dist/documents/types/documents.d.ts +0 -22
- package/dist/email/customer-verification-snapshot.d.ts +53 -0
- package/dist/email/customer-verification-snapshot.js +143 -0
- package/dist/email/types/email-kinds.d.ts +9 -1
- package/dist/email/types/email-kinds.js +13 -1
- package/dist/email/types/shop-configuration.d.ts +8 -0
- package/dist/email/types/template-data.d.ts +9 -0
- package/dist/email/types/template-data.js +8 -0
- package/dist/modules/documents/domain/options.d.ts +1 -9
- package/dist/modules/documents/domain/options.js +0 -6
- package/dist/public/shop-master-data.d.ts +4 -5
- package/dist/public/shop-master-data.js +5 -5
- package/dist/shop-config/build-food-shop-config.js +16 -5
- package/dist/shop-config/options.d.ts +4 -6
- package/dist/shop-config/options.js +0 -14
- package/package.json +2 -2
- package/dist/modules/documents/domain/merchant.d.ts +0 -22
- package/dist/modules/documents/domain/merchant.js +0 -85
|
@@ -363,6 +363,9 @@ export declare const EmailPersistedDataSchemas: {
|
|
|
363
363
|
locale: z.ZodNullable<z.ZodString>;
|
|
364
364
|
}, z.core.$strict>;
|
|
365
365
|
readonly "user.invite": z.ZodObject<{}, z.core.$strict>;
|
|
366
|
+
readonly "auth.verification": z.ZodObject<{
|
|
367
|
+
locale: z.ZodNullable<z.ZodString>;
|
|
368
|
+
}, z.core.$strict>;
|
|
366
369
|
};
|
|
367
370
|
export declare const EmailRenderDataSchemas: {
|
|
368
371
|
readonly "auth.password_reset": z.ZodObject<{
|
|
@@ -374,6 +377,10 @@ export declare const EmailRenderDataSchemas: {
|
|
|
374
377
|
invite_url: z.ZodString;
|
|
375
378
|
expires_at: z.ZodOptional<z.ZodString>;
|
|
376
379
|
}, z.core.$strict>;
|
|
380
|
+
readonly "auth.verification": z.ZodObject<{
|
|
381
|
+
locale: z.ZodNullable<z.ZodString>;
|
|
382
|
+
verify_url: z.ZodString;
|
|
383
|
+
}, z.core.$strict>;
|
|
377
384
|
readonly "order.received": z.ZodObject<{
|
|
378
385
|
order_id: z.ZodString;
|
|
379
386
|
summary: z.ZodOptional<z.ZodObject<{
|
|
@@ -601,6 +608,8 @@ export type EmailEphemeralRenderContextMap = {
|
|
|
601
608
|
}> : Kind extends "user.invite" ? Readonly<{
|
|
602
609
|
invite_url: string;
|
|
603
610
|
expires_at?: string;
|
|
611
|
+
}> : Kind extends "auth.verification" ? Readonly<{
|
|
612
|
+
verify_url: string;
|
|
604
613
|
}> : EmptyRenderContext;
|
|
605
614
|
};
|
|
606
615
|
export type EmailRenderDataMap = {
|
|
@@ -215,6 +215,11 @@ exports.EmailPersistedDataSchemas = {
|
|
|
215
215
|
})
|
|
216
216
|
.strict(),
|
|
217
217
|
"user.invite": zod_1.z.object({}).strict(),
|
|
218
|
+
"auth.verification": zod_1.z
|
|
219
|
+
.object({
|
|
220
|
+
locale: NullableLocaleSchema,
|
|
221
|
+
})
|
|
222
|
+
.strict(),
|
|
218
223
|
};
|
|
219
224
|
exports.EmailRenderDataSchemas = {
|
|
220
225
|
...exports.EmailPersistedDataSchemas,
|
|
@@ -228,4 +233,7 @@ exports.EmailRenderDataSchemas = {
|
|
|
228
233
|
/** When the invite expires (ISO 8601), from the current invite. */
|
|
229
234
|
expires_at: zod_1.z.string().datetime().optional(),
|
|
230
235
|
}),
|
|
236
|
+
"auth.verification": exports.EmailPersistedDataSchemas["auth.verification"].extend({
|
|
237
|
+
verify_url: zod_1.z.string().url(),
|
|
238
|
+
}),
|
|
231
239
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { DocumentHtmlFactory } from "../../../documents/types/html-factory";
|
|
2
|
-
import type {
|
|
3
|
-
import { type DocumentMerchantValues } from "./merchant";
|
|
2
|
+
import type { DocumentPdfOptions } from "../../../documents/types/documents";
|
|
4
3
|
/** Used when the `documents.numbering.timeZone` option is not given. */
|
|
5
4
|
export declare const DEFAULT_NUMBERING_TIME_ZONE = "Europe/Vienna";
|
|
6
5
|
/** The `documents` namespace of the base plugin options. */
|
|
@@ -10,11 +9,6 @@ export type DocumentPluginOptions = {
|
|
|
10
9
|
* `createDefaultDocumentHtmlFactory` with the `numbering.timeZone`.
|
|
11
10
|
*/
|
|
12
11
|
htmlFactory?: DocumentHtmlFactory;
|
|
13
|
-
/**
|
|
14
|
-
* Fallback for the shop master data of the base plugin: used per field
|
|
15
|
-
* only where no value is stored there.
|
|
16
|
-
*/
|
|
17
|
-
merchant?: DocumentMerchantOption;
|
|
18
12
|
numbering?: {
|
|
19
13
|
timeZone?: string;
|
|
20
14
|
};
|
|
@@ -22,8 +16,6 @@ export type DocumentPluginOptions = {
|
|
|
22
16
|
};
|
|
23
17
|
export type ResolvedDocumentPluginOptions = {
|
|
24
18
|
htmlFactory: DocumentHtmlFactory;
|
|
25
|
-
/** The `merchant` option keyed by shop master data field. */
|
|
26
|
-
merchantFallback: DocumentMerchantValues;
|
|
27
19
|
numbering: {
|
|
28
20
|
timeZone: string;
|
|
29
21
|
};
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.resolveDocumentPluginOptions = exports.DEFAULT_NUMBERING_TIME_ZONE = void 0;
|
|
4
4
|
const utils_1 = require("@medusajs/framework/utils");
|
|
5
5
|
const html_factory_1 = require("../../../documents/templates/html-factory");
|
|
6
|
-
const merchant_1 = require("./merchant");
|
|
7
6
|
/** Used when the `documents.numbering.timeZone` option is not given. */
|
|
8
7
|
exports.DEFAULT_NUMBERING_TIME_ZONE = "Europe/Vienna";
|
|
9
8
|
const resolveDocumentPluginOptions = (options) => {
|
|
@@ -24,14 +23,9 @@ const resolveDocumentPluginOptions = (options) => {
|
|
|
24
23
|
typeof options.htmlFactory !== "function") {
|
|
25
24
|
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "The documents 'htmlFactory' option must be a function.");
|
|
26
25
|
}
|
|
27
|
-
if (options?.merchant !== undefined &&
|
|
28
|
-
(typeof options.merchant !== "object" || options.merchant === null)) {
|
|
29
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "The documents 'merchant' option must be an object.");
|
|
30
|
-
}
|
|
31
26
|
const executablePath = options?.pdf?.executablePath?.trim() || "google-chrome";
|
|
32
27
|
return {
|
|
33
28
|
htmlFactory: options?.htmlFactory ?? (0, html_factory_1.createDefaultDocumentHtmlFactory)({ timeZone }),
|
|
34
|
-
merchantFallback: (0, merchant_1.merchantOptionToFallback)(options?.merchant),
|
|
35
29
|
numbering: { timeZone },
|
|
36
30
|
pdf: { executablePath },
|
|
37
31
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { MedusaContainer } from "@medusajs/framework/types";
|
|
2
|
-
import type { PluginSettingsFallback } from "./types";
|
|
3
2
|
/**
|
|
4
3
|
* The base's own descriptor: the shop's master data (Firmenangaben), edited
|
|
5
4
|
* on the generic plugin page like any plugin's settings. It cannot be
|
|
@@ -18,8 +17,8 @@ export type ResolvedShopMasterData = {
|
|
|
18
17
|
missing: ShopMasterDataKey[];
|
|
19
18
|
};
|
|
20
19
|
/**
|
|
21
|
-
* The shop's master data for server-side code
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* The shop's master data for server-side code, exactly as stored in the
|
|
21
|
+
* Admin: there is no config fallback. A missing base plugin fails with
|
|
22
|
+
* `UNEXPECTED_STATE`; read failures propagate.
|
|
24
23
|
*/
|
|
25
|
-
export declare function getShopMasterData(container: MedusaContainer
|
|
24
|
+
export declare function getShopMasterData(container: MedusaContainer): Promise<ResolvedShopMasterData>;
|
|
@@ -74,12 +74,12 @@ exports.shopMasterDataDescriptor = (0, descriptor_1.definePluginFeatures)({
|
|
|
74
74
|
],
|
|
75
75
|
});
|
|
76
76
|
/**
|
|
77
|
-
* The shop's master data for server-side code
|
|
78
|
-
*
|
|
79
|
-
*
|
|
77
|
+
* The shop's master data for server-side code, exactly as stored in the
|
|
78
|
+
* Admin: there is no config fallback. A missing base plugin fails with
|
|
79
|
+
* `UNEXPECTED_STATE`; read failures propagate.
|
|
80
80
|
*/
|
|
81
|
-
async function getShopMasterData(container
|
|
82
|
-
const resolved = await (0, settings_1.getPluginSettings)(container, exports.shopMasterDataDescriptor
|
|
81
|
+
async function getShopMasterData(container) {
|
|
82
|
+
const resolved = await (0, settings_1.getPluginSettings)(container, exports.shopMasterDataDescriptor);
|
|
83
83
|
const values = {};
|
|
84
84
|
for (const [key, value] of Object.entries(resolved.values)) {
|
|
85
85
|
if (typeof value === "string") {
|
|
@@ -5,6 +5,7 @@ exports.defineFoodShopConfig = defineFoodShopConfig;
|
|
|
5
5
|
const logger_1 = require("@medusajs/framework/logger");
|
|
6
6
|
const utils_1 = require("@medusajs/framework/utils");
|
|
7
7
|
const config_1 = require("../public/config");
|
|
8
|
+
const customer_verification_snapshot_1 = require("../email/customer-verification-snapshot");
|
|
8
9
|
const sentry_logger_1 = require("../public/sentry-logger");
|
|
9
10
|
const options_1 = require("./options");
|
|
10
11
|
/**
|
|
@@ -18,7 +19,6 @@ const options_1 = require("./options");
|
|
|
18
19
|
*/
|
|
19
20
|
function buildFoodShopConfig(options, environment = process.env) {
|
|
20
21
|
(0, options_1.assertFoodShopConfigOptions)(options);
|
|
21
|
-
const { merchant } = options;
|
|
22
22
|
if (options.loadEnvFile !== false) {
|
|
23
23
|
(0, utils_1.loadEnv)(process.env.NODE_ENV || "development", process.cwd());
|
|
24
24
|
}
|
|
@@ -157,14 +157,14 @@ function buildFoodShopConfig(options, environment = process.env) {
|
|
|
157
157
|
orderNotificationEmail: options.orderNotificationEmail,
|
|
158
158
|
// The e-mail module appends "#token=<token>".
|
|
159
159
|
passwordResetUrl: () => (0, config_1.shopUrl)(storefrontOrigin, `${storefrontPath}/reset-password`),
|
|
160
|
+
// Account confirmation (E-Mail toggle `customer_verification`);
|
|
161
|
+
// the e-mail module appends "#token=<token>".
|
|
162
|
+
verifyAccountUrl: () => (0, config_1.shopUrl)(storefrontOrigin, `${storefrontPath}/verify-account`),
|
|
160
163
|
timeZone: options.timeZone,
|
|
161
164
|
},
|
|
162
165
|
},
|
|
163
166
|
documents: {
|
|
164
167
|
htmlFactory: options.documentHtmlFactory,
|
|
165
|
-
// Fallback only: the shop master data in the Admin ("Hartl Services
|
|
166
|
-
// Plugins" -> Shop-Stammdaten) wins per field.
|
|
167
|
-
merchant,
|
|
168
168
|
numbering: {
|
|
169
169
|
// Chooses the annual document-number period; matches the date the
|
|
170
170
|
// HTML factory prints.
|
|
@@ -179,7 +179,7 @@ function buildFoodShopConfig(options, environment = process.env) {
|
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
181
|
resolve: "@hartl-services/medusa-tax-compliance",
|
|
182
|
-
options: {
|
|
182
|
+
options: {},
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
resolve: "@hartl-services/medusa-free-shipping",
|
|
@@ -231,6 +231,17 @@ function buildFoodShopConfig(options, environment = process.env) {
|
|
|
231
231
|
authCors: env.AUTH_CORS,
|
|
232
232
|
jwtSecret: env.JWT_SECRET,
|
|
233
233
|
cookieSecret: env.COOKIE_SECRET,
|
|
234
|
+
// Medusa reads this synchronously on every login and keeps the
|
|
235
|
+
// `authVerificationsPerActor` object (defineConfig and ConfigManager
|
|
236
|
+
// copy `http` shallowly), so a getter switches e-mail confirmation of
|
|
237
|
+
// customer accounts at run time. It answers from an in-memory copy of
|
|
238
|
+
// the E-Mail plugin's `customer_verification` toggle, refreshed at
|
|
239
|
+
// most every 30 s (see customer-verification-snapshot.ts).
|
|
240
|
+
authVerificationsPerActor: {
|
|
241
|
+
get customer() {
|
|
242
|
+
return (0, customer_verification_snapshot_1.customerVerificationActors)();
|
|
243
|
+
},
|
|
244
|
+
},
|
|
234
245
|
},
|
|
235
246
|
// The storefront turns its customer JWT into a Medusa browser session
|
|
236
247
|
// at login, so its browser-side cart and payment calls carry the
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import type { DocumentHtmlFactory
|
|
1
|
+
import type { DocumentHtmlFactory } from "../documents/types";
|
|
2
2
|
/**
|
|
3
3
|
* The shop-specific facts of a food shop. Deployment values and secrets are
|
|
4
4
|
* not options: they come from the environment (see the README).
|
|
5
5
|
*/
|
|
6
6
|
export type FoodShopConfigOptions = Readonly<{
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Shop name in the branding of the default e-mail templates (and the store
|
|
9
|
+
* name of a shop's initial seed). Company name, address and UID are not
|
|
10
|
+
* options: they come only from the Shop-Stammdaten in the Admin.
|
|
11
11
|
*/
|
|
12
|
-
merchant: DocumentMerchantOption;
|
|
13
|
-
/** Shop name in the branding of the default e-mail templates. */
|
|
14
12
|
displayName: string;
|
|
15
13
|
/** Receives the shop's order notification e-mails. */
|
|
16
14
|
orderNotificationEmail: string;
|
|
@@ -45,20 +45,6 @@ const requireObject = (value, name) => {
|
|
|
45
45
|
*/
|
|
46
46
|
function assertFoodShopConfigOptions(options) {
|
|
47
47
|
const candidate = requireObject(options, "options");
|
|
48
|
-
const merchant = requireObject(candidate.merchant, "merchant");
|
|
49
|
-
requireText(merchant.legalName, "merchant.legalName");
|
|
50
|
-
requireCountryCode(merchant.countryCode, "merchant.countryCode");
|
|
51
|
-
if (merchant.vatNumber !== undefined) {
|
|
52
|
-
requireText(merchant.vatNumber, "merchant.vatNumber");
|
|
53
|
-
}
|
|
54
|
-
const address = requireObject(merchant.registeredAddress, "merchant.registeredAddress");
|
|
55
|
-
requireText(address.address1, "merchant.registeredAddress.address1");
|
|
56
|
-
if (address.address2 !== undefined) {
|
|
57
|
-
requireText(address.address2, "merchant.registeredAddress.address2");
|
|
58
|
-
}
|
|
59
|
-
requireText(address.city, "merchant.registeredAddress.city");
|
|
60
|
-
requireText(address.postalCode, "merchant.registeredAddress.postalCode");
|
|
61
|
-
requireCountryCode(address.countryCode, "merchant.registeredAddress.countryCode");
|
|
62
48
|
requireText(candidate.displayName, "displayName");
|
|
63
49
|
requireEmail(candidate.orderNotificationEmail, "orderNotificationEmail");
|
|
64
50
|
requireTimeZone(candidate.timeZone, "timeZone");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hartl-services/medusa-base",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Base plugin for Hartl Services Medusa shops: per-plugin feature toggles with a generic Admin settings page, a Store endpoint for storefronts, enforcement helpers, the complete-cart hook composition, the root redirect, cart-promotion link repair, the built-in E-Mail, Documents and S3 file storage modules, config helpers with the turnkey food-shop preset, and the Sentry logger wrapper and instrumentation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"mime-types": "3.0.1",
|
|
89
89
|
"nodemailer": "6.10.1",
|
|
90
90
|
"ulid": "^2.4.0",
|
|
91
|
-
"@hartl-services/medusa-food-supplements-contracts": "^0.
|
|
91
|
+
"@hartl-services/medusa-food-supplements-contracts": "^0.18.0"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@medusajs/admin-sdk": "2.19.0",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { DocumentMerchant, DocumentMerchantOption } from "../../../documents/types/documents";
|
|
2
|
-
/** Shop master data keys (base plugin, `plugin_key: "shop"`) documents read. */
|
|
3
|
-
export type DocumentMerchantKey = keyof DocumentMerchant;
|
|
4
|
-
export type DocumentMerchantValues = Partial<Record<DocumentMerchantKey, string>>;
|
|
5
|
-
/** Without these a financial document or packing list has no legal sender. */
|
|
6
|
-
export declare const DOCUMENT_MERCHANT_REQUIRED_FIELDS: readonly ["legal_name", "address_line1", "postal_code", "city", "country_code"];
|
|
7
|
-
/** Development placeholder UID: never printed on a document. */
|
|
8
|
-
export declare const MERCHANT_VAT_PLACEHOLDER = "ATU00000000";
|
|
9
|
-
/**
|
|
10
|
-
* The plugin's `merchant` option as a per-field fallback for the shop master
|
|
11
|
-
* data. Empty values are left out so they never shadow a declared default.
|
|
12
|
-
*/
|
|
13
|
-
export declare const merchantOptionToFallback: (option: DocumentMerchantOption | undefined) => DocumentMerchantValues;
|
|
14
|
-
export type DocumentMerchantResolution = {
|
|
15
|
-
merchant: DocumentMerchant;
|
|
16
|
-
missing: [];
|
|
17
|
-
} | {
|
|
18
|
-
merchant: null;
|
|
19
|
-
missing: DocumentMerchantKey[];
|
|
20
|
-
};
|
|
21
|
-
/** Maps resolved shop master data to the render input's `merchant`. */
|
|
22
|
-
export declare const toDocumentMerchant: (values: DocumentMerchantValues) => DocumentMerchantResolution;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toDocumentMerchant = exports.merchantOptionToFallback = exports.MERCHANT_VAT_PLACEHOLDER = exports.DOCUMENT_MERCHANT_REQUIRED_FIELDS = void 0;
|
|
4
|
-
/** Without these a financial document or packing list has no legal sender. */
|
|
5
|
-
exports.DOCUMENT_MERCHANT_REQUIRED_FIELDS = [
|
|
6
|
-
"legal_name",
|
|
7
|
-
"address_line1",
|
|
8
|
-
"postal_code",
|
|
9
|
-
"city",
|
|
10
|
-
"country_code",
|
|
11
|
-
];
|
|
12
|
-
/** Development placeholder UID: never printed on a document. */
|
|
13
|
-
exports.MERCHANT_VAT_PLACEHOLDER = "ATU00000000";
|
|
14
|
-
const text = (value) => {
|
|
15
|
-
if (typeof value !== "string") {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
const trimmed = value.trim();
|
|
19
|
-
return trimmed ? trimmed : null;
|
|
20
|
-
};
|
|
21
|
-
const vatNumber = (value) => {
|
|
22
|
-
const normalized = text(value);
|
|
23
|
-
return normalized &&
|
|
24
|
-
normalized.replace(/\s+/g, "").toUpperCase() === exports.MERCHANT_VAT_PLACEHOLDER
|
|
25
|
-
? null
|
|
26
|
-
: normalized;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* The plugin's `merchant` option as a per-field fallback for the shop master
|
|
30
|
-
* data. Empty values are left out so they never shadow a declared default.
|
|
31
|
-
*/
|
|
32
|
-
const merchantOptionToFallback = (option) => {
|
|
33
|
-
if (!option) {
|
|
34
|
-
return {};
|
|
35
|
-
}
|
|
36
|
-
const address = option.registeredAddress;
|
|
37
|
-
const entries = [
|
|
38
|
-
["legal_name", option.legalName],
|
|
39
|
-
["address_line1", address?.address1],
|
|
40
|
-
["address_line2", address?.address2],
|
|
41
|
-
["postal_code", address?.postalCode],
|
|
42
|
-
["city", address?.city],
|
|
43
|
-
[
|
|
44
|
-
"country_code",
|
|
45
|
-
text(address?.countryCode ?? option.countryCode)?.toLowerCase(),
|
|
46
|
-
],
|
|
47
|
-
["vat_number", option.vatNumber],
|
|
48
|
-
];
|
|
49
|
-
const fallback = {};
|
|
50
|
-
for (const [key, value] of entries) {
|
|
51
|
-
const normalized = text(value);
|
|
52
|
-
if (normalized) {
|
|
53
|
-
fallback[key] = normalized;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return fallback;
|
|
57
|
-
};
|
|
58
|
-
exports.merchantOptionToFallback = merchantOptionToFallback;
|
|
59
|
-
/** Maps resolved shop master data to the render input's `merchant`. */
|
|
60
|
-
const toDocumentMerchant = (values) => {
|
|
61
|
-
const missing = exports.DOCUMENT_MERCHANT_REQUIRED_FIELDS.filter((key) => !text(values[key]));
|
|
62
|
-
if (missing.length > 0) {
|
|
63
|
-
return { merchant: null, missing };
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
merchant: {
|
|
67
|
-
legal_name: text(values.legal_name),
|
|
68
|
-
address_line1: text(values.address_line1),
|
|
69
|
-
address_line2: text(values.address_line2),
|
|
70
|
-
postal_code: text(values.postal_code),
|
|
71
|
-
city: text(values.city),
|
|
72
|
-
country_code: text(values.country_code).toLowerCase(),
|
|
73
|
-
vat_number: vatNumber(values.vat_number),
|
|
74
|
-
email: text(values.email),
|
|
75
|
-
phone: text(values.phone),
|
|
76
|
-
website: text(values.website),
|
|
77
|
-
iban: text(values.iban),
|
|
78
|
-
bic: text(values.bic),
|
|
79
|
-
company_register_number: text(values.company_register_number),
|
|
80
|
-
company_register_court: text(values.company_register_court),
|
|
81
|
-
},
|
|
82
|
-
missing: [],
|
|
83
|
-
};
|
|
84
|
-
};
|
|
85
|
-
exports.toDocumentMerchant = toDocumentMerchant;
|