donation item, shop soft open
All checks were successful
Deploy / build-deploy (push) Successful in 4m11s

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-08-17 11:04:03 +02:00
commit abbd616b40
23 changed files with 2898 additions and 209 deletions

View file

@ -75,6 +75,38 @@ std::string BuildOrderConfirmationEmail(const OrderRecord& o,
// CR/LF would become an extra recipient, so the check repeats here.
if (!Form::LooksLikeEmail(o.buyer.email)) return {};
// A donation's confirmation is a different message: a thank-you, no
// invoice attached (none exists), no dispatch promise (nothing ships).
// Single-part plain text — multipart with one part is just noise.
if (o.donation) {
std::string m;
m.reserve(1024);
m += std::format("From: {}\n", from);
m += std::format("To: {}\n", o.buyer.email);
m += std::format("Subject: Catcrafts donation {} received\n", o.reference);
m += std::format("Date: {}\n", dateRfc2822);
m += std::format("Message-ID: <{}@{}>\n", o.token, kSellerSite);
m += "MIME-Version: 1.0\n";
m += "Content-Type: text/plain; charset=utf-8\n";
m += "Content-Transfer-Encoding: 8bit\n\n";
m += std::format("Thank you — your donation {} of {} has arrived.\n\n",
o.reference, Money::FormatEuro(o.totalMinor));
if (!o.paidVia.empty()) {
m += std::format("* Paid via: {}\n\n", o.paidVia);
}
m += "It funds the open-source work directly and will appear in the "
"running total on https://catcrafts.net/financials — as an "
"aggregate, never individually. No VAT applies to a donation and "
"no invoice is issued; this email and the donation page are the "
"receipt:\n\n";
m += std::format(" {}\n\n", orderUrl);
m += "Questions? Reply to this email.\n\n";
m += std::format("{} · {} · {}\n", kSellerName, kSellerStreet, kSellerCity);
m += std::format("KVK {} · VAT {} · https://{}\n", kSellerKvk, kSellerVat,
kSellerSite);
return m;
}
const std::string item = colorLabel.empty()
? std::string(productName)
: std::format("{} — {}", productName, colorLabel);