From defd078e4b9b33d152603620845c65201bcc6a1e Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Wed, 29 Apr 2026 20:13:23 +0200 Subject: [PATCH] feat(cms): white-label email templates and API doc config (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Replace all hardcoded muellerprints brand identity in email templates with template variables sourced from env vars - Inject shop context into both `sendInvoice` and `sendDeliveryNote` template calls in `order.ts` - Make API documentation title/description env-var driven ## New env vars (all optional with safe defaults) | Var | Default | Used in | |-----|---------|---------| | `SHOP_NAME` | `"Shop"` | Email subject, body, footer | | `SHOP_CONTACT_NAME` | `""` | Email footer | | `SHOP_ADDRESS` | `""` | Email footer | | `SHOP_PHONE` | `""` | Email footer | | `SHOP_EMAIL` | `ADMIN_EMAIL_ADDRESS` | Email footer | | `SHOP_LOGO_URL` | `""` | Email header logo | | `SHOP_SECONDARY_LOGO_URL` | `""` | Email footer logo | | `API_TITLE` | `"Paperwork API"` | Swagger/OpenAPI title | | `API_DESCRIPTION` | `"Paperwork API"` | Swagger/OpenAPI description | ## Test plan - [ ] Set `SHOP_NAME=TestShop` and trigger invoice send → confirm subject and body use `TestShop` - [ ] Leave `SHOP_NAME` unset → confirm default `"Shop"` appears - [ ] Set `SHOP_LOGO_URL` → confirm logo renders in email header; unset → confirm no broken `` tag - [ ] Check Strapi admin `/documentation` with `API_TITLE=MyAPI` env var Closes #1 Reviewed-on: https://git.librete.ch/libreshop/cms/pulls/2 Co-authored-by: Michael Czechowski Co-committed-by: Michael Czechowski --- CHANGELOG.md | 21 ++++++- config/constants.ts | 8 +++ config/plugins.ts | 12 ++-- src/api/order/services/order.ts | 16 ++--- .../documentation/config/settings.json | 4 +- src/templates/emailTemplates.ts | 62 +++++++++---------- 6 files changed, 74 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2478f30..3fce3e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,26 @@ All notable changes to libreshop/cms are documented here. -## Unreleased +## [0.1.1] - 2026-04-29 + +### Changed + +- White-label email templates: replace all hardcoded muellerprints company + identity (name, contact, address, phone, email, logo URLs) with + `<%= shopName %>` / `<%= shopContactName %>` / `<%= shopAddress %>` / + `<%= shopPhone %>` / `<%= shopEmail %>` / `<%= shopLogoUrl %>` / + `<%= shopSecondaryLogoUrl %>` template variables, sourced from env vars + `SHOP_NAME`, `SHOP_CONTACT_NAME`, `SHOP_ADDRESS`, `SHOP_PHONE`, + `SHOP_EMAIL`, `SHOP_LOGO_URL`, `SHOP_SECONDARY_LOGO_URL`. +- `config/constants.ts`: export shop brand constants from env. +- `src/api/order/services/order.ts`: inject shop context into template calls. +- `config/plugins.ts`: API doc title/description driven by `API_TITLE` / + `API_DESCRIPTION` env vars (defaults: `"Paperwork API"`). +- `src/extensions/documentation/config/settings.json`: neutral placeholder. + +Closes #1 + +## [0.1.0] - 2026-04-29 - Extracted from `mp/cms/` (2026-04-29). The component history before the extraction lives in the `muellerprints` repository. diff --git a/config/constants.ts b/config/constants.ts index 6bd7c34..d3de926 100644 --- a/config/constants.ts +++ b/config/constants.ts @@ -10,6 +10,14 @@ export const paypalEnvironment = process.env.PAYPAL_ENVIRONMENT! === "production export const adminEmail = process.env.ADMIN_EMAIL_ADDRESS!; +export const shopName = process.env.SHOP_NAME ?? "Shop"; +export const shopContactName = process.env.SHOP_CONTACT_NAME ?? ""; +export const shopAddress = process.env.SHOP_ADDRESS ?? ""; +export const shopPhone = process.env.SHOP_PHONE ?? ""; +export const shopEmail = process.env.SHOP_EMAIL ?? process.env.ADMIN_EMAIL_ADDRESS ?? ""; +export const shopLogoUrl = process.env.SHOP_LOGO_URL ?? ""; +export const shopSecondaryLogoUrl = process.env.SHOP_SECONDARY_LOGO_URL ?? ""; + // TODO: Should be retrieved from DepotApi export const vatIncludedDecimal = 1.19; // TODO: Should be retrieved from DepotApi diff --git a/config/plugins.ts b/config/plugins.ts index 8139c5f..10b4b99 100644 --- a/config/plugins.ts +++ b/config/plugins.ts @@ -10,15 +10,11 @@ export default ({ env }) => ({ openapi: "3.0.1", info: { version: "1.0.0", - title: "MUELLERPTINTS. Paperwork", - description: "API Documentation for MUELLERPRINTS. Paperwork", + title: env("API_TITLE", "Paperwork API"), + description: env("API_DESCRIPTION", "Paperwork API"), termsOfService: false, - contact: { - name: "Michael W. Czechowski", - email: "mail@dailysh.it", - url: "https://dailysh.it" - }, - license: "Copyright (C) 2024 Michael W. Czechowski", + contact: false, + license: false, externalDocs: false }, "x-strapi-config": { diff --git a/src/api/order/services/order.ts b/src/api/order/services/order.ts index 6313307..dd846be 100644 --- a/src/api/order/services/order.ts +++ b/src/api/order/services/order.ts @@ -3,7 +3,7 @@ import fs from "fs"; import { factories } from "@strapi/strapi"; import { sanitize } from "@strapi/utils"; import { ID } from "@strapi/database/dist/types"; -import { vatDecimal, vatIncludedDecimal, baseUrl, adminEmail } from "../../../../config/constants"; +import { vatDecimal, vatIncludedDecimal, baseUrl, adminEmail, shopName, shopContactName, shopAddress, shopPhone, shopEmail, shopLogoUrl, shopSecondaryLogoUrl } from "../../../../config/constants"; import { calculateTotalProductPrice, productDefaultParams } from "../../product/services/product"; import { CartProduct, Order, PdfBody } from "../../../../types"; import { pdfApi } from "../../../services/PdfApi"; @@ -81,12 +81,13 @@ export default factories.createCoreService("api::order.order", ({ strapi }) => ( strapi.log.info(`app:i:order-service: - Sending invoice for order ${uuid}`); const oderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Partial; + const shopContext = { shopName, shopContactName, shopAddress, shopPhone, shopEmail, shopLogoUrl, shopSecondaryLogoUrl }; try { const emailConfig: MessageBody = { to_email: oderUnsafe.email, - subject: template(invoiceEmailTemplate.subject)(oderUnsafe), - message: template(invoiceEmailTemplate.text)({ baseUrl, ...oderUnsafe }), - html: template(invoiceEmailTemplate.html)({ baseUrl, ...oderUnsafe }) + subject: template(invoiceEmailTemplate.subject)({ ...shopContext, ...oderUnsafe }), + message: template(invoiceEmailTemplate.text)({ baseUrl, ...shopContext, ...oderUnsafe }), + html: template(invoiceEmailTemplate.html)({ baseUrl, ...shopContext, ...oderUnsafe }) }; strapi.log.debug(`app:d:order-service: - Email config ${emailConfig.html}`); @@ -118,12 +119,13 @@ export default factories.createCoreService("api::order.order", ({ strapi }) => ( sendDeliveryNote: async (uuid: string, blob?: ArrayBuffer) => { strapi.log.info(`app:i:order-service: - Sending delivery note for order ${uuid}`); const oderUnsafe = (await strapi.service("api::order.order").findOneByUuid(uuid)) as Partial; + const shopContext = { shopName, shopContactName, shopAddress, shopPhone, shopEmail, shopLogoUrl, shopSecondaryLogoUrl }; try { const emailConfig: MessageBody = { to_email: oderUnsafe.email, - subject: template(deliveryNoteEmailTemplate.subject)(oderUnsafe), - message: template(deliveryNoteEmailTemplate.text)(oderUnsafe), - html: template(deliveryNoteEmailTemplate.html)({ ...oderUnsafe, baseUrl }) + subject: template(deliveryNoteEmailTemplate.subject)({ ...shopContext, ...oderUnsafe }), + message: template(deliveryNoteEmailTemplate.text)({ ...shopContext, ...oderUnsafe }), + html: template(deliveryNoteEmailTemplate.html)({ baseUrl, ...shopContext, ...oderUnsafe }) }; await mailApi.sendTextMessage(emailConfig); strapi.log.info(`app:i:order-service: ✔ Sending delivery note for order ${uuid}`); diff --git a/src/extensions/documentation/config/settings.json b/src/extensions/documentation/config/settings.json index ac399d7..2303c2c 100644 --- a/src/extensions/documentation/config/settings.json +++ b/src/extensions/documentation/config/settings.json @@ -2,8 +2,8 @@ "openapi": "3.0.1", "info": { "version": "1.0.0", - "title": "MUELLERPTINTS. Paperwork", - "description": "API Documentation for MUELLERPRINTS. Paperwork", + "title": "Paperwork API", + "description": "Paperwork API", "termsOfService": false, "contact": false, "license": false diff --git a/src/templates/emailTemplates.ts b/src/templates/emailTemplates.ts index 4dff953..2a8cb61 100644 --- a/src/templates/emailTemplates.ts +++ b/src/templates/emailTemplates.ts @@ -1,5 +1,5 @@ export const invoiceEmailTemplate = { - subject: "MUELLERPRINTS Rechnungsnummer <%= invoiceNumber %>", + subject: "<%= shopName %> Rechnungsnummer <%= invoiceNumber %>", text: `Rechnungsnummer: <%= invoiceNumber %> Ausstellungsdatum: <%= new Date(acceptedTermsAndConditionsAt).toLocaleDateString("de-DE") %> @@ -7,7 +7,7 @@ Ausstellungsdatum: <%= new Date(acceptedTermsAndConditionsAt).toLocaleDateString Hallo <%= invoiceAddressStructured.givenName %>, -vielen Dank für deinen Einkauf bei MUELLERPRINTS. +vielen Dank für deinen Einkauf bei <%= shopName %>. Deine Bestellnummer: <%= id %> Zur Bestellübersicht: <%= baseUrl %>/checkout/result/<%= uuid %> @@ -49,14 +49,14 @@ inkl. MwSt. (19%): <%= VAT.toFixed(2) %> EUR Deine Rechnung kannst du jederzeit über diesen Link herunterladen: <%= baseUrl %><%= invoice.url %> <% } %> -Vielen Dank, dass du dich für MUELLERPRINTS entschieden hast. +Vielen Dank, dass du dich für <%= shopName %> entschieden hast. ------------------ -MUELLERPRINTS -Max Müller -Rotenbergstraße 39, 70190 Stuttgart -T +49 (0)711/262 49 64 -paperwork@muellerprints.de`, +<%= shopName %> +<%= shopContactName %> +<%= shopAddress %> +<%= shopPhone ? "T " + shopPhone : "" %> +<%= shopEmail %>`, html: ` @@ -74,7 +74,7 @@ paperwork@muellerprints.de`, - MUELLERPRINTS PAPERWORK + <% if (shopLogoUrl) { %><%= shopName %><% } %> @@ -83,7 +83,7 @@ paperwork@muellerprints.de`,

- Vielen Dank für deinen Einkauf bei MUELLERPRINTS. + Vielen Dank für deinen Einkauf bei <%= shopName %>.

@@ -197,7 +197,7 @@ paperwork@muellerprints.de`, <% } %>

- Vielen Dank, dass du dich für MUELLERPRINTS entschieden hast. + Vielen Dank, dass du dich für <%= shopName %> entschieden hast.

@@ -209,15 +209,15 @@ paperwork@muellerprints.de`,

- MUELLERPRINTS
- Max Müller
- Rotenbergstraße 39, 70190 Stuttgart
- T +49 (0)711/262 49 64
- paperwork@muellerprints.de + <%= shopName %>
+ <% if (shopContactName) { %><%= shopContactName %>
<% } %> + <% if (shopAddress) { %><%= shopAddress %>
<% } %> + <% if (shopPhone) { %>T <%= shopPhone %>
<% } %> + <% if (shopEmail) { %><%= shopEmail %><% } %>

- MUELLERPRINTS + <% if (shopSecondaryLogoUrl) { %><%= shopName %><% } %> @@ -243,7 +243,7 @@ paperwork@muellerprints.de`, }; export const deliveryNoteEmailTemplate = { - subject: "Your Delivery Note <%= deliveryNoteNumber %> from MUELLERPRINTS", + subject: "Your Delivery Note <%= deliveryNoteNumber %> from <%= shopName %>", text: `Dear Customer, Thank you for your Your delivery note <%= deliveryNoteNumber %> is attached to this email. @@ -272,14 +272,14 @@ Delivery Address: If you have any questions about your delivery, please don't hesitate to contact us. Best regards, -MUELLERPRINTS PAPERWORK +<%= shopName %> ------------------ -MUELLERPRINTS PAPERWORK -Max Müller -Rotenbergstraße 39, 70190 Stuttgart -T +49 (0)711/262 49 64 -paperwork@muellerprints.de`, +<%= shopName %> +<%= shopContactName %> +<%= shopAddress %> +<%= shopPhone ? "T " + shopPhone : "" %> +<%= shopEmail %>`, html: ` @@ -295,7 +295,7 @@ paperwork@muellerprints.de`, - MUELLERPRINTS PAPERWORK + <% if (shopLogoUrl) { %><%= shopName %><% } %> @@ -407,15 +407,15 @@ paperwork@muellerprints.de`,

- MUELLERPRINTS PAPERWORK
- Max Müller
- Rotenbergstraße 39, 70190 Stuttgart
- T +49 (0)711/262 49 64
- paperwork@muellerprints.de + <%= shopName %>
+ <% if (shopContactName) { %><%= shopContactName %>
<% } %> + <% if (shopAddress) { %><%= shopAddress %>
<% } %> + <% if (shopPhone) { %>T <%= shopPhone %>
<% } %> + <% if (shopEmail) { %><%= shopEmail %><% } %>

- MUELLERPRINTS + <% if (shopSecondaryLogoUrl) { %><%= shopName %><% } %>