feat(pdf): drop the prices-excl.-VAT notice from offer/order/PO PDFs
The 'Ceny jsou uvedeny bez DPH...' explanatory line is removed at user request from all three non-tax-document PDFs - the 'Celkem bez DPH' total label carries the information by itself. Dead vat_notice keys and .vat-note CSS removed; tests now pin the notice's ABSENCE (file renamed pdf-vat-note -> pdf-no-vat). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -532,7 +532,7 @@ describe("renderIssuedOrderHtml", () => {
|
|||||||
expect(fallback).toContain("Objednáváme si u Vás:");
|
expect(fallback).toContain("Objednáváme si u Vás:");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("never renders VAT columns, totals NET with 'Celkem bez DPH' and the prices notice", () => {
|
it("never renders VAT columns or notices; totals NET with 'Celkem bez DPH'", () => {
|
||||||
const html = renderIssuedOrderHtml(order, items, null, null, "cs", issuer);
|
const html = renderIssuedOrderHtml(order, items, null, null, "cs", issuer);
|
||||||
// No VAT anywhere — the PO is not a tax document.
|
// No VAT anywhere — the PO is not a tax document.
|
||||||
expect(html).not.toContain("%DPH");
|
expect(html).not.toContain("%DPH");
|
||||||
@@ -540,21 +540,17 @@ describe("renderIssuedOrderHtml", () => {
|
|||||||
// Line total = netto (2 × 100).
|
// Line total = netto (2 × 100).
|
||||||
expect(html).toContain('<td class="right total-cell">200,00</td>');
|
expect(html).toContain('<td class="right total-cell">200,00</td>');
|
||||||
expect(html).toContain("Celkem bez DPH");
|
expect(html).toContain("Celkem bez DPH");
|
||||||
// No Mezisoučet row (it would duplicate the grand total).
|
// No Mezisoučet row (it would duplicate the grand total) and no
|
||||||
|
// prices-excl.-VAT notice (user removed it — the total label suffices).
|
||||||
expect(html).not.toContain("Mezisoučet");
|
expect(html).not.toContain("Mezisoučet");
|
||||||
// The fixed prices-excl.-VAT notice.
|
expect(html).not.toContain("Ceny jsou uvedeny bez DPH");
|
||||||
expect(html).toContain(
|
|
||||||
"Ceny jsou uvedeny bez DPH. DPH bude účtováno dle platných předpisů.",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders the English notice and total label for lang=en", () => {
|
it("renders the English total label for lang=en, no VAT columns or notice", () => {
|
||||||
const html = renderIssuedOrderHtml(order, items, null, null, "en", issuer);
|
const html = renderIssuedOrderHtml(order, items, null, null, "en", issuer);
|
||||||
expect(html).toContain("Total excl. VAT");
|
expect(html).toContain("Total excl. VAT");
|
||||||
expect(html).toContain(
|
|
||||||
"Prices are exclusive of VAT. VAT will be charged according to applicable regulations.",
|
|
||||||
);
|
|
||||||
expect(html).not.toContain("VAT%");
|
expect(html).not.toContain("VAT%");
|
||||||
|
expect(html).not.toContain("Prices are exclusive of VAT");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("footer shows the logged-in user's name, no e-mail, no Schválil column", () => {
|
it("footer shows the logged-in user's name, no e-mail, no Schválil column", () => {
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import offersPdfRoutes from "../routes/admin/offers-pdf";
|
|||||||
|
|
||||||
// Offers, received orders (their confirmation PDF) and issued orders are NOT
|
// Offers, received orders (their confirmation PDF) and issued orders are NOT
|
||||||
// tax documents — VAT must never appear on them. These tests pin that contract
|
// tax documents — VAT must never appear on them. These tests pin that contract
|
||||||
// for the confirmation and offer PDFs: no VAT columns/rows, the grand total is
|
// for the confirmation and offer PDFs: no VAT columns/rows/notices, and the
|
||||||
// "Celkem bez DPH" / "Total excl. VAT", and the fixed prices-excl.-VAT notice
|
// grand total is "Celkem bez DPH" / "Total excl. VAT". (The issued-order PDF
|
||||||
// is printed. (The issued-order PDF is covered in issued-orders.test.ts.)
|
// is covered in issued-orders.test.ts.)
|
||||||
|
|
||||||
const CS_NOTE =
|
// The explanatory prices-excl.-VAT notice was removed at user request — the
|
||||||
"Ceny jsou uvedeny bez DPH. DPH bude účtováno dle platných předpisů.";
|
// total label alone carries the information. Pin its absence too.
|
||||||
const EN_NOTE =
|
const CS_NOTE = "Ceny jsou uvedeny bez DPH";
|
||||||
"Prices are exclusive of VAT. VAT will be charged according to applicable regulations.";
|
const EN_NOTE = "Prices are exclusive of VAT";
|
||||||
|
|
||||||
describe("renderOrderConfirmationHtml (order confirmation PDF)", () => {
|
describe("renderOrderConfirmationHtml (order confirmation PDF)", () => {
|
||||||
const order = {
|
const order = {
|
||||||
@@ -36,7 +36,7 @@ describe("renderOrderConfirmationHtml (order confirmation PDF)", () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
it("cs: NET total labeled 'Celkem bez DPH', no VAT columns, notice present", () => {
|
it("cs: NET total labeled 'Celkem bez DPH', no VAT columns or notice", () => {
|
||||||
const html = renderOrderConfirmationHtml(order, items, null, "cs", "Jan");
|
const html = renderOrderConfirmationHtml(order, items, null, "cs", "Jan");
|
||||||
expect(html).not.toContain("%DPH");
|
expect(html).not.toContain("%DPH");
|
||||||
expect(html).not.toContain(">DPH<");
|
expect(html).not.toContain(">DPH<");
|
||||||
@@ -44,14 +44,14 @@ describe("renderOrderConfirmationHtml (order confirmation PDF)", () => {
|
|||||||
// Line total = netto (2 × 100), no VAT-on-top anywhere.
|
// Line total = netto (2 × 100), no VAT-on-top anywhere.
|
||||||
expect(html).toContain('<td class="right total-cell">200,00</td>');
|
expect(html).toContain('<td class="right total-cell">200,00</td>');
|
||||||
expect(html).toContain("Celkem bez DPH");
|
expect(html).toContain("Celkem bez DPH");
|
||||||
expect(html).toContain(CS_NOTE);
|
expect(html).not.toContain(CS_NOTE);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("en: 'Total excl. VAT' + the English notice, no VAT columns", () => {
|
it("en: 'Total excl. VAT', no VAT columns or notice", () => {
|
||||||
const html = renderOrderConfirmationHtml(order, items, null, "en", "Jan");
|
const html = renderOrderConfirmationHtml(order, items, null, "en", "Jan");
|
||||||
expect(html).not.toContain("VAT%");
|
expect(html).not.toContain("VAT%");
|
||||||
expect(html).toContain("Total excl. VAT");
|
expect(html).toContain("Total excl. VAT");
|
||||||
expect(html).toContain(EN_NOTE);
|
expect(html).not.toContain(EN_NOTE);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("excludes not-included lines from the NET total", () => {
|
it("excludes not-included lines from the NET total", () => {
|
||||||
@@ -107,7 +107,7 @@ afterAll(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("GET /api/admin/offers-pdf/:id (offer PDF html)", () => {
|
describe("GET /api/admin/offers-pdf/:id (offer PDF html)", () => {
|
||||||
it("renders NET-only totals with 'Celkem bez DPH' and the cs notice", async () => {
|
it("renders NET-only totals with 'Celkem bez DPH', no notice", async () => {
|
||||||
// Direct prisma insert (explicit number → no sequence consumed).
|
// Direct prisma insert (explicit number → no sequence consumed).
|
||||||
const quotation = await prisma.quotations.create({
|
const quotation = await prisma.quotations.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -139,7 +139,7 @@ describe("GET /api/admin/offers-pdf/:id (offer PDF html)", () => {
|
|||||||
expect(res.statusCode).toBe(200);
|
expect(res.statusCode).toBe(200);
|
||||||
const html = res.body;
|
const html = res.body;
|
||||||
expect(html).toContain("Celkem bez DPH");
|
expect(html).toContain("Celkem bez DPH");
|
||||||
expect(html).toContain(CS_NOTE);
|
expect(html).not.toContain(CS_NOTE);
|
||||||
expect(html).not.toContain("%DPH");
|
expect(html).not.toContain("%DPH");
|
||||||
expect(html).not.toContain("Mezisoučet");
|
expect(html).not.toContain("Mezisoučet");
|
||||||
expect(html).not.toContain("Celkem k úhradě");
|
expect(html).not.toContain("Celkem k úhradě");
|
||||||
@@ -203,8 +203,6 @@ const translations: Record<Lang, Record<string, string>> = {
|
|||||||
col_total: "Celkem",
|
col_total: "Celkem",
|
||||||
total_no_vat: "Celkem bez DPH",
|
total_no_vat: "Celkem bez DPH",
|
||||||
amounts_in: "Částky jsou uvedeny v",
|
amounts_in: "Částky jsou uvedeny v",
|
||||||
vat_notice:
|
|
||||||
"Ceny jsou uvedeny bez DPH. DPH bude účtováno dle platných předpisů.",
|
|
||||||
notes: "Poznámky",
|
notes: "Poznámky",
|
||||||
delivery_terms: "Dodací podmínky:",
|
delivery_terms: "Dodací podmínky:",
|
||||||
payment_terms: "Platební podmínky:",
|
payment_terms: "Platební podmínky:",
|
||||||
@@ -227,8 +225,6 @@ const translations: Record<Lang, Record<string, string>> = {
|
|||||||
col_total: "Total",
|
col_total: "Total",
|
||||||
total_no_vat: "Total excl. VAT",
|
total_no_vat: "Total excl. VAT",
|
||||||
amounts_in: "Amounts are in",
|
amounts_in: "Amounts are in",
|
||||||
vat_notice:
|
|
||||||
"Prices are exclusive of VAT. VAT will be charged according to applicable regulations.",
|
|
||||||
notes: "Notes",
|
notes: "Notes",
|
||||||
delivery_terms: "Delivery terms:",
|
delivery_terms: "Delivery terms:",
|
||||||
payment_terms: "Payment terms:",
|
payment_terms: "Payment terms:",
|
||||||
@@ -593,12 +589,6 @@ export function renderIssuedOrderHtml(
|
|||||||
color: #1a1a1a;
|
color: #1a1a1a;
|
||||||
margin-top: 2mm;
|
margin-top: 2mm;
|
||||||
}
|
}
|
||||||
.totals .vat-note {
|
|
||||||
text-align: right;
|
|
||||||
font-size: 8pt;
|
|
||||||
color: #646464;
|
|
||||||
margin-top: 1mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dodaci / platebni podminky (PO-specificke) */
|
/* Dodaci / platebni podminky (PO-specificke) */
|
||||||
.terms {
|
.terms {
|
||||||
@@ -751,7 +741,6 @@ ${indentCSS}
|
|||||||
<span class="value">${formatNum(total)} ${escapeHtml(currency)}</span>
|
<span class="value">${formatNum(total)} ${escapeHtml(currency)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="currency-note">${escapeHtml(t.amounts_in)} ${escapeHtml(currency)}</div>
|
<div class="currency-note">${escapeHtml(t.amounts_in)} ${escapeHtml(currency)}</div>
|
||||||
<div class="vat-note">${escapeHtml(t.vat_notice)}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -204,10 +204,6 @@ const TRANSLATIONS: Record<string, Record<string, string>> = {
|
|||||||
included: { EN: "Included", CZ: "Zahrnuto" },
|
included: { EN: "Included", CZ: "Zahrnuto" },
|
||||||
total: { EN: "Total", CZ: "Celkem" },
|
total: { EN: "Total", CZ: "Celkem" },
|
||||||
total_no_vat: { EN: "Total excl. VAT", CZ: "Celkem bez DPH" },
|
total_no_vat: { EN: "Total excl. VAT", CZ: "Celkem bez DPH" },
|
||||||
vat_notice: {
|
|
||||||
EN: "Prices are exclusive of VAT. VAT will be charged according to applicable regulations.",
|
|
||||||
CZ: "Ceny jsou uvedeny bez DPH. DPH bude \u00FA\u010Dtov\u00E1no dle platn\u00FDch p\u0159edpis\u016F.",
|
|
||||||
},
|
|
||||||
ico: { EN: "ID", CZ: "I\u010CO" },
|
ico: { EN: "ID", CZ: "I\u010CO" },
|
||||||
dic: { EN: "VAT ID", CZ: "DI\u010C" },
|
dic: { EN: "VAT ID", CZ: "DI\u010C" },
|
||||||
page: { EN: "Page", CZ: "Strana" },
|
page: { EN: "Page", CZ: "Strana" },
|
||||||
@@ -321,8 +317,7 @@ export default async function offersPdfRoutes(
|
|||||||
const totalsHtml = `<div class="grand">
|
const totalsHtml = `<div class="grand">
|
||||||
<span class="label">${escapeHtml(t("total_no_vat"))}</span>
|
<span class="label">${escapeHtml(t("total_no_vat"))}</span>
|
||||||
<span class="value">${formatCurrency(total, currency)}</span>
|
<span class="value">${formatCurrency(total, currency)}</span>
|
||||||
</div>
|
</div>`;
|
||||||
<div class="vat-note">${escapeHtml(t("vat_notice"))}</div>`;
|
|
||||||
const quotationNumber = escapeHtml(quotation.quotation_number);
|
const quotationNumber = escapeHtml(quotation.quotation_number);
|
||||||
|
|
||||||
let scopeHtml = "";
|
let scopeHtml = "";
|
||||||
@@ -566,12 +561,6 @@ ${indentCSS}
|
|||||||
border-bottom: 2.5pt solid #de3a3a;
|
border-bottom: 2.5pt solid #de3a3a;
|
||||||
padding-bottom: 1mm;
|
padding-bottom: 1mm;
|
||||||
}
|
}
|
||||||
.totals .vat-note {
|
|
||||||
text-align: right;
|
|
||||||
font-size: 8pt;
|
|
||||||
color: #646464;
|
|
||||||
margin-top: 2mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Scope sections ---- */
|
/* ---- Scope sections ---- */
|
||||||
.scope-page {
|
.scope-page {
|
||||||
|
|||||||
@@ -194,8 +194,6 @@ const translations: Record<string, Record<string, string>> = {
|
|||||||
col_total: "Celkem",
|
col_total: "Celkem",
|
||||||
total_no_vat: "Celkem bez DPH",
|
total_no_vat: "Celkem bez DPH",
|
||||||
amounts_in: "Částky jsou uvedeny v",
|
amounts_in: "Částky jsou uvedeny v",
|
||||||
vat_notice:
|
|
||||||
"Ceny jsou uvedeny bez DPH. DPH bude účtováno dle platných předpisů.",
|
|
||||||
notes: "Poznámky",
|
notes: "Poznámky",
|
||||||
issued_by: "Vystavil:",
|
issued_by: "Vystavil:",
|
||||||
received_by: "Převzal:",
|
received_by: "Převzal:",
|
||||||
@@ -219,8 +217,6 @@ const translations: Record<string, Record<string, string>> = {
|
|||||||
col_total: "Total",
|
col_total: "Total",
|
||||||
total_no_vat: "Total excl. VAT",
|
total_no_vat: "Total excl. VAT",
|
||||||
amounts_in: "Amounts are in",
|
amounts_in: "Amounts are in",
|
||||||
vat_notice:
|
|
||||||
"Prices are exclusive of VAT. VAT will be charged according to applicable regulations.",
|
|
||||||
notes: "Notes",
|
notes: "Notes",
|
||||||
issued_by: "Issued by:",
|
issued_by: "Issued by:",
|
||||||
received_by: "Received by:",
|
received_by: "Received by:",
|
||||||
@@ -573,12 +569,6 @@ export function renderOrderConfirmationHtml(
|
|||||||
color: #1a1a1a;
|
color: #1a1a1a;
|
||||||
margin-top: 2mm;
|
margin-top: 2mm;
|
||||||
}
|
}
|
||||||
.totals .vat-note {
|
|
||||||
text-align: right;
|
|
||||||
font-size: 8pt;
|
|
||||||
color: #646464;
|
|
||||||
margin-top: 1mm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Vystavil */
|
/* Vystavil */
|
||||||
.issued-by {
|
.issued-by {
|
||||||
@@ -736,7 +726,6 @@ ${indentCSS}
|
|||||||
<span class="value">${formatNum(total)} ${escapeHtml(currency)}</span>
|
<span class="value">${formatNum(total)} ${escapeHtml(currency)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="currency-note">${escapeHtml(t.amounts_in)} ${escapeHtml(currency)}</div>
|
<div class="currency-note">${escapeHtml(t.amounts_in)} ${escapeHtml(currency)}</div>
|
||||||
<div class="vat-note">${escapeHtml(t.vat_notice)}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user