@hartl-services/medusa-base 2.10.0 → 3.0.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.
Files changed (87) hide show
  1. package/.medusa/server/src/admin/index.js +44 -40
  2. package/.medusa/server/src/admin/index.mjs +44 -40
  3. package/.medusa/server/src/api/admin/tax-compliance/customer-addresses/[address_id]/tax-identification/route.js +15 -0
  4. package/.medusa/server/src/api/check-customer-address-tax-identification.js +93 -0
  5. package/.medusa/server/src/api/customer-address-identification-response.js +14 -0
  6. package/.medusa/server/src/api/middlewares.js +55 -1
  7. package/.medusa/server/src/api/store/carts/[id]/tax-identification/route.js +179 -0
  8. package/.medusa/server/src/api/store/customers/me/addresses/[address_id]/tax-identification/route.js +12 -0
  9. package/.medusa/server/src/api/store/customers/me/tax-identifications/route.js +14 -0
  10. package/.medusa/server/src/api/store/tax-identification-policy/route.js +21 -0
  11. package/.medusa/server/src/api/tax-identification-message.js +9 -0
  12. package/.medusa/server/src/api/to-response-amount.js +19 -0
  13. package/.medusa/server/src/email/application/deliver-ephemeral-auth-mail.js +2 -4
  14. package/.medusa/server/src/email/application/handle-password-reset-event.js +75 -27
  15. package/.medusa/server/src/email/rendering/default-templates.js +2 -1
  16. package/.medusa/server/src/email/rendering/render-email.js +2 -1
  17. package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +5 -1
  18. package/.medusa/server/src/email/templates/blocks/dynamic-blocks.js +5 -2
  19. package/.medusa/server/src/email/templates/defaults/documents.js +8 -1
  20. package/.medusa/server/src/email/templates/defaults/subjects.js +3 -1
  21. package/.medusa/server/src/email/templates/defaults/texts.js +4 -2
  22. package/.medusa/server/src/email/templates/render.js +2 -1
  23. package/.medusa/server/src/email/templates/sample-data.js +5 -1
  24. package/.medusa/server/src/email/types/email-kinds.js +3 -1
  25. package/.medusa/server/src/email/types/template-data.js +8 -1
  26. package/.medusa/server/src/jobs/tax-compliance-state-sync.js +26 -0
  27. package/.medusa/server/src/modules/email/migrations/Migration20261013120000.js +20 -0
  28. package/.medusa/server/src/modules/tax-compliance/domain/validation-policy.js +48 -0
  29. package/.medusa/server/src/modules/tax-compliance/index.js +15 -0
  30. package/.medusa/server/src/modules/tax-compliance/migrations/Migration20260814120459.js +18 -0
  31. package/.medusa/server/src/modules/tax-compliance/migrations/Migration20260814121724.js +14 -0
  32. package/.medusa/server/src/modules/tax-compliance/migrations/Migration20260814153410.js +14 -0
  33. package/.medusa/server/src/modules/tax-compliance/migrations/Migration20260929091620.js +27 -0
  34. package/.medusa/server/src/modules/tax-compliance/migrations/Migration20261011090147.js +16 -0
  35. package/.medusa/server/src/modules/tax-compliance/models/tax-compliance-state.js +29 -0
  36. package/.medusa/server/src/modules/tax-compliance/models/tax-compliance-validation.js +74 -0
  37. package/.medusa/server/src/modules/tax-compliance/runtime-settings.js +43 -0
  38. package/.medusa/server/src/modules/tax-compliance/service.js +693 -0
  39. package/.medusa/server/src/providers/tax-compliance/index.js +11 -0
  40. package/.medusa/server/src/providers/tax-compliance/service.js +179 -0
  41. package/.medusa/server/src/public/constants.js +4 -2
  42. package/.medusa/server/src/public/index.js +6 -2
  43. package/.medusa/server/src/public/tax-compliance.js +22 -0
  44. package/.medusa/server/src/shared/lib/index.js +2 -1
  45. package/.medusa/server/src/shared/lib/optional-registration.js +34 -0
  46. package/.medusa/server/src/shop-config/build-food-shop-config.js +12 -9
  47. package/.medusa/server/src/subscribers/tax-compliance-plugin-features-updated.js +25 -0
  48. package/.medusa/server/src/tax-compliance/complete-cart-hooks.js +26 -0
  49. package/.medusa/server/src/tax-compliance/integrations/finanzonline/client.js +222 -0
  50. package/.medusa/server/src/tax-compliance/integrations/finanzonline/validator.js +50 -0
  51. package/.medusa/server/src/tax-compliance/integrations/registry.js +26 -0
  52. package/.medusa/server/src/tax-compliance/integrations/validator.js +19 -0
  53. package/.medusa/server/src/tax-compliance/lib/order-tax-context.js +100 -0
  54. package/.medusa/server/src/tax-compliance/lib/tax-compliance-state.js +59 -0
  55. package/.medusa/server/src/tax-compliance/lib/tax-runtime-settings.js +79 -0
  56. package/.medusa/server/src/tax-compliance/plugin-features.js +73 -0
  57. package/.medusa/server/src/tax-compliance/resolve-services.js +7 -0
  58. package/.medusa/server/src/tax-compliance/types/tax-compliance.js +6 -0
  59. package/.medusa/server/src/workflows/documents/issue-invoice-after-shipment.js +25 -30
  60. package/.medusa/server/src/workflows/documents/issue-packing-list.js +3 -14
  61. package/.medusa/server/src/workflows/hooks/cart-tax-context.js +78 -0
  62. package/.medusa/server/src/workflows/hooks/order-tax-context.js +7 -0
  63. package/.medusa/server/src/workflows/hooks/shipping-tax-apportionment.js +145 -0
  64. package/.medusa/server/src/workflows/tax-compliance/apportion-order-shipping-tax.js +72 -0
  65. package/.medusa/server/src/workflows/tax-compliance/domain/requires-frozen-tax-evidence.js +27 -0
  66. package/.medusa/server/src/workflows/tax-compliance/freeze-order-evidence.js +125 -0
  67. package/.medusa/server/src/workflows/tax-compliance/submit-customer-address-tax-identification.js +18 -0
  68. package/.medusa/server/src/workflows/tax-compliance/submit-tax-identification.js +18 -0
  69. package/README.md +369 -27
  70. package/dist/email/types/email-kinds.d.ts +3 -2
  71. package/dist/email/types/email-kinds.js +2 -0
  72. package/dist/email/types/shop-configuration.d.ts +8 -0
  73. package/dist/email/types/template-data.d.ts +6 -1
  74. package/dist/email/types/template-data.js +7 -0
  75. package/dist/public/constants.d.ts +2 -0
  76. package/dist/public/constants.js +3 -1
  77. package/dist/public/index.d.ts +2 -1
  78. package/dist/public/index.js +5 -1
  79. package/dist/public/tax-compliance.d.ts +30 -0
  80. package/dist/public/tax-compliance.js +21 -0
  81. package/dist/shared/lib/index.d.ts +1 -0
  82. package/dist/shared/lib/index.js +1 -0
  83. package/dist/shared/lib/optional-registration.d.ts +18 -0
  84. package/dist/shared/lib/optional-registration.js +33 -0
  85. package/dist/shop-config/build-food-shop-config.d.ts +2 -2
  86. package/dist/shop-config/build-food-shop-config.js +11 -8
  87. package/package.json +5 -4
