chore(release): v2.4.35 — lint cleanup (68→0) + duplicate-Zavřít modal fix
UI fix:
- Close-only modals showing a redundant second close button now use
hideCancel: ReceivedInvoices paid-detail modal (was two identical "Zavřít"
buttons) and PlanCellModal "Den je součástí rozsahu".
- Add modal-duplicate-close test enforcing close-only modals set hideCancel.
Lint: cleared all 68 warnings → 0.
- preserve-caught-error: attach { cause } in ai.service / exchange-rates.
- no-require-imports: package.json version read via fs (APP_VERSION) instead
of require(), avoiding a rootDir-expanding static JSON import.
- react-hooks/exhaustive-deps (11): ref-in-cleanup copies, derived-value
useMemo wrapping, PlanGrid field extraction, stable nextKey useCallback,
AuthContext documented cycle-break.
- no-explicit-any (53): precise route param/Prisma types, generic enrich*()
preserving payload shape, minimal vite module type, frontend body/query-key
types, SystemInfo for Settings.
Refactor (test enablement): shift-form types moved to dependency-free
shiftFormTypes.ts so the print-HTML builders are unit-testable without the
component graph; characterization test pins their output.
Gates: 649 tests pass, tsc -b clean, lint 0. Verified touched flows live
via Playwright (PlanWork CRUD + optimistic cache, warehouse form keys,
Settings system info, invoice detail).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,11 +79,36 @@ async function syncProjectStatus(
|
||||
// silently 0 in the per-currency totals.
|
||||
//
|
||||
// Orders are NOT tax documents — totals are NET only (no VAT anywhere).
|
||||
function enrichOrder(o: any) {
|
||||
// Structural shape for enrichOrder — like enrichQuotation it runs over several
|
||||
// different selects (full include vs. the minimal totals select), so only the
|
||||
// fields actually read are pinned; everything else is spread through.
|
||||
type EnrichableLineItem = {
|
||||
is_included_in_total?: unknown;
|
||||
quantity?: unknown;
|
||||
unit_price?: unknown;
|
||||
};
|
||||
type EnrichableOrder = {
|
||||
order_items: EnrichableLineItem[];
|
||||
order_sections?: unknown;
|
||||
invoices?: Array<{
|
||||
id?: number | null;
|
||||
invoice_number?: string | null;
|
||||
}> | null;
|
||||
customers?: { name?: string | null } | null;
|
||||
quotations?: {
|
||||
quotation_number?: string | null;
|
||||
project_code?: string | null;
|
||||
} | null;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
// Generic over the concrete payload so `...rest` keeps every field the caller's
|
||||
// select actually returned (the return type must stay as rich as the input).
|
||||
function enrichOrder<T extends EnrichableOrder>(o: T) {
|
||||
const total = o.order_items
|
||||
.filter((i: any) => i.is_included_in_total !== false)
|
||||
.filter((i) => i.is_included_in_total !== false)
|
||||
.reduce(
|
||||
(s: number, i: any) =>
|
||||
(s: number, i) =>
|
||||
s + (Number(i.quantity) || 0) * (Number(i.unit_price) || 0),
|
||||
0,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user