- feat: manual VAT override in order confirmation modal
- feat: order confirmation PDF respects user-selected applyVat toggle

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-04-23 18:17:20 +02:00
parent 07cb428287
commit 5a28f75303
4 changed files with 44 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "app-ts", "name": "app-ts",
"version": "1.5.2", "version": "1.5.3",
"description": "", "description": "",
"main": "dist/server.js", "main": "dist/server.js",
"scripts": { "scripts": {

View File

@@ -13,10 +13,15 @@ interface ConfirmationItem {
interface OrderConfirmationModalProps { interface OrderConfirmationModalProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onGenerate: (lang: string, items?: ConfirmationItem[]) => Promise<void>; onGenerate: (
lang: string,
applyVat: boolean,
items?: ConfirmationItem[],
) => Promise<void>;
initialItems: ConfirmationItem[]; initialItems: ConfirmationItem[];
orderNumber: string; orderNumber: string;
defaultVatRate: number; defaultVatRate: number;
applyVat: boolean;
} }
export default function OrderConfirmationModal({ export default function OrderConfirmationModal({
@@ -26,16 +31,18 @@ export default function OrderConfirmationModal({
initialItems, initialItems,
orderNumber, orderNumber,
defaultVatRate, defaultVatRate,
applyVat,
}: OrderConfirmationModalProps) { }: OrderConfirmationModalProps) {
const [step, setStep] = useState<"choose" | "edit">("choose"); const [step, setStep] = useState<"choose" | "edit">("choose");
const [lang, setLang] = useState<string>("cs"); const [lang, setLang] = useState<string>("cs");
const [applyVatState, setApplyVatState] = useState(applyVat);
const [items, setItems] = useState<ConfirmationItem[]>(initialItems); const [items, setItems] = useState<ConfirmationItem[]>(initialItems);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const handleUseExisting = async () => { const handleUseExisting = async () => {
setLoading(true); setLoading(true);
try { try {
await onGenerate(lang, undefined); await onGenerate(lang, applyVatState, undefined);
} finally { } finally {
setLoading(false); setLoading(false);
setStep("choose"); setStep("choose");
@@ -46,7 +53,7 @@ export default function OrderConfirmationModal({
const handleEditGenerate = async () => { const handleEditGenerate = async () => {
setLoading(true); setLoading(true);
try { try {
await onGenerate(lang, items); await onGenerate(lang, applyVatState, items);
} finally { } finally {
setLoading(false); setLoading(false);
setStep("choose"); setStep("choose");
@@ -144,6 +151,34 @@ export default function OrderConfirmationModal({
</div> </div>
</div> </div>
<div className="admin-form-group">
<label className="admin-form-label">DPH</label>
<div className="flex-row gap-2">
<button
type="button"
onClick={() => setApplyVatState(true)}
className={
applyVatState
? "admin-btn admin-btn-primary admin-btn-sm"
: "admin-btn admin-btn-secondary admin-btn-sm"
}
>
S DPH
</button>
<button
type="button"
onClick={() => setApplyVatState(false)}
className={
!applyVatState
? "admin-btn admin-btn-primary admin-btn-sm"
: "admin-btn admin-btn-secondary admin-btn-sm"
}
>
Bez DPH
</button>
</div>
</div>
<div className="admin-form-group"> <div className="admin-form-group">
<label className="admin-form-label">Obsah potvrzení</label> <label className="admin-form-label">Obsah potvrzení</label>
<p <p

View File

@@ -231,6 +231,7 @@ export default function OrderDetail() {
const handleGenerateConfirmation = async ( const handleGenerateConfirmation = async (
lang: string, lang: string,
applyVat: boolean,
customItems?: Array<{ customItems?: Array<{
description: string; description: string;
quantity: number; quantity: number;
@@ -247,7 +248,7 @@ export default function OrderDetail() {
{ {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ lang, items: customItems }), body: JSON.stringify({ lang, applyVat, items: customItems }),
}, },
); );
if (!response.ok) { if (!response.ok) {
@@ -846,6 +847,7 @@ export default function OrderDetail() {
}))} }))}
orderNumber={order.order_number} orderNumber={order.order_number}
defaultVatRate={Number(order.vat_rate) || 21} defaultVatRate={Number(order.vat_rate) || 21}
applyVat={!!order.apply_vat}
/> />
)} )}
</div> </div>

View File

@@ -250,7 +250,8 @@ export default async function ordersPdfRoutes(
} }
const currency = order.currency || "CZK"; const currency = order.currency || "CZK";
const applyVat = !!order.apply_vat; const applyVat =
body.applyVat !== undefined ? !!body.applyVat : !!order.apply_vat;
const orderVatRate = Number(order.vat_rate) || 21; const orderVatRate = Number(order.vat_rate) || 21;
// Use custom items from body if provided, otherwise order items // Use custom items from body if provided, otherwise order items