@hartl-services/medusa-base 2.5.0 → 2.6.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/admin-components/features/plugin-features/components/ImageSettingInput.js +48 -0
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginActionsSection.js +3 -2
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +17 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginPageShell.js +20 -0
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginSettingsForm.js +16 -3
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +5 -1
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +20 -4
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginFeatures.js +1 -1
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +5 -1
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/action-runs.d.ts +1 -1
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/action-runs.js +3 -2
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +20 -4
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/plugin-features-admin-client.js +1 -1
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/settings-draft.d.ts +17 -2
- package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/settings-draft.js +33 -1
- package/{dist → .medusa/server/src/admin}/admin-components/i18n/texts.d.ts +3 -0
- package/{dist → .medusa/server/src/admin}/admin-components/i18n/texts.js +3 -0
- package/.medusa/server/src/admin/admin-components/index.d.ts +36 -0
- package/.medusa/server/src/admin/admin-components/index.js +37 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/date-input.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/date-input.js +43 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/errors.d.ts +9 -0
- package/{dist/admin-components → .medusa/server/src/admin/admin-components/shared}/lib/errors.js +4 -6
- package/.medusa/server/src/admin/admin-components/shared/lib/file-validation.d.ts +24 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/file-validation.js +18 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/format.d.ts +32 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/format.js +77 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/pdf-preview.d.ts +16 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/pdf-preview.js +31 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/pdf.d.ts +6 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/pdf.js +13 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/use-debounced-value.d.ts +2 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/use-debounced-value.js +10 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/use-pdf-preview.d.ts +24 -0
- package/.medusa/server/src/admin/admin-components/shared/lib/use-pdf-preview.js +47 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminDatePicker.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/AdminDatePicker.js +9 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/BackLink.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/BackLink.js +5 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/DateRangeFilter.d.ts +20 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/DateRangeFilter.js +17 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FilePickerButton.d.ts +14 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/FilePickerButton.js +14 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/MappedStatusBadge.d.ts +17 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/MappedStatusBadge.js +12 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/OffsetTablePagination.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/OffsetTablePagination.js +19 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PdfPreviewModal.d.ts +20 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PdfPreviewModal.js +7 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PluginFeatureRoute.d.ts +19 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/PluginFeatureRoute.js +16 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/QueryState.d.ts +24 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/QueryState.js +23 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SearchableReferenceField.d.ts +63 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SearchableReferenceField.js +84 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SectionHeader.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/SectionHeader.js +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/mapped-status.d.ts +6 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/mapped-status.js +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/offset-pagination.d.ts +17 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/offset-pagination.js +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/reference-results-state.d.ts +16 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/reference-results-state.js +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/InsertMenu.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/InsertMenu.js +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/LinkPrompt.d.ts +14 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/LinkPrompt.js +26 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/RichTextEditor.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/RichTextEditor.js +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/RichTextToolbar.d.ts +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/RichTextToolbar.js +49 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/SlashMenu.d.ts +11 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/SlashMenu.js +44 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/build-extensions.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/build-extensions.js +43 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/drag-handle.d.ts +15 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/drag-handle.js +161 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/drag-target.d.ts +30 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/drag-target.js +47 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/editor-styles.d.ts +6 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/editor-styles.js +46 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/index.d.ts +9 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/index.js +6 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/link-href.d.ts +8 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/link-href.js +21 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/link-policy.d.ts +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/link-policy.js +20 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/slash-command.d.ts +13 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/slash-command.js +60 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/slash-items.d.ts +25 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/slash-items.js +10 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/tiptap.d.ts +7 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/tiptap.js +7 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/use-rich-text-editor.d.ts +44 -0
- package/.medusa/server/src/admin/admin-components/shared/ui/rich-text-editor/use-rich-text-editor.js +37 -0
- package/.medusa/server/src/admin/index.js +4513 -1447
- package/.medusa/server/src/admin/index.mjs +4515 -1452
- package/.medusa/server/src/api/admin/email/attachments/[id]/mail-kinds/route.js +16 -0
- package/.medusa/server/src/api/admin/email/attachments/[id]/route.js +15 -0
- package/.medusa/server/src/api/admin/email/attachments/[id]/versions/[version_id]/download/route.js +16 -0
- package/.medusa/server/src/api/admin/email/attachments/[id]/versions/route.js +41 -0
- package/.medusa/server/src/api/admin/email/attachments/route.js +21 -0
- package/.medusa/server/src/api/admin/email/templates/[kind]/preview/route.js +31 -0
- package/.medusa/server/src/api/admin/email/templates/[kind]/route.js +28 -0
- package/.medusa/server/src/api/admin/email/templates/[kind]/send-test/route.js +179 -0
- package/.medusa/server/src/api/admin/email/templates/[kind]/test-sources/route.js +19 -0
- package/.medusa/server/src/api/admin/email/templates/route.js +15 -0
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/route.js +2 -2
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/runs/route.js +2 -2
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/route.js +2 -2
- package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/settings/route.js +2 -2
- package/.medusa/server/src/api/admin/plugin-features/route.js +2 -2
- package/.medusa/server/src/api/attachment-download-response.js +12 -0
- package/.medusa/server/src/api/email-template-response.js +43 -0
- package/.medusa/server/src/api/middlewares.js +75 -17
- package/.medusa/server/src/api/plugin-actions.js +6 -5
- package/.medusa/server/src/api/plugin-features-http.js +4 -9
- package/.medusa/server/src/api/store/carts/[id]/completion-check/route.js +2 -2
- package/.medusa/server/src/api/store/plugin-features/[plugin_key]/route.js +2 -2
- package/.medusa/server/src/api/store/plugin-features/route.js +2 -2
- package/.medusa/server/src/documents/plugin-features.js +1 -7
- package/.medusa/server/src/documents/templates/financial-document.js +12 -11
- package/.medusa/server/src/documents/templates/html-factory.js +1 -1
- package/.medusa/server/src/documents/templates/html-utils.js +4 -10
- package/.medusa/server/src/documents/templates/layout.js +30 -11
- package/.medusa/server/src/documents/templates/packing-list.js +8 -7
- package/.medusa/server/src/documents/utils/document-render-settings.js +9 -6
- package/.medusa/server/src/email/application/handle-customer-verification-event.js +8 -3
- package/.medusa/server/src/email/application/handle-invite-event.js +8 -3
- package/.medusa/server/src/email/application/handle-password-reset-event.js +8 -3
- package/.medusa/server/src/email/application/notification-attachments.js +86 -0
- package/.medusa/server/src/email/application/template-data-from-order.js +339 -0
- package/.medusa/server/src/email/config/index.js +5 -29
- package/.medusa/server/src/email/domain/business-keys.js +5 -5
- package/.medusa/server/src/email/domain/documents-fact-fingerprint.js +3 -3
- package/.medusa/server/src/email/domain/order-summary.js +21 -27
- package/.medusa/server/src/email/domain/refund-summary.js +7 -12
- package/.medusa/server/src/email/domain/return-summary.js +32 -38
- package/.medusa/server/src/email/domain/shipment-summary.js +22 -28
- package/.medusa/server/src/email/plugin-features.js +2 -10
- package/.medusa/server/src/email/rendering/calendar-dates.js +19 -0
- package/.medusa/server/src/email/rendering/default-templates.js +99 -682
- package/.medusa/server/src/email/rendering/email-html.js +189 -0
- package/.medusa/server/src/email/rendering/load-email-shop-details.js +14 -12
- package/.medusa/server/src/email/rendering/render-email.js +46 -13
- package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +3 -14
- package/.medusa/server/src/email/templates/blocks/dynamic-blocks.js +427 -0
- package/.medusa/server/src/email/templates/blocks/placeholders.js +71 -0
- package/.medusa/server/src/email/templates/blocks/render-document.js +137 -0
- package/.medusa/server/src/email/templates/code-override.js +18 -0
- package/.medusa/server/src/email/templates/defaults/documents.js +129 -0
- package/.medusa/server/src/email/templates/defaults/subjects.js +62 -0
- package/.medusa/server/src/email/templates/defaults/texts.js +42 -0
- package/.medusa/server/src/email/templates/index.js +22 -0
- package/.medusa/server/src/email/templates/load-template.js +39 -0
- package/.medusa/server/src/email/templates/preview.js +33 -0
- package/.medusa/server/src/email/templates/render.js +70 -0
- package/.medusa/server/src/email/templates/sample-data.js +165 -0
- package/.medusa/server/src/email/templates/types.js +3 -0
- package/.medusa/server/src/email/templates/validate.js +113 -0
- package/.medusa/server/src/files/config/index.js +6 -9
- package/.medusa/server/src/migration-scripts/move-logo-to-shop-appearance.js +53 -0
- package/.medusa/server/src/modules/documents/domain/cancellation-snapshot.js +4 -3
- package/.medusa/server/src/modules/documents/domain/merchant.js +4 -3
- package/.medusa/server/src/modules/documents/domain/options.js +3 -5
- package/.medusa/server/src/modules/documents/domain/tax-breakdown.js +4 -7
- package/.medusa/server/src/modules/documents/service.js +12 -33
- package/.medusa/server/src/modules/email/domain/attachment.js +22 -8
- package/.medusa/server/src/modules/email/migrations/Migration20261009083539.js +80 -0
- package/.medusa/server/src/modules/email/migrations/Migration20261009100654.js +17 -0
- package/.medusa/server/src/modules/email/models/email-attachment-document-version.js +39 -0
- package/.medusa/server/src/modules/email/models/email-attachment-document.js +27 -0
- package/.medusa/server/src/modules/email/models/email-template.js +25 -0
- package/.medusa/server/src/modules/email/service.js +370 -93
- package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +9 -11
- package/.medusa/server/src/modules/plugin-features/service.js +2 -1
- package/.medusa/server/src/providers/s3-cache/cache/cache-manager.js +3 -3
- package/.medusa/server/src/providers/s3-cache/s3-object-store.js +3 -9
- package/.medusa/server/src/providers/smtp/service.js +13 -13
- package/.medusa/server/src/public/descriptor.js +16 -18
- package/.medusa/server/src/public/enforcement.js +29 -1
- package/.medusa/server/src/public/index.js +8 -2
- package/.medusa/server/src/public/module-access.js +9 -2
- package/.medusa/server/src/public/shop-master-data.js +109 -18
- package/.medusa/server/src/shared/lib/coerce.js +26 -0
- package/.medusa/server/src/shared/lib/collections.js +19 -0
- package/.medusa/server/src/shared/lib/dates.js +43 -0
- package/.medusa/server/src/shared/lib/errors.js +11 -0
- package/.medusa/server/src/shared/lib/hash.js +8 -0
- package/.medusa/server/src/shared/lib/index.js +29 -0
- package/.medusa/server/src/shared/lib/logging.js +61 -0
- package/.medusa/server/src/shared/lib/money.js +47 -0
- package/.medusa/server/src/shared/lib/text.js +53 -0
- package/.medusa/server/src/shared/lib/transaction.js +58 -0
- package/.medusa/server/src/{api → shared/lib}/wire-response.js +1 -1
- package/.medusa/server/src/shop-config/options.js +3 -5
- package/.medusa/server/src/subscribers/packing-list-fulfillment-canceled.js +4 -6
- package/.medusa/server/src/workflows/documents/issue-invoice-after-shipment.js +10 -12
- package/.medusa/server/src/workflows/documents/issue-packing-list.js +5 -6
- package/.medusa/server/src/workflows/documents/reconcile-order-cancellation.js +6 -8
- package/.medusa/server/src/workflows/email/dispatch-email-message.js +11 -41
- package/.medusa/server/src/workflows/email/prepare-order-received-email.js +2 -2
- package/.medusa/server/src/workflows/hooks/complete-cart-participants.js +4 -8
- package/README.md +427 -54
- package/dist/documents/templates/financial-document.js +11 -10
- package/dist/documents/templates/html-factory.d.ts +1 -1
- package/dist/documents/templates/html-factory.js +1 -1
- package/dist/documents/templates/html-utils.d.ts +0 -1
- package/dist/documents/templates/html-utils.js +3 -9
- package/dist/documents/templates/layout.js +29 -10
- package/dist/documents/templates/packing-list.js +7 -6
- package/dist/documents/types/documents.d.ts +7 -1
- package/dist/email/config/index.js +4 -28
- package/dist/email/types/shop-configuration.d.ts +6 -5
- package/dist/files/config/index.js +5 -8
- package/dist/modules/documents/domain/options.js +2 -4
- package/dist/public/descriptor.js +15 -17
- package/dist/public/enforcement.d.ts +21 -1
- package/dist/public/enforcement.js +28 -0
- package/dist/public/index.d.ts +3 -2
- package/dist/public/index.js +7 -1
- package/dist/public/module-access.d.ts +8 -0
- package/dist/public/module-access.js +8 -1
- package/dist/public/shop-master-data.d.ts +22 -5
- package/dist/public/shop-master-data.js +108 -17
- package/dist/public/types.d.ts +10 -2
- package/dist/shared/lib/coerce.d.ts +19 -0
- package/dist/shared/lib/coerce.js +25 -0
- package/dist/shared/lib/collections.d.ts +3 -0
- package/dist/shared/lib/collections.js +18 -0
- package/dist/shared/lib/dates.d.ts +12 -0
- package/dist/shared/lib/dates.js +42 -0
- package/dist/shared/lib/errors.d.ts +2 -0
- package/dist/shared/lib/errors.js +10 -0
- package/dist/shared/lib/hash.d.ts +2 -0
- package/dist/shared/lib/hash.js +7 -0
- package/dist/shared/lib/index.d.ts +10 -0
- package/dist/shared/lib/index.js +28 -0
- package/dist/shared/lib/logging.d.ts +26 -0
- package/dist/shared/lib/logging.js +60 -0
- package/dist/shared/lib/money.d.ts +13 -0
- package/dist/shared/lib/money.js +46 -0
- package/dist/shared/lib/text.d.ts +19 -0
- package/dist/shared/lib/text.js +52 -0
- package/dist/shared/lib/transaction.d.ts +26 -0
- package/dist/shared/lib/transaction.js +57 -0
- package/dist/shared/lib/wire-response.d.ts +6 -0
- package/dist/shared/lib/wire-response.js +9 -0
- package/dist/shop-config/options.js +2 -4
- package/package.json +19 -4
- package/.medusa/server/src/api/admin/email/terms-versions/[id]/download/route.js +0 -16
- package/.medusa/server/src/api/admin/email/terms-versions/route.js +0 -47
- package/.medusa/server/src/api/terms-download-response.js +0 -12
- package/.medusa/server/src/modules/email/models/email-terms-version.js +0 -37
- package/dist/admin-components/features/plugin-features/components/ImageSettingInput.js +0 -42
- package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +0 -16
- package/dist/admin-components/features/plugin-features/components/PluginPageShell.js +0 -20
- package/dist/admin-components/features/plugin-features/lib/image-upload.d.ts +0 -6
- package/dist/admin-components/features/plugin-features/lib/image-upload.js +0 -17
- package/dist/admin-components/index.d.ts +0 -14
- package/dist/admin-components/index.js +0 -14
- package/dist/admin-components/lib/errors.d.ts +0 -6
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/ImageSettingInput.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginActionsSection.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginDetailPage.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginDetailPage.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeatureGate.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeatureGate.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeatureSections.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeatureSections.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeaturesCard.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeaturesCard.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginHubCard.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginHubCard.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginPageShell.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginSettingsForm.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginStatusChips.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/components/PluginStatusChips.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/hooks/usePluginSettingsForm.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/plugin-paths.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/lib/plugin-paths.js +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/queries/pluginFeatureKeys.d.ts +0 -0
- /package/{dist → .medusa/server/src/admin}/admin-components/features/plugin-features/queries/pluginFeatureKeys.js +0 -0
- /package/{dist/admin-components → .medusa/server/src/admin/admin-components/shared}/lib/sdk.d.ts +0 -0
- /package/{dist/admin-components → .medusa/server/src/admin/admin-components/shared}/lib/sdk.js +0 -0
package/README.md
CHANGED
|
@@ -31,7 +31,8 @@ packing lists) and S3 file storage, and the turnkey `medusa-config.ts` preset
|
|
|
31
31
|
- Holds the shop's master data (Firmenangaben) as its own settings and
|
|
32
32
|
exports `getShopMasterData` (see "Shop-Stammdaten").
|
|
33
33
|
- Exports Admin components from `@hartl-services/medusa-base/admin-components`
|
|
34
|
-
|
|
34
|
+
(also `sdk`, `getErrorMessage` and the rich-text editor) and server helpers
|
|
35
|
+
from `@hartl-services/medusa-base/lib` (`toWireResponse`) so a plugin composes the base's sections into its own page and hides
|
|
35
36
|
widgets of disabled features (see "Admin components for plugin pages").
|
|
36
37
|
- Owns the `completeCartWorkflow` hooks `validate` and `orderCreated` and runs
|
|
37
38
|
the workflows that plugins declare for them (see "Complete-cart hook
|
|
@@ -112,7 +113,7 @@ exports from the matching `@hartl-services/medusa-base` subpath. The
|
|
|
112
113
|
e-mail module follows the Documents `invoices` toggle.
|
|
113
114
|
|
|
114
115
|
Peer dependencies are the host's Medusa 2.19 packages (`@medusajs/framework`,
|
|
115
|
-
`@medusajs/medusa`, `@medusajs/admin-sdk`, `@medusajs/js-sdk`, `@medusajs/ui`)
|
|
116
|
+
`@medusajs/medusa`, `@medusajs/admin-sdk`, `@medusajs/js-sdk`, `@medusajs/ui`, `@medusajs/icons`)
|
|
116
117
|
plus React, React Router and TanStack Query in the versions the Medusa 2.19
|
|
117
118
|
dashboard uses.
|
|
118
119
|
|
|
@@ -216,6 +217,9 @@ export default defineMiddlewares({
|
|
|
216
217
|
})
|
|
217
218
|
```
|
|
218
219
|
|
|
220
|
+
`pluginFeatureGate(demoPluginFeatures)` returns the same entries as a short
|
|
221
|
+
`gate("/store/demo/coupons", "coupons")`.
|
|
222
|
+
|
|
219
223
|
A disabled plugin or feature answers 404. With several keys, all must be
|
|
220
224
|
enabled. The toggles are read once per request.
|
|
221
225
|
|
|
@@ -329,7 +333,11 @@ class DemoModuleService extends MedusaService({ /* models */ }) {
|
|
|
329
333
|
non-empty, unique values; the stored value must be one of them), `image`
|
|
330
334
|
(the http(s) URL of a PNG/JPEG of at most 2 MiB that the Admin uploads
|
|
331
335
|
through Medusa's `/admin/uploads` into the public File Module storage and
|
|
332
|
-
previews; replacing or removing it leaves the old file in storage)
|
|
336
|
+
previews; replacing or removing it leaves the old file in storage), `color`
|
|
337
|
+
(a hex color `#rrggbb`, stored lowercase; the Admin shows a hex field with a
|
|
338
|
+
color picker and checks the format before saving). An optional `group`
|
|
339
|
+
(non-empty text) is a section heading: the Admin starts a new section with
|
|
340
|
+
that heading whenever the group changes from one setting to the next. Keys
|
|
333
341
|
follow the feature key format and are unique. A `secret` has no default;
|
|
334
342
|
any other default must match its type, options and bounds. `options` exist
|
|
335
343
|
only on `select`, `min`/`max` only on `number`. `required` defaults to
|
|
@@ -488,6 +496,22 @@ settings like any plugin's:
|
|
|
488
496
|
| `iban`, `bic` | string | no |
|
|
489
497
|
| `company_register_number` (Firmenbuchnummer), `company_register_court` (Firmenbuchgericht) | string | no |
|
|
490
498
|
|
|
499
|
+
These company fields form the section "Firmendaten". The section
|
|
500
|
+
"Erscheinungsbild" below them holds the look of the default e-mail and
|
|
501
|
+
document layouts; all of it is optional:
|
|
502
|
+
|
|
503
|
+
| Key | Type | Used by the default e-mail layout | Used by the default document layout |
|
|
504
|
+
|---|---|---|---|
|
|
505
|
+
| `logo` | image | on top of every mail (else the `displayName`) | top left (else the legal name) |
|
|
506
|
+
| `color_accent` (Akzentfarbe) | color | buttons, heading, logo fallback text, tracking links | `--accent` |
|
|
507
|
+
| `color_text` (Textfarbe) | color | body text, values, item titles, totals | `--text` |
|
|
508
|
+
| `color_muted` (Nebentextfarbe) | color | labels, links, variants, footer | `--muted` |
|
|
509
|
+
| `color_line` (Linienfarbe) | color | borders and dividers | `--line` |
|
|
510
|
+
| `color_surface` (Flächenfarbe) | color | page background, info box | `--table-head` |
|
|
511
|
+
|
|
512
|
+
An empty color keeps the default of that output, so without any value mails
|
|
513
|
+
and documents look as before. Button text and the mail card stay white.
|
|
514
|
+
|
|
491
515
|
Server-side code reads them exactly as stored in the Admin; there is no
|
|
492
516
|
medusa-config fallback:
|
|
493
517
|
|
|
@@ -503,9 +527,24 @@ if (!configured) {
|
|
|
503
527
|
}
|
|
504
528
|
```
|
|
505
529
|
|
|
530
|
+
The appearance is read separately and holds only what is set:
|
|
531
|
+
|
|
532
|
+
```ts
|
|
533
|
+
import { getShopAppearance } from "@hartl-services/medusa-base"
|
|
534
|
+
|
|
535
|
+
const { logo, colors } = await getShopAppearance(container)
|
|
536
|
+
// colors: { accent?, text?, muted?, line?, surface? } as lowercase #rrggbb
|
|
537
|
+
```
|
|
538
|
+
|
|
506
539
|
The base only checks presence and type; what counts as a usable value
|
|
507
540
|
(for example a placeholder UID) is the consuming plugin's rule.
|
|
508
541
|
|
|
542
|
+
The migration script `move-logo-to-shop-appearance` (run once by
|
|
543
|
+
`medusa db:migrate`) moved the former `logo` settings of the E-Mail and the
|
|
544
|
+
Documents plugin into the appearance: the Documents logo, else the E-Mail
|
|
545
|
+
logo; a `logo` stored in the Shop-Stammdaten by an earlier release is kept
|
|
546
|
+
only when neither plugin had one.
|
|
547
|
+
|
|
509
548
|
## Admin pages
|
|
510
549
|
|
|
511
550
|
- `/settings/hartl-services` (sidebar entry "Hartl Services Plugins") is the
|
|
@@ -542,6 +581,28 @@ build, with types) exports:
|
|
|
542
581
|
| `usePluginFeatureEnabled(pluginKey, ...featureKeys)` | `{ enabled, isPending, isError }` from the shared list query (30 s stale time); plugin switch and every key must be effective; `enabled` is `false` while loading and on error |
|
|
543
582
|
| `PluginFeatureGate({ pluginKey, featureKeys?, fallback? })` | Renders `children` only while enabled, otherwise `fallback` (default nothing) |
|
|
544
583
|
| `PluginFeatureDisabledNotice({ pluginKey, featureLabel? })` | "Diese Funktion ist unter Einstellungen → Hartl Services Plugins ausgeschaltet." with a link to the hub |
|
|
584
|
+
| `sdk` | The Admin's configured Medusa JS SDK client (`sdk.client.fetch(path, { query })`); use it instead of a per-plugin copy |
|
|
585
|
+
| `getErrorMessage(error, fallback?)` | Readable message from an unknown error (SDK `response.data.message`, `body.message`, `Error.message`), else `fallback` |
|
|
586
|
+
| `ADMIN_LOCALE` (`de-AT`), `ADMIN_DASH`, `formatDate(value, { timeZone? })`, `formatDateTime(value, { timeZone? })`, `formatAmount(amount, currencyCode)`, `getTodayInputDate({ utc? })` | The one Admin locale and formatters; `"-"` for empty or invalid values; pass `{ timeZone: "UTC" }` for date-only values stored at UTC midnight |
|
|
587
|
+
| `useDebouncedValue(value, delayMs)` | Debounced copy of a value |
|
|
588
|
+
| `fetchPdfObjectUrl(path)` | Loads a PDF through `sdk` and returns an object URL; the caller revokes it |
|
|
589
|
+
| `usePdfPreview()` | Returns `{ isOpen, url, isLoading, error, open(load, errorMessage), close() }` for a `PdfPreviewModal`; `load` returns an object URL (e.g. `() => fetchPdfObjectUrl(path)`). Drops stale responses and revokes the URL on close, replacement and unmount |
|
|
590
|
+
| `dateFromInputValue(value)`, `inputValueFromDate(date)` | `"yyyy-mm-dd"` calendar-date string state <-> local `Date` for `DatePicker` (which reads and emits local dates); `null` / `""` for empty or invalid |
|
|
591
|
+
| `validateFile(file, { maxBytes, types, extensions?, messages })` | Pure check of a picked file: `messages.wrongType` / `empty` / `tooLarge` (German text of the caller) or `null`. With `extensions` the name must end with one and an empty MIME type is tolerated |
|
|
592
|
+
| `dateTimeFromInputValue(value)`, `inputValueFromDateTime(date)` | Same for `"yyyy-mm-ddThh:mm"` with `DatePicker granularity="minute"` |
|
|
593
|
+
| `SectionHeader({ title, description?, actions?, level? })` | Heading, subtle description and actions at the top of a `Container className="divide-y p-0"` section |
|
|
594
|
+
| `QueryState({ isLoading, error?, isError?, isEmpty?, loadingText?, errorText?, emptyText?, children? })` | Loading, error and empty body (`px-6 py-8`), otherwise `children`; `errorText` may be a function of the error message |
|
|
595
|
+
| `BackLink({ to, label })` | Arrow icon (`ArrowLongLeft`) + label link above a page |
|
|
596
|
+
| `PluginFeatureRoute({ pluginKey, featureKey?, featureLabel?, hideOnError?, children })` | Route body: nothing while pending, `children` when enabled, otherwise `PluginFeatureDisabledNotice` |
|
|
597
|
+
| `SearchableReferenceField<T>(props)`, type `SearchableReferenceFieldProps` | Search input with a debounced overlay result list (opens on focus/typing, closes on select, Escape or outside click), optional selected card with optional clear button; the caller runs its query on `onDebouncedQueryChange` |
|
|
598
|
+
| `PdfPreviewModal({ open, onOpenChange, title, url, isLoading?, error? })` | `FocusModal` with an iframe for a PDF object URL |
|
|
599
|
+
| `AdminDatePicker(props)` | Medusa `DatePicker` pinned to `ADMIN_LOCALE` (de-AT) via `I18nProvider`; the dashboard language would otherwise show "MM/DD/YYYY". Use it instead of `DatePicker` (importing that from `@medusajs/ui` is a lint error) |
|
|
600
|
+
| `DateRangeFilter({ from, to, onChange, fromLabel?, toLabel? })` | "Von" / "Bis" `AdminDatePicker` pair on `yyyy-mm-dd` strings; `onChange({ from, to })`. Renders the two fields as a fragment, the caller sets the layout. No from > to check (caller's job); an external reset needs a `key` |
|
|
601
|
+
| `FilePickerButton({ accept, label, disabled?, isLoading?, id?, onFileSelected })` | Medusa `Button` that opens the file dialog of a hidden `<input type="file">`; calls `onFileSelected(file)` and resets the input |
|
|
602
|
+
| `OffsetTablePagination({ count, offset, limit, onOffsetChange, maxOffset? })` | German `Table.Pagination` footer for an offset/limit list ("1 - 20 von 45 Ergebnisse", "Zurück", "Weiter") |
|
|
603
|
+
| `MappedStatusBadge({ value, map, fallback? })` | `StatusBadge` from a `value → { label, color }` map; empty value renders `ADMIN_DASH` |
|
|
604
|
+
| `useRichTextEditor(config, initialContent, deps)`, `RichTextEditor`, `InsertMenu`, `filterSlashItems`, `normalizeLinkHref`, `isDefaultAllowedHref`, types `RichTextEditorConfig`, `SlashItem`, `SlashContext`, `NestedContainer` | Generic TipTap editor, see "Rich-text editor" |
|
|
605
|
+
| `Node`, `Mark`, `Extension`, `mergeAttributes`, `ReactNodeViewRenderer`, `NodeViewWrapper`, `NodeViewContent`, `useEditorState`, `Plugin`, `PluginKey`, `NodeSelection`, `TextSelection`, types `AnyExtension`, `ChainedCommands`, `Editor`, `JSONContent`, `NodeViewProps`, `Range` | Re-exported TipTap and ProseMirror building blocks for editor extensions; a plugin needs no own `@tiptap/*` dependency |
|
|
545
606
|
|
|
546
607
|
```tsx
|
|
547
608
|
// src/admin/routes/settings/hartl-services/demo/page.tsx
|
|
@@ -587,6 +648,151 @@ The consuming plugin lists `@hartl-services/medusa-base` in its
|
|
|
587
648
|
external and the shop's Admin resolves one shared copy. The components use
|
|
588
649
|
the host Admin's React, React Query, React Router and `@medusajs/ui`.
|
|
589
650
|
|
|
651
|
+
#### Rich-text editor
|
|
652
|
+
|
|
653
|
+
`useRichTextEditor(config, initialContent, deps)` returns the TipTap
|
|
654
|
+
`Editor | null` (`null` until it exists), `<RichTextEditor editor
|
|
655
|
+
linkInvalidMessage? className? styles? toolbarExtra? />` renders toolbar and
|
|
656
|
+
content. `config` (`RichTextEditorConfig`, all optional):
|
|
657
|
+
|
|
658
|
+
| Key | Meaning |
|
|
659
|
+
| --- | --- |
|
|
660
|
+
| `starterKit` | `Partial<StarterKitOptions>`; disable what the document may not contain (the starter kit's own link is always off) |
|
|
661
|
+
| `link` | `false` leaves the link mark and its toolbar button out; `{ isAllowedHref }` sets the link policy; omitted: http(s) and mailto (`isDefaultAllowedHref`). The policy is stored on the editor, so the Link mark, the toolbar and the link prompt always use the same function |
|
|
662
|
+
| `extensions` | The owner's nodes and marks, added after the starter kit and link |
|
|
663
|
+
| `slashItems({ query, editor })` | Returns the entries of the "/" menu (`SlashItem[]`, already filtered by `query`); the menu exists only with it |
|
|
664
|
+
| `dragHandle` | `true` for a grip left of each block, or `{ nestedContainers: [{ nodeName, contentSelector }] }` to give children of a container their own grip |
|
|
665
|
+
| `ariaLabel` | Accessible name of the writing area |
|
|
666
|
+
| `editorProps` | ProseMirror props; `attributes` must be an object, it is merged over the base's `role` and `aria-label` |
|
|
667
|
+
|
|
668
|
+
`SlashItem<T>` is `{ id, label, hint?, data: T, run(editor, range) }`;
|
|
669
|
+
`filterSlashItems(items, query)` keeps the entries whose label contains the
|
|
670
|
+
query. `normalizeLinkHref(input, isAllowed)` turns a typed target into an
|
|
671
|
+
allowed href (`mailto:` for a bare address, `https://` for a bare host) or
|
|
672
|
+
`null`. `InsertMenu({ label, options, labels, onSelect })` is a toolbar
|
|
673
|
+
dropdown for `toolbarExtra`. The e-mail template editor
|
|
674
|
+
(`features/email/template-editor/use-template-editor.ts`) is the reference
|
|
675
|
+
extension.
|
|
676
|
+
|
|
677
|
+
```tsx
|
|
678
|
+
import {
|
|
679
|
+
Node,
|
|
680
|
+
RichTextEditor,
|
|
681
|
+
filterSlashItems,
|
|
682
|
+
mergeAttributes,
|
|
683
|
+
useRichTextEditor,
|
|
684
|
+
type JSONContent,
|
|
685
|
+
type RichTextEditorConfig,
|
|
686
|
+
type SlashItem,
|
|
687
|
+
} from "@hartl-services/medusa-base/admin-components"
|
|
688
|
+
import { Button } from "@medusajs/ui"
|
|
689
|
+
|
|
690
|
+
const Callout = Node.create({
|
|
691
|
+
name: "callout",
|
|
692
|
+
group: "block",
|
|
693
|
+
content: "inline*",
|
|
694
|
+
parseHTML: () => [{ tag: "div[data-callout]" }],
|
|
695
|
+
renderHTML: ({ HTMLAttributes }) => [
|
|
696
|
+
"div",
|
|
697
|
+
mergeAttributes(HTMLAttributes, { "data-callout": "" }),
|
|
698
|
+
0,
|
|
699
|
+
],
|
|
700
|
+
})
|
|
701
|
+
|
|
702
|
+
const calloutItems: SlashItem[] = [
|
|
703
|
+
{
|
|
704
|
+
id: "callout",
|
|
705
|
+
label: "Hinweisbox",
|
|
706
|
+
data: null,
|
|
707
|
+
run: (editor, range) =>
|
|
708
|
+
editor.chain().focus().deleteRange(range).setNode("callout").run(),
|
|
709
|
+
},
|
|
710
|
+
]
|
|
711
|
+
|
|
712
|
+
const config = {
|
|
713
|
+
extensions: [Callout],
|
|
714
|
+
slashItems: ({ query }) => filterSlashItems(calloutItems, query),
|
|
715
|
+
ariaLabel: "Text",
|
|
716
|
+
} satisfies RichTextEditorConfig
|
|
717
|
+
|
|
718
|
+
export const NoteEditor = ({ initial }: { initial: JSONContent }) => {
|
|
719
|
+
const editor = useRichTextEditor(config, initial, [])
|
|
720
|
+
if (!editor) return null
|
|
721
|
+
return (
|
|
722
|
+
<RichTextEditor
|
|
723
|
+
editor={editor}
|
|
724
|
+
toolbarExtra={
|
|
725
|
+
<Button size="small" variant="secondary" onClick={() => editor.commands.setNode("callout")}>
|
|
726
|
+
Hinweisbox
|
|
727
|
+
</Button>
|
|
728
|
+
}
|
|
729
|
+
/>
|
|
730
|
+
)
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
Stability: the editor is created once and re-created only when `deps`
|
|
735
|
+
change (it then starts from the `config` and `initialContent` of that
|
|
736
|
+
render, so the cursor is lost). `starterKit`, `extensions`, which features are
|
|
737
|
+
on (`link`, `slashItems`, `dragHandle`), `ariaLabel` and `editorProps` are
|
|
738
|
+
read at creation; changing them has an effect only together with a change of
|
|
739
|
+
`deps` (for example the id of the loaded document). `slashItems` and the link
|
|
740
|
+
policy (`link.isAllowedHref`) are read on every use and always see the latest
|
|
741
|
+
render, so they need no stable reference. Pass `[]` for an editor that lives as
|
|
742
|
+
long as its component.
|
|
743
|
+
|
|
744
|
+
### Server helpers
|
|
745
|
+
|
|
746
|
+
`@hartl-services/medusa-base/lib` (server and isomorphic code; a separate
|
|
747
|
+
subpath because unit tests mock `@hartl-services/medusa-base` wholesale)
|
|
748
|
+
exports:
|
|
749
|
+
|
|
750
|
+
| Export | Purpose |
|
|
751
|
+
| --- | --- |
|
|
752
|
+
| `toWireResponse(schema, value)` | Serializes `value` as HTTP JSON does (`JSON.parse(JSON.stringify(value))`), then `schema.parse`s it with a Contracts Zod schema, which strips fields outside the public response contract; returns `z.infer<typeof schema>`. Use it for `res.json(...)` in custom routes |
|
|
753
|
+
| `toNumericAmount(value)` | Finite number from a number, numeric string, Medusa `BigNumber` (by shape, not `instanceof`), bignumber.js value or raw `{ value }`; `null` for anything else (blank, `NaN`, `Infinity`) |
|
|
754
|
+
| `getCurrencyDecimalPlaces(currencyCode)` | Minor-unit digits from Medusa's currency table (EUR 2, JPY 0, KWD 3); 2 for an unknown currency |
|
|
755
|
+
| `SqlManager` (type) | Raw SQL surface of a module's transaction manager: `execute(query, params?, method?)`, optional `flush()` |
|
|
756
|
+
| `requireTransactionManager(sharedContext, message?)` | `sharedContext.transactionManager`; throws `UNEXPECTED_STATE` without one (no fallback to `manager`) |
|
|
757
|
+
| `acquireAdvisoryXactLock(manager, key)` | `select pg_advisory_xact_lock(hashtext(?))` with a string key; serializes work per business key until commit |
|
|
758
|
+
| `isUniqueConstraintViolation(error)` | `true` for Postgres 23505 (also in `cause` / `driverError`) or the `INVALID_DATA` MedusaError "... with <field>: <value>, already exists." |
|
|
759
|
+
| `describeError(error)` | Message of an `Error` or error-like object, else `String(error)` |
|
|
760
|
+
| `resolveOptionalLogger(source)` | Logger with `warn` from a container (`resolve("logger")`) or a module cradle (`cradle.logger`), else `undefined`; never throws |
|
|
761
|
+
| `createWarnOnce()` | Returns `warnOnce(key, signature, warn)`: runs `warn` unless the last warning for `key` had the same `signature` (returns whether it ran); `warnOnce.reset(key?)` re-arms |
|
|
762
|
+
| `sha256Hex(value)` | Lower-case hex SHA-256 of a string (UTF-8) or bytes |
|
|
763
|
+
| `toValidDate(value, message?)` | `Date` from `Date` / string / number; throws `INVALID_DATA` for an invalid date |
|
|
764
|
+
| `startOfUtcDate(value)` / `toIsoDate(value)` | Midnight UTC of the UTC day / its `yyyy-mm-dd`; throw for an invalid date |
|
|
765
|
+
| `toWireDate(value)` / `toOptionalWireDate(value)` | ISO-8601 string for a response (throws for an invalid date) / `null` for `null` and `undefined` |
|
|
766
|
+
| `isValidTimeZone(value)` | `true` for a non-blank IANA time zone the runtime knows |
|
|
767
|
+
| `normalizeVatNumber(value)`, `VAT_NUMBER_PLACEHOLDER` | Whitespace removed and upper-cased; the development placeholder UID `ATU00000000` |
|
|
768
|
+
| `normalizeEmail(value)` | Trimmed and lower-cased; `null` for blank or malformed (no "@", leading or trailing "@") so the caller decides whether to throw |
|
|
769
|
+
| `escapeLikePattern(value)` | Escapes `\`, `%` and `_` for `LIKE` / `ILIKE` |
|
|
770
|
+
| `escapeHtml(value)` | Escapes `& < > " '`; accepts numbers, `null` and `undefined` (empty string) |
|
|
771
|
+
| `isHttpUrl(value)` / `isNonEmptyString(value)` | Absolute `http:` / `https:` URL; string with a non-whitespace character (both type guards) |
|
|
772
|
+
| `chunk(items, size)` / `sleep(ms)` | Slices of at most `size` (positive integer, else `INVALID_DATA`) / promise resolved after `ms` |
|
|
773
|
+
| `asRecord(value)` / `asRecordOrNull(value)` | Plain object (arrays excluded), else `{}` / `null` |
|
|
774
|
+
| `asText(value)` | Trimmed string, `null` for blank or non-string |
|
|
775
|
+
| `asArray(value)` | The array, else `[]` |
|
|
776
|
+
| `asOptionalString(value, { allowBlank? })` | The string as is (not trimmed), `null` for non-strings and, unless `allowBlank`, blank strings |
|
|
777
|
+
| `asFiniteNumber(value)` | The number if finite, else `null` (no parsing) |
|
|
778
|
+
|
|
779
|
+
Admin code never imports from `/lib`; it uses `/admin-components`.
|
|
780
|
+
|
|
781
|
+
The main entry (`@hartl-services/medusa-base`) additionally exports, next to
|
|
782
|
+
`requirePluginFeature`:
|
|
783
|
+
|
|
784
|
+
| Export | Purpose |
|
|
785
|
+
| --- | --- |
|
|
786
|
+
| `pluginFeatureGate(descriptor)` | Returns `gate(matcher, ...featureKeys)`, a `defineMiddlewares` route entry (no `methods`, so a prefix match before authentication) whose middleware is `requirePluginFeature(descriptor, ...featureKeys)` |
|
|
787
|
+
| `isOwnPluginEvent(data, pluginKey)` | `true` when the event payload's `plugin_key` is `pluginKey`; never throws. For subscribers of `plugin-features.updated.v1` and `plugin-settings.updated.v1` |
|
|
788
|
+
| `isBasePluginRegistered(container)` / `resolveBaseModule(container)` | Whether the base module is registered (boot-time check) / its service, or `UNEXPECTED_STATE` |
|
|
789
|
+
|
|
790
|
+
`/admin-components` is built (after `medusa plugin:build`) into
|
|
791
|
+
`.medusa/server/src/admin/admin-components`, not into `dist`: the host Admin's
|
|
792
|
+
Tailwind scans only `.medusa/server/src/admin/**` of a plugin, so the classes of
|
|
793
|
+
the shared components are generated there. Do not move the outDir of
|
|
794
|
+
`tsconfig.admin-components.json`.
|
|
795
|
+
|
|
590
796
|
## Semantics
|
|
591
797
|
|
|
592
798
|
- No stored row: every value is its declared default, `version` is 0.
|
|
@@ -968,7 +1174,7 @@ feature is switched on again.
|
|
|
968
1174
|
|
|
969
1175
|
| Key | Label | Default | Gates | Keeps running when off |
|
|
970
1176
|
| --------------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------- |
|
|
971
|
-
| (plugin switch) | E-Mail | on | every route under `/admin/email/*` (mail log, resends,
|
|
1177
|
+
| (plugin switch) | E-Mail | on | every route under `/admin/email/*` (mail log, resends, attachments; 404); jobs `email-reconcile-attempts`, `email-reconcile-pending-messages`, `email-retry-messages`; every feature below | checkout and orders; already queued messages stay stored |
|
|
972
1178
|
| `order_mails` | Bestell-Mails | on | subscribers `order-placed`, `email-shipment-created`, `email-order-canceled`, `return-requested`, `return-received`, `documents-shipment-invoice-assignment-decided`, `documents-order-cancellation-ready`, `documents-refund-ready`; route `/admin/draft-orders/:id/order-confirmation` (404) and its draft-order widget | jobs, Admin routes, already created messages |
|
|
973
1179
|
| `account_mails` | Konto-Mails | on | subscribers `password-reset`, `user-invite`, `customer-verification` (the last one only with `customer_verification` on as well) | jobs, Admin routes, already created messages |
|
|
974
1180
|
| `customer_verification` | Kontobestätigung per E-Mail | off | Medusa's e-mail verification of customer logins (see "Kontobestätigung per E-Mail"), route `POST /store/customer-verification/resend` (404 while off), subscriber `customer-verification`; child of `account_mails` | checkout and orders; confirmed accounts stay confirmed, already created messages |
|
|
@@ -981,15 +1187,14 @@ meantime, such as a password-reset link, is not sent). A toggle read
|
|
|
981
1187
|
failure fails the subscriber with its fixed sentinel (the Event Bus retries
|
|
982
1188
|
it) or fails the job run.
|
|
983
1189
|
|
|
984
|
-
The plugin declares
|
|
985
|
-
|
|
986
|
-
mail. It is not a Shop-Stammdaten field; Documents has its own `logo`.
|
|
1190
|
+
The plugin declares no settings. Its logo and colors come from the
|
|
1191
|
+
Shop-Stammdaten (section "Erscheinungsbild").
|
|
987
1192
|
|
|
988
1193
|
Admin surfaces of a disabled feature are hidden. The E-Mail settings page
|
|
989
1194
|
keeps `PluginFeatureSections` visible (so the plugin can be switched back on)
|
|
990
|
-
and gates the
|
|
991
|
-
plugin switch, showing `PluginFeatureDisabledNotice`
|
|
992
|
-
is off.
|
|
1195
|
+
and gates the Anhänge card above it, the mail log section below it and the
|
|
1196
|
+
Anhänge sub-page on the plugin switch, showing `PluginFeatureDisabledNotice`
|
|
1197
|
+
in place of the mail log and the sub-page while it is off.
|
|
993
1198
|
|
|
994
1199
|
### Kontobestätigung per E-Mail
|
|
995
1200
|
|
|
@@ -1102,7 +1307,8 @@ Storefront contract (DTOs, schema and path from the Contracts package,
|
|
|
1102
1307
|
- Affiliate owns reminder eligibility and publishes reminder and application
|
|
1103
1308
|
facts.
|
|
1104
1309
|
- Email resolves recipients, renders content, attaches files, and owns delivery
|
|
1105
|
-
status plus the append-only
|
|
1310
|
+
status plus the attachment library (documents with append-only PDF
|
|
1311
|
+
versions).
|
|
1106
1312
|
- Public HTTP DTOs, schemas, and paths remain in
|
|
1107
1313
|
`@hartl-services/medusa-food-supplements-contracts`.
|
|
1108
1314
|
|
|
@@ -1262,13 +1468,25 @@ has at most 35 characters. Email runtime-validates every contract before use.
|
|
|
1262
1468
|
- Every placed Order creates independent customer and Shop intents. The customer
|
|
1263
1469
|
intent honors `no_notification`; the Shop intent always targets the static
|
|
1264
1470
|
role mailbox selected by the Shop configuration.
|
|
1265
|
-
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1471
|
+
- Library attachments (see "Mail attachments") can be assigned to the customer
|
|
1472
|
+
kinds `order.received`, `order.shipped`, `order.canceled`,
|
|
1473
|
+
`order.return_requested`, `order.return_received` and `order.refunded`
|
|
1474
|
+
(`EMAIL_ATTACHABLE_KINDS`). When a message of such a kind is first created,
|
|
1475
|
+
it snapshots, for every document assigned to its kind, the newest version
|
|
1476
|
+
whose `effective_at` is not later than the reference time: the
|
|
1477
|
+
authoritative `order.created_at` for `order.received`, the creation time of
|
|
1478
|
+
the message otherwise. `order.return_received` is created together with the
|
|
1479
|
+
return request and so freezes the state of that moment. A document without
|
|
1480
|
+
an effective version is skipped. Shop, account and affiliate mails never
|
|
1481
|
+
receive library attachments.
|
|
1482
|
+
- A message lists Documents artifacts (invoice, cancellation) first, then its
|
|
1483
|
+
library attachments by document name, whichever correlated fact created it.
|
|
1484
|
+
- Attachment versions and their private files are immutable. Event replays,
|
|
1485
|
+
transport retries, and explicit Admin resends reuse the original message
|
|
1486
|
+
snapshot, so a later or backdated upload or a changed assignment never
|
|
1487
|
+
changes an existing message. A missing or altered library file fails the
|
|
1488
|
+
message terminally (`attachment_unavailable`/`attachment_invalid`); it is
|
|
1489
|
+
never sent without it.
|
|
1272
1490
|
- Event payloads are runtime-validated before use and may be replayed, delayed,
|
|
1273
1491
|
or delivered out of order.
|
|
1274
1492
|
- With the Documents `invoices` feature on, shipment and
|
|
@@ -1285,29 +1503,32 @@ has at most 35 characters. Email runtime-validates every contract before use.
|
|
|
1285
1503
|
- Password-reset and account-confirmation messages cannot be retried by the
|
|
1286
1504
|
generic retry job or resent by an Admin.
|
|
1287
1505
|
- Unknown transport outcomes are never automatically resent.
|
|
1288
|
-
- Shop branding is the configured `displayName` plus the
|
|
1289
|
-
the
|
|
1290
|
-
single renderers in its own configuration, not in the
|
|
1506
|
+
- Shop branding is the configured `displayName` plus the company details and
|
|
1507
|
+
the Erscheinungsbild (logo, colors) of the Shop-Stammdaten; a shop overrides
|
|
1508
|
+
the default layout or single renderers in its own configuration, not in the
|
|
1509
|
+
plugin.
|
|
1291
1510
|
|
|
1292
1511
|
Read this section and the central design before changing Email domain behavior.
|
|
1293
1512
|
|
|
1294
1513
|
### Shop configuration and default templates
|
|
1295
1514
|
|
|
1296
1515
|
The E-Mail module ships a neutral German layout in grey tones (table-based,
|
|
1297
|
-
inline styles) and one renderer per accepted kind
|
|
1298
|
-
|
|
1299
|
-
|
|
1516
|
+
inline styles) and one renderer per accepted kind; the colors of the
|
|
1517
|
+
Erscheinungsbild replace the grey tones where set (see "Shop-Stammdaten").
|
|
1518
|
+
The layout shows, from top to bottom: the `logo` of the Erscheinungsbild
|
|
1519
|
+
centered (without one, the configured `displayName`), a white card with the subject as heading and the
|
|
1300
1520
|
renderer's body, a contact line ("Fragen? Dann schreib uns an … oder ruf uns
|
|
1301
1521
|
an unter …", only with `email`/`phone`), and a footer with the company details
|
|
1302
1522
|
(`legal_name` or `displayName`, address, UID, Firmenbuchnummer and
|
|
1303
1523
|
Firmenbuchgericht, website) plus "Diese E-Mail wurde automatisch versendet.".
|
|
1304
|
-
Missing master data fields are left out. Email reads the
|
|
1305
|
-
|
|
1306
|
-
a read fails the mail is sent without that part (
|
|
1307
|
-
instead of failing. Besides
|
|
1524
|
+
Missing master data fields are left out. Email reads the Shop-Stammdaten and
|
|
1525
|
+
the Erscheinungsbild when it sends a mail, so a change applies to the next
|
|
1526
|
+
mail; if a read fails the mail is sent without that part (company details, or
|
|
1527
|
+
logo and colors) instead of failing. Besides
|
|
1308
1528
|
the layout, `displayName` appears in the password-reset and invite subjects.
|
|
1309
|
-
A custom `layout` receives the same data as `shop` (`EmailShopDetails
|
|
1310
|
-
field optional) next to `bodyHtml`,
|
|
1529
|
+
A custom `layout` receives the same data as `shop` (`EmailShopDetails`: the
|
|
1530
|
+
master data, `logo` and `colors`, every field optional) next to `bodyHtml`,
|
|
1531
|
+
`preheader` and `subject`; a renderer receives it as its second argument. A shop
|
|
1311
1532
|
therefore needs only `displayName`, `affiliatePortalUrl`, `inviteUrl`,
|
|
1312
1533
|
`passwordResetUrl` and `orderNotificationEmail`.
|
|
1313
1534
|
|
|
@@ -1515,12 +1736,44 @@ Email exposes authenticated Admin operations at:
|
|
|
1515
1736
|
attempts.
|
|
1516
1737
|
- `POST /admin/email/messages/:id/resends` makes one explicit resend decision
|
|
1517
1738
|
using a request UUID.
|
|
1518
|
-
- `GET /admin/email/
|
|
1519
|
-
effective
|
|
1520
|
-
- `POST /admin/email/
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1739
|
+
- `GET /admin/email/attachments` lists every attachment document by name with
|
|
1740
|
+
its safe version metadata, newest effective version first.
|
|
1741
|
+
- `POST /admin/email/attachments` idempotently (per `request_id`) creates a
|
|
1742
|
+
document with a name and its assigned `mail_kinds`; `POST
|
|
1743
|
+
/admin/email/attachments/:id` renames it and, when `mail_kinds` is sent,
|
|
1744
|
+
replaces its assignments (left out = unchanged). An empty `mail_kinds` lets
|
|
1745
|
+
the document rest. Kinds outside `EMAIL_ATTACHABLE_KINDS` answer 400.
|
|
1746
|
+
- `POST /admin/email/attachments/:id/mail-kinds` (`{ kind, attached }`)
|
|
1747
|
+
attaches the document to one mail kind or detaches it. The kinds are read
|
|
1748
|
+
and changed under the document's row lock, so two toggles of different
|
|
1749
|
+
kinds both persist; repeating a request is harmless. A kind outside
|
|
1750
|
+
`EMAIL_ATTACHABLE_KINDS` answers 400, an unknown document 404. Answers like
|
|
1751
|
+
the update route (`{ created: false, attachment }`).
|
|
1752
|
+
- `POST /admin/email/attachments/:id/versions` idempotently stores one private
|
|
1753
|
+
PDF of at most 5 MiB with its `effective_at` timestamp; replaying a
|
|
1754
|
+
`request_id` with other data or for another document answers 409.
|
|
1755
|
+
- `GET /admin/email/attachments/:id/versions/:version_id/download` streams one
|
|
1756
|
+
authenticated, non-cacheable PDF download (404 when the version does not
|
|
1757
|
+
belong to the document).
|
|
1758
|
+
- `GET /admin/email/templates` lists the editable mails
|
|
1759
|
+
(`EMAIL_EDITABLE_KINDS`) with `customized` (a template is stored) and
|
|
1760
|
+
`code_override` (the shop's code configuration overrides the kind).
|
|
1761
|
+
`GET /admin/email/templates/:kind` returns the stored template or the
|
|
1762
|
+
default one, `POST` stores one (`{ subject, document }`, validated against
|
|
1763
|
+
`EmailTemplateDocumentSchema` and the kind's `EMAIL_TEMPLATE_CATALOG`, at
|
|
1764
|
+
most 256 KiB; 400 otherwise) and `DELETE` goes back to the default. `POST
|
|
1765
|
+
/admin/email/templates/:kind/preview` renders `{ subject, document }` with
|
|
1766
|
+
sample data in the current layout and appearance (`{ subject, html, text }`;
|
|
1767
|
+
not allowed while e-mail is not configured). Other kinds answer 404. `POST
|
|
1768
|
+
/admin/email/templates/:kind/send-test` (`{ subject, document, to,
|
|
1769
|
+
order_display_id?, source_id?, include_attachments? }`) renders the same
|
|
1770
|
+
preview, with sample data or the data of a real order, and sends it to
|
|
1771
|
+
`to` (`{ sent: true, to, subject, attachments }`, `attachments` = number of
|
|
1772
|
+
attached files). `GET
|
|
1773
|
+
/admin/email/templates/:kind/test-sources?order_display_id=N` lists the
|
|
1774
|
+
shipments, returns or refunds of that order a test of the mail can use
|
|
1775
|
+
(`{ sources: [{ id, occurred_at, amount, currency_code, latest }] }`);
|
|
1776
|
+
see "Testmail" under "Mail templates".
|
|
1524
1777
|
- `GET /admin/draft-orders/:id/order-confirmation` returns
|
|
1525
1778
|
`AdminDraftOrderConfirmationResponse` (`{ draft_order_id,
|
|
1526
1779
|
send_order_confirmation }`); `POST` with
|
|
@@ -1531,8 +1784,9 @@ List and detail responses expose only safe identifiers and linkage metadata,
|
|
|
1531
1784
|
kind/status and safe status codes, resource references, trigger, attempt
|
|
1532
1785
|
counts, and timestamps. They never expose recipients, rendered content,
|
|
1533
1786
|
template data, payloads, reset tokens, transport responses, or credentials.
|
|
1534
|
-
|
|
1535
|
-
|
|
1787
|
+
Attachment responses expose name, assigned kinds and, per version, filename,
|
|
1788
|
+
effective timestamp, byte size, SHA-256 and creation time, but never request
|
|
1789
|
+
IDs, file IDs, storage keys, URLs, or content.
|
|
1536
1790
|
|
|
1537
1791
|
An Admin resend is accepted only for a `sent`, `unknown`, or terminal `failed`
|
|
1538
1792
|
source. Password-reset messages can never use the generic resend operation.
|
|
@@ -1548,10 +1802,12 @@ The E-Mail module has one Admin page, `/settings/hartl-services/email`
|
|
|
1548
1802
|
(**Settings → Hartl Services Plugins → E-Mail → Öffnen**; the descriptor's
|
|
1549
1803
|
`admin_page` points the hub there) instead of a top-level sidebar item. It
|
|
1550
1804
|
composes the base's `PluginPageShell` and `PluginFeatureSections` from
|
|
1551
|
-
`@hartl-services/medusa-base/admin-components` (the toggles above)
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1805
|
+
`@hartl-services/medusa-base/admin-components` (the toggles above). Above
|
|
1806
|
+
them sits the **Anhänge** card (documents and the mails they are assigned to,
|
|
1807
|
+
"Bearbeiten" opens the sub-page) and the **Vorlagen** card (the editable
|
|
1808
|
+
mails with "Standard"/"angepasst", "Bearbeiten" opens the template editor,
|
|
1809
|
+
see "Mail templates"); below them, as the last section, the
|
|
1810
|
+
**E-Mail-Protokoll**. The mail
|
|
1555
1811
|
log provides bounded server pagination, allowlisted status/kind filters, a
|
|
1556
1812
|
search by the exact resource ID (e.g. `order_…`, `cus_…`, as pasted from
|
|
1557
1813
|
elsewhere), safe message and attempt status, and an explicitly confirmed
|
|
@@ -1564,11 +1820,123 @@ switch "An Kunden senden" starts off and decides whether the customer receives
|
|
|
1564
1820
|
the order confirmation when the draft is converted (see "Draft orders and
|
|
1565
1821
|
0 € orders").
|
|
1566
1822
|
|
|
1567
|
-
The
|
|
1568
|
-
|
|
1569
|
-
first
|
|
1570
|
-
|
|
1571
|
-
|
|
1823
|
+
The sub-page `/settings/hartl-services/email/attachments` manages the
|
|
1824
|
+
attachment library: "Neuer Anhang" creates a document (name, assigned mails,
|
|
1825
|
+
first PDF with its effective date), each document can be renamed and
|
|
1826
|
+
reassigned ("Bearbeiten") and gets further versions ("Neue Version"; PDF of
|
|
1827
|
+
at most 5 MiB). Versions are listed newest effective first, marked
|
|
1828
|
+
"aktuell" or "geplant", and can be downloaded. Every create and upload sends
|
|
1829
|
+
a fresh request UUID; downloads use the configured authenticated Admin SDK
|
|
1830
|
+
and never expose storage file IDs or URLs in the UI. There is no delete:
|
|
1831
|
+
removing every assigned mail lets a document rest.
|
|
1832
|
+
|
|
1833
|
+
### Mail templates
|
|
1834
|
+
|
|
1835
|
+
All twelve mails (`EMAIL_EDITABLE_KINDS`) are block templates an Admin edits
|
|
1836
|
+
on the E-Mail page (card **Vorlagen**, grouped into Bestell-, Konto- and
|
|
1837
|
+
Affiliate-Mails → editor page `/settings/hartl-services/email/templates/:kind`).
|
|
1838
|
+
The editor offers a toolbar, slash commands ("/" lists what the mail
|
|
1839
|
+
allows), a drag handle to move top-level blocks, a live preview, a test mail
|
|
1840
|
+
and, for the six customer order mails, the attachment checkboxes of the
|
|
1841
|
+
mail (`POST /admin/email/attachments/:id/mail-kinds`, one kind at a time;
|
|
1842
|
+
the Anhänge page's edit dialog likewise saves the name only when it changed
|
|
1843
|
+
and then each changed mail kind on its own).
|
|
1844
|
+
|
|
1845
|
+
- **Document:** a subset of the editor's ProseMirror JSON
|
|
1846
|
+
(`EmailTemplateDocumentSchema` in Contracts): paragraphs with bold, italic,
|
|
1847
|
+
http(s)/mailto links and line breaks, bullet lists, placeholders, a
|
|
1848
|
+
**Hinweis** box (`notice`), a **Nur wenn …** section (`conditional`) and
|
|
1849
|
+
the dynamic blocks of the kind (`EMAIL_TEMPLATE_CATALOG`): `details`
|
|
1850
|
+
(Eckdaten), `order_summary` (items and totals, optional heading),
|
|
1851
|
+
`item_list` (items without prices, optional heading), `address`,
|
|
1852
|
+
`tracking`, `button` (the mail's action link: target fixed per kind from
|
|
1853
|
+
the data or the configuration, label editable; nothing without a URL),
|
|
1854
|
+
`link_fallback` (the plain link, HTML only), `validity` and `message` (the
|
|
1855
|
+
partner application's text). Dynamic blocks render the mail's real data at
|
|
1856
|
+
send time and render nothing without it. Conditions: `invoice_attached`,
|
|
1857
|
+
`cancellation_attached`, `more_to_follow`, `return_number`. Password reset,
|
|
1858
|
+
account confirmation and admin invite must contain the `button` block
|
|
1859
|
+
(`required_blocks`); a template without it is rejected.
|
|
1860
|
+
- **Placeholders** (`shop_name`, `order_number`, `customer_name`,
|
|
1861
|
+
`return_number`, `refund_amount`, `affiliate_name`, `report_month`,
|
|
1862
|
+
`applicant_name`, per kind as in the catalog) are escaped in
|
|
1863
|
+
the HTML and raw in subject and text; a missing value is empty. A custom
|
|
1864
|
+
subject writes them as `{{key}}`; blank subject = the default subject.
|
|
1865
|
+
- **Defaults:** without a stored template a mail renders its default
|
|
1866
|
+
document, which produces exactly the former code output. Messages stored
|
|
1867
|
+
before order snapshots existed keep their code fallback. Password reset,
|
|
1868
|
+
account confirmation and invite read the stored template in their own
|
|
1869
|
+
handlers, the other mails at dispatch.
|
|
1870
|
+
- **When it applies:** templates are read at send time, so a saved template
|
|
1871
|
+
also applies to queued, retried and resent mails; attachments are fixed
|
|
1872
|
+
when the mail is created. An invalid stored template or a failed read sends
|
|
1873
|
+
the default (logged as a warning); a template never fails a mail.
|
|
1874
|
+
- **Precedence:** a shop's code `renderers[kind]` > Admin template > default.
|
|
1875
|
+
The editor shows when a code override is active.
|
|
1876
|
+
- Stored in `email_template` (one row per kind, upsert on save).
|
|
1877
|
+
- **Testmail:** the editor sends the current draft to one address
|
|
1878
|
+
(`POST /admin/email/templates/:kind/send-test`). The subject starts with
|
|
1879
|
+
`[Test] `. The mail goes straight through the Notification module: it is
|
|
1880
|
+
not recorded as an email message, is neither retried nor deduplicated, never
|
|
1881
|
+
goes to the customer, and can be sent again freely. A rejected address, an
|
|
1882
|
+
unreachable mail server or an unclear outcome answers a German message
|
|
1883
|
+
without the provider's own text; while e-mail is not configured the route
|
|
1884
|
+
answers 400 (`not_allowed`).
|
|
1885
|
+
- **Data:** sample data by default. For the seven order mails,
|
|
1886
|
+
`order_display_id` (the order number, e.g. `14`) renders the data of that
|
|
1887
|
+
real, non-draft order instead, so the mail contains real customer data:
|
|
1888
|
+
the order itself (confirmation, shop notification; cancellation only for
|
|
1889
|
+
a canceled order), or one of its shipments (shipped, not canceled),
|
|
1890
|
+
returns (not canceled), received returns (status `received`) or refunds
|
|
1891
|
+
(over all payments). In the editor's dialog the order field searches by
|
|
1892
|
+
number, e-mail or name and offers up to eight orders.
|
|
1893
|
+
- **Source:** `GET …/test-sources?order_display_id=N` lists the candidates
|
|
1894
|
+
of shipping, return and refund mails with the same filters, newest first
|
|
1895
|
+
(by `shipped_at`, `created_at`, `received_at` or the refund's
|
|
1896
|
+
`created_at`; refunds with `amount` and `currency_code`, otherwise
|
|
1897
|
+
`null`); `latest` marks the default. Other mails list none (`[]`), an
|
|
1898
|
+
unknown order answers 404. `send-test` takes the chosen `source_id`;
|
|
1899
|
+
without it the newest is used. `source_id` without `order_display_id`,
|
|
1900
|
+
for a mail without candidates („Diese Mail hat keine Vorgänge zur
|
|
1901
|
+
Auswahl.“) or not among the order's candidates („Dieser Vorgang gehört
|
|
1902
|
+
nicht zu Bestellung #14 oder passt nicht zu dieser Mail.“) answers 400.
|
|
1903
|
+
An unknown order answers 404, a missing event 400 (e.g. „Bestellung #14
|
|
1904
|
+
hat keinen Versand.“), an order number for an account or affiliate mail
|
|
1905
|
+
400. The Notification of such a test carries `resource_type: "order"`,
|
|
1906
|
+
the order id and `data: { admin_id }`; otherwise
|
|
1907
|
+
`resource_type: "email_template"`.
|
|
1908
|
+
- **Attachments:** `include_attachments` (default `true`) attaches the
|
|
1909
|
+
library documents currently assigned to the mail, each in the version
|
|
1910
|
+
effective at the cut-off date: the order's placing for the order
|
|
1911
|
+
confirmation with a real order (like the real mail), otherwise now. It is
|
|
1912
|
+
ignored for mails that cannot carry attachments.
|
|
1913
|
+
- **Receipts from the real mail:** with a real order and
|
|
1914
|
+
`include_attachments`, a shipping, cancellation or refund test carries
|
|
1915
|
+
exactly the receipts (invoice, cancellation document) the real mail of
|
|
1916
|
+
that shipment, cancellation or refund carried — found by its business
|
|
1917
|
+
key (`order-shipped:<fulfillment>`, `order-canceled:<order>`,
|
|
1918
|
+
`refund:<refund>`), its non-library attachments in their originally sent
|
|
1919
|
+
version — and sets `invoice_attached` / `cancellation_attached` as that
|
|
1920
|
+
mail had it, so its receipt hint shows. Without a real mail (e.g. the
|
|
1921
|
+
refund of a canceled order, whose receipt went with the cancellation, or
|
|
1922
|
+
receipts were switched off then) there is no receipt and no hint, as for
|
|
1923
|
+
the customer; the current Documents switches play no role. With
|
|
1924
|
+
`include_attachments: false` neither receipts, library documents nor the
|
|
1925
|
+
hint are sent. Receipts come first, then library documents; `attachments`
|
|
1926
|
+
counts both. A missing or changed file answers 400 („Anhang „X“ fehlt
|
|
1927
|
+
bzw. ist beschädigt.“), any other read failure „Anhang „X“ konnte
|
|
1928
|
+
gerade nicht geladen werden.“
|
|
1929
|
+
|
|
1930
|
+
### Mail attachments
|
|
1931
|
+
|
|
1932
|
+
The global Terms PDFs (`AGB`), the EU legal-guarantee notice or a flyer are
|
|
1933
|
+
documents of the attachment library. A document has a name, the customer
|
|
1934
|
+
mail kinds it is attached to and immutable PDF versions, each valid from its
|
|
1935
|
+
`effective_at`. Which version a mail carries is decided once, when the mail
|
|
1936
|
+
is created (see the rules above). Migration `Migration20261009083539` turned
|
|
1937
|
+
the former Terms PDF versions into the document `AGB` (id `eatd_terms`,
|
|
1938
|
+
assigned to `order.received`, version ids kept) and rewrote every stored
|
|
1939
|
+
message snapshot accordingly; it cannot be reverted.
|
|
1572
1940
|
|
|
1573
1941
|
Admin consumers import wire DTOs and paths only from the Contracts package and
|
|
1574
1942
|
reuse their configured Medusa SDK:
|
|
@@ -1769,16 +2137,21 @@ every page. Packing lists show only the sender in the footer. Every page
|
|
|
1769
2137
|
carries "Seite x von y" bottom right in an 8 mm bottom page margin
|
|
1770
2138
|
(`@page { @bottom-right }`; the page count exists only in page margin boxes).
|
|
1771
2139
|
|
|
1772
|
-
Settings under Settings → "Hartl Services Plugins" → **Dokumente
|
|
1773
|
-
every render and passed as
|
|
2140
|
+
Settings under Settings → "Hartl Services Plugins" → **Dokumente** and the
|
|
2141
|
+
Erscheinungsbild of the Shop-Stammdaten, read on every render and passed as
|
|
2142
|
+
`input.settings` (`DocumentRenderSettings`). Like
|
|
1774
2143
|
the merchant data they are not part of the snapshot: a regenerated document
|
|
1775
2144
|
shows the current values.
|
|
1776
2145
|
|
|
1777
|
-
- **Logo** (`logo
|
|
1778
|
-
most 2 MiB) and passes it inline
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
a logo never blocks issuance.
|
|
2146
|
+
- **Logo** (the `logo` of the Shop-Stammdaten, section "Erscheinungsbild"):
|
|
2147
|
+
each render downloads it (10 s timeout, at most 2 MiB) and passes it inline
|
|
2148
|
+
as `settings.logo_src` (`data:` URL), so Chromium never waits on the
|
|
2149
|
+
network. Without a logo, or when the download fails (logged as a warning),
|
|
2150
|
+
the document shows the merchant's legal name; a logo never blocks issuance.
|
|
2151
|
+
- **Colors** (the colors of the Erscheinungsbild, `settings.colors`): the set
|
|
2152
|
+
ones override `--accent`, `--text`, `--muted`, `--line` and `--table-head`
|
|
2153
|
+
in a `:root` block after the default stylesheet and before the shop
|
|
2154
|
+
theme's stylesheet, so a shop theme still wins.
|
|
1782
2155
|
- **Zahlungskonditionen** (`payment_terms`, text): printed below the totals
|
|
1783
2156
|
of invoices only (not on cancellations or credit notes); blank means none.
|
|
1784
2157
|
Line breaks in the text are kept.
|