@@ -0,0 +1,30 @@
1
+ import type { MedusaContainer } from "@medusajs/framework/types";
2
+ export declare const TAX_COMPLIANCE_STATUSES: readonly ["eligible", "ineligible", "invalid", "unavailable"];
3
+ export type TaxComplianceStatus = (typeof TAX_COMPLIANCE_STATUSES)[number];
4
+ export type AddressSnapshot = {
5
+ address1: string;
6
+ address2?: string | null;
7
+ city: string;
8
+ countryCode: string;
9
+ postalCode: string;
10
+ };
11
+ /** Status of the current UID check of a saved customer address whose facts still match it. */
12
+ export type CustomerAddressTaxIdentification = {
13
+ customer_address_id: string;
14
+ status: TaxComplianceStatus;
15
+ customer_vat_number: string;
16
+ company_name: string;
17
+ validated_at: Date;
18
+ /** `eligible` or `ineligible`: the UID is real and matches company and address. */
19
+ verified: boolean;
20
+ /** The billing address the UID was checked against (`countryCode` lowercase, `address2` only when set). */
21
+ billing_address: AddressSnapshot;
22
+ };
23
+ /**
24
+ * The current UID check of each saved address of the customer that still
25
+ * matches the address as it is now, whatever its status (also `unavailable`
26
+ * and `invalid`). For other plugins, e.g. the Affiliate partner registration;
27
+ * the caller decides whether the `vat_validation` feature of `tax_compliance`
28
+ * is on (`isPluginFeatureEnabledByKey`).
29
+ */
30
+ export declare const listCustomerAddressTaxIdentifications: (container: MedusaContainer, customerId: string) => Promise<CustomerAddressTaxIdentification[]>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listCustomerAddressTaxIdentifications = exports.TAX_COMPLIANCE_STATUSES = void 0;
4
+ const constants_1 = require("./constants");
5
+ exports.TAX_COMPLIANCE_STATUSES = [
6
+ "eligible",
7
+ "ineligible",
8
+ "invalid",
9
+ "unavailable",
10
+ ];
11
+ /**
12
+ * The current UID check of each saved address of the customer that still
13
+ * matches the address as it is now, whatever its status (also `unavailable`
14
+ * and `invalid`). For other plugins, e.g. the Affiliate partner registration;
15
+ * the caller decides whether the `vat_validation` feature of `tax_compliance`
16
+ * is on (`isPluginFeatureEnabledByKey`).
17
+ */
18
+ const listCustomerAddressTaxIdentifications = (container, customerId) => container
19
+ .resolve(constants_1.TAX_COMPLIANCE_MODULE)
20
+ .listCustomerAddressIdentifications(customerId);
21
+ exports.listCustomerAddressTaxIdentifications = listCustomerAddressTaxIdentifications;
@@ -5,6 +5,7 @@ export * from "./errors";
5
5
  export * from "./hash";
6
6
  export * from "./logging";
7
7
  export * from "./money";
8
+ export * from "./optional-registration";
8
9
  export * from "./refreshing-snapshot";
9
10
  export * from "./shipping-tax";
10
11
  export * from "./text";
@@ -23,6 +23,7 @@ __exportStar(require("./errors"), exports);
23
23
  __exportStar(require("./hash"), exports);
24
24
  __exportStar(require("./logging"), exports);
25
25
  __exportStar(require("./money"), exports);
26
+ __exportStar(require("./optional-registration"), exports);
26
27
  __exportStar(require("./refreshing-snapshot"), exports);
27
28
  __exportStar(require("./shipping-tax"), exports);
28
29
  __exportStar(require("./text"), exports);
@@ -0,0 +1,18 @@
1
+ type ResolvingContainer = {
2
+ resolve<TValue = unknown>(name: string): TValue;
3
+ hasRegistration?: (name: string) => boolean;
4
+ };
5
+ /**
6
+ * Whether `error` is the container saying `name` is not registered: the
7
+ * awilix message Medusa throws ("Could not resolve 'name'. ...", only for the
8
+ * requested name itself, never a failing dependency further down the chain)
9
+ * or the older "Missing registration" wording.
10
+ */
11
+ export declare const isMissingRegistrationError: (error: unknown, name: string) => boolean;
12
+ /**
13
+ * Resolves an optional plugin's module service by its container key, or null
14
+ * while that plugin is not installed. A known-absent registration returns
15
+ * null without resolving; any other resolution failure is rethrown.
16
+ */
17
+ export declare const tryResolveOptional: <T>(container: ResolvingContainer, name: string) => T | null;
18
+ export {};
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tryResolveOptional = exports.isMissingRegistrationError = void 0;
4
+ /**
5
+ * Whether `error` is the container saying `name` is not registered: the
6
+ * awilix message Medusa throws ("Could not resolve 'name'. ...", only for the
7
+ * requested name itself, never a failing dependency further down the chain)
8
+ * or the older "Missing registration" wording.
9
+ */
10
+ const isMissingRegistrationError = (error, name) => error instanceof Error &&
11
+ (error.message.includes("Missing registration") ||
12
+ error.message.startsWith(`Could not resolve '${name}'`));
13
+ exports.isMissingRegistrationError = isMissingRegistrationError;
14
+ /**
15
+ * Resolves an optional plugin's module service by its container key, or null
16
+ * while that plugin is not installed. A known-absent registration returns
17
+ * null without resolving; any other resolution failure is rethrown.
18
+ */
19
+ const tryResolveOptional = (container, name) => {
20
+ if (container.hasRegistration?.(name) === false) {
21
+ return null;
22
+ }
23
+ try {
24
+ return container.resolve(name);
25
+ }
26
+ catch (error) {
27
+ if ((0, exports.isMissingRegistrationError)(error, name)) {
28
+ return null;
29
+ }
30
+ throw error;
31
+ }
32
+ };
33
+ exports.tryResolveOptional = tryResolveOptional;
@@ -33,8 +33,8 @@ export type FoodShopConfigInput = {
33
33
  * Builds the plain `medusa-config.ts` input of a food shop: Medusa core
34
34
  * settings, the Redis event bus, the mail provider (set up in the Admin), S3 file storage, tax and
35
35
  * Stripe payment providers, and the Hartl Services plugins (the base plugin
36
- * with its E-Mail, Documents and file storage modules plus five feature
37
- * plugins). Deployment
36
+ * with its E-Mail, Documents, Steuer-Compliance and file storage modules plus
37
+ * four feature plugins). Deployment
38
38
  * values are read and validated from `environment`; a missing or invalid one
39
39
  * fails with its name.
40
40
  */
@@ -14,8 +14,8 @@ const options_1 = require("./options");
14
14
  * Builds the plain `medusa-config.ts` input of a food shop: Medusa core
15
15
  * settings, the Redis event bus, the mail provider (set up in the Admin), S3 file storage, tax and
16
16
  * Stripe payment providers, and the Hartl Services plugins (the base plugin
17
- * with its E-Mail, Documents and file storage modules plus five feature
18
- * plugins). Deployment
17
+ * with its E-Mail, Documents, Steuer-Compliance and file storage modules plus
18
+ * four feature plugins). Deployment
19
19
  * values are read and validated from `environment`; a missing or invalid one
20
20
  * fails with its name.
21
21
  */
@@ -130,7 +130,7 @@ function buildFoodShopConfig(options, environment = process.env) {
130
130
  options: {
131
131
  providers: [
132
132
  {
133
- resolve: "@hartl-services/medusa-tax-compliance/providers/tax-compliance",
133
+ resolve: "@hartl-services/medusa-base/providers/tax-compliance",
134
134
  },
135
135
  ],
136
136
  },
@@ -162,7 +162,8 @@ function buildFoodShopConfig(options, environment = process.env) {
162
162
  const plugins = [
163
163
  {
164
164
  // Always first: owns the plugin feature toggles the other plugins gate
165
- // on, and carries E-Mail, Documents and the /files gateway.
165
+ // on, and carries E-Mail, Documents, Steuer-Compliance and the /files
166
+ // gateway.
166
167
  resolve: "@hartl-services/medusa-base",
167
168
  options: {
168
169
  email: {
@@ -172,6 +173,12 @@ function buildFoodShopConfig(options, environment = process.env) {
172
173
  adminAffiliateApplicationsUrl: () => new URL("/app/affiliates/applications", backendOrigin).toString(),
173
174
  // The Admin dashboard mounts under admin.path ("/app").
174
175
  adminOrderUrl: ({ orderId }) => new URL(`/app/orders/${encodeURIComponent(orderId)}`, backendOrigin).toString(),
176
+ // The Admin dashboard reads the token from the query, not the hash.
177
+ adminPasswordResetUrl: ({ token }) => {
178
+ const url = new URL("/app/reset-password", backendOrigin);
179
+ url.searchParams.set("token", token);
180
+ return url.toString();
181
+ },
175
182
  displayName: options.displayName,
176
183
  affiliatePortalUrl: (0, config_1.shopUrl)(storefrontOrigin, `${storefrontPath}/partnerportal`),
177
184
  // The Admin dashboard mounts "/invite" under admin.path ("/app").
@@ -203,10 +210,6 @@ function buildFoodShopConfig(options, environment = process.env) {
203
210
  files: { gateway: s3CacheStorage.gateway },
204
211
  },
205
212
  },
206
- {
207
- resolve: "@hartl-services/medusa-tax-compliance",
208
- options: {},
209
- },
210
213
  {
211
214
  resolve: "@hartl-services/medusa-free-shipping",
212
215
  options: {},
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hartl-services/medusa-base",
3
- "version": "2.10.0",
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.",
3
+ "version": "3.0.0",
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, Steuer-Compliance (UID check, Tax provider) 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": [
7
7
  ".medusa/server",
@@ -92,6 +92,7 @@
92
92
  "@aws-sdk/client-s3": "^3.948.0",
93
93
  "@aws-sdk/lib-storage": "^3.954.0",
94
94
  "@floating-ui/dom": "1.7.4",
95
+ "soap": "1.10.0",
95
96
  "@tiptap/extension-link": "3.31.4",
96
97
  "@tiptap/pm": "3.31.4",
97
98
  "@tiptap/react": "3.31.4",
@@ -101,7 +102,7 @@
101
102
  "mime-types": "3.0.1",
102
103
  "nodemailer": "6.10.1",
103
104
  "ulid": "^2.4.0",
104
- "@hartl-services/medusa-food-supplements-contracts": "^0.30.0"
105
+ "@hartl-services/medusa-food-supplements-contracts": "^0.31.0"
105
106
  },
106
107
  "devDependencies": {
107
108
  "@medusajs/admin-sdk": "2.19.0",
@@ -153,7 +154,7 @@
153
154
  "dev": "medusa plugin:develop",
154
155
  "typecheck": "tsc --noEmit && tsc -p tsconfig.type-tests.json --noEmit && tsc -p tsconfig.component-tests.json",
155
156
  "pretest:unit": "pnpm --filter @hartl-services/medusa-food-supplements-contracts build",
156
- "test:unit": "jest",
157
+ "test:unit": "sh ../../scripts/dev-capped.sh jest",
157
158
  "pretest:contract": "pnpm --filter @hartl-services/medusa-food-supplements-contracts build",
158
159
  "test:contract": "jest --config jest.contract.config.js --runInBand",
159
160
  "test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js --silent=false --runInBand --forceExit"