fix: opravy generování QR kódů, zobrazení také na stránce objednání
CI / Generate TypeScript types (push) Successful in 14s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 25s
CI / Build client (push) Successful in 34s
CI / Playwright E2E tests (push) Successful in 1m18s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 3s
CI / Generate TypeScript types (push) Successful in 14s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 25s
CI / Build client (push) Successful in 34s
CI / Playwright E2E tests (push) Successful in 1m18s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 3s
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
[
|
||||
"Zobrazení neuhrazených plateb i na stránce objednávek",
|
||||
"Oprava duplicitního zobrazení QR kódu u Pizza day",
|
||||
"Odstranění diakritiky v platebních QR kódech"
|
||||
]
|
||||
+19
-5
@@ -44,6 +44,24 @@ function createStorageKey(customerName: string, id: string): string {
|
||||
return `qr_${nameHash}_${id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Očistí zprávu (účel platby) pro QR platbu:
|
||||
* - transliteruje diakritiku na základní písmena (š→s, č→c, ř→r, ...)
|
||||
* - odstraní zbylé znaky mimo ISO 8859-1
|
||||
* - odstraní '*', který v QR platbě slouží jako oddělovač polí
|
||||
* - ořízne na max. 60 znaků
|
||||
*
|
||||
* @param message původní zpráva
|
||||
* @returns očištěná zpráva vhodná pro QR platbu
|
||||
*/
|
||||
export function sanitizeQrMessage(message: string): string {
|
||||
const sanitized = message
|
||||
.normalize('NFD').replace(/[\u0300-\u036f]/g, '') // diakritika → základní písmeno
|
||||
.replace(/[^\x00-\xff]/g, '') // znaky mimo ISO 8859-1
|
||||
.replace(/\*/g, ''); // '*' je v QR platbě oddělovač
|
||||
return sanitized.length > 60 ? sanitized.substring(0, 60) : sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vygeneruje a uloží obrázek platebního QR kódu do storage (Redis/JSON).
|
||||
* Data přežijí redeploy — není třeba persistentní filesystém.
|
||||
@@ -56,11 +74,7 @@ function createStorageKey(customerName: string, id: string): string {
|
||||
* @param id unikátní identifikátor (UUID) tohoto QR kódu
|
||||
*/
|
||||
export async function generateQr(customerName: string, bankAccountNumber: string, bankAccountHolder: string, amount: number, message: string, id: string): Promise<void> {
|
||||
// Zpráva nesmí obsahovat '*' a znaky mimo ISO 8859-1; délka max. 60 znaků
|
||||
message = message.replace(/[^\x00-\xff]/g, '').replace(/\*/g, '');
|
||||
if (message.length > 60) {
|
||||
message = message.substring(0, 60);
|
||||
}
|
||||
message = sanitizeQrMessage(message);
|
||||
const payload = {
|
||||
iban: convertBbanToIban(bankAccountNumber),
|
||||
amount,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { convertBbanToIban } from '../qr';
|
||||
import { convertBbanToIban, sanitizeQrMessage } from '../qr';
|
||||
|
||||
test('konverze BBAN s prefixem na IBAN', () => {
|
||||
// Číslo účtu 19-2000145399/0800 (Česká spořitelna) → CZ6508000000192000145399
|
||||
@@ -34,3 +34,26 @@ test('výsledek vždy začíná CZ', () => {
|
||||
expect(convertBbanToIban('100-2000145399/0300')).toMatch(/^CZ/);
|
||||
expect(convertBbanToIban('2000145399/0100')).toMatch(/^CZ/);
|
||||
});
|
||||
|
||||
test('sanitizace zprávy – diakritika se transliteruje na základní písmena', () => {
|
||||
expect(sanitizeQrMessage('Pizza Šunková')).toBe('Pizza Sunkova');
|
||||
expect(sanitizeQrMessage('čaj a káva')).toBe('caj a kava');
|
||||
expect(sanitizeQrMessage('Žížala, řeřicha, ďábel')).toBe('Zizala, rericha, dabel');
|
||||
});
|
||||
|
||||
test('sanitizace zprávy – hvězdička se odstraní', () => {
|
||||
expect(sanitizeQrMessage('Pizza *akce* 1+1')).toBe('Pizza akce 1+1');
|
||||
expect(sanitizeQrMessage('***')).toBe('');
|
||||
});
|
||||
|
||||
test('sanitizace zprávy – znaky mimo ISO 8859-1 se odstraní', () => {
|
||||
// Emoji a CJK znaky nemají ASCII ekvivalent → zmizí, zbytek zůstane
|
||||
expect(sanitizeQrMessage('Oběd 🍕 hotovo')).toBe('Obed hotovo');
|
||||
// Znaky v rozsahu ISO 8859-1 (např. § ° é) zůstanou zachovány
|
||||
expect(sanitizeQrMessage('Cena 100°C § café')).toBe('Cena 100°C § cafe');
|
||||
});
|
||||
|
||||
test('sanitizace zprávy – ořez na 60 znaků', () => {
|
||||
const long = 'a'.repeat(70);
|
||||
expect(sanitizeQrMessage(long)).toHaveLength(60);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user