Fix invoice-image code-review findings: aspect ratio, whitelist config, stale refs
- MigraDocExtensions: fix a bug where capping an oversized explicit width+height image re-derived the other dimension from the image's native pixel ratio instead of scaling both sides uniformly, silently distorting a deliberately non-native-ratio (e.g. stretched) image. - InvoiceService: derive the mfr-portal image whitelist prefix from the existing Fds:MFR_host config setting (via MFRClientConfig.RestRoot) instead of a second hardcoded literal, so it can't drift from the actual configured host; parse <img> sources with HtmlAgilityPack (already used by the PDF's own HTML converter) instead of a regex, so a decoy attribute like data-src can't be picked up in place of the real src; dedup fetch URLs with a HashSet instead of O(n^2) List scanning; reuse FuchsPdf.MigraDocFilenameFromByteArray instead of re-spelling the "base64:" prefix. - Fix a stale log message and comment left over from the GenerateInvoicePdf -> GenerateInvoicePdfAsync rename, and update INVOICE_LIFECYCLE.md's references to the old sync method name. - Add tests for the config-derived whitelist, a decoy-attribute src, and the 20-image-per-invoice fetch cap boundary. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -116,7 +116,7 @@ vat }` plus set header/member tagging) that is posted to the server.
|
||||
| User action | JS entry point | Endpoint | Controller handler | Effect |
|
||||
|---|---|---|---|---|
|
||||
| First save without preview | `$inv.ssave` | `req/save` | `Do_Process_Requests` case `save` | `RegisterInvoiceAsync(change: id present)` — creates or updates the draft row, **no PDF rendered** |
|
||||
| Preview a **new** invoice | `$inv.sprev(false)` | `req/sprep` | case `sprep` | Registers draft, then `GenerateInvoicePdf` → renders preview images |
|
||||
| Preview a **new** invoice | `$inv.sprev(false)` | `req/sprep` | case `sprep` | Registers draft, then `GenerateInvoicePdfAsync` → renders preview images |
|
||||
| Preview an **existing** draft | `$inv.sprev(true)` (aka `$inv.sedit`) | `req/sedit` | case `sedit` | Same as `sprep` but requires `id`, updates existing draft |
|
||||
| Cancel out of preview | dialog `cancel` handler | `req/sdel` | case `sdel` | `fds__remInvoice` — deletes the (unfinalised) draft row |
|
||||
|
||||
@@ -134,7 +134,8 @@ JSON into SQL parameters and calls, in one batch:
|
||||
- **Existing draft**: `fds__setInvoice` (same parameter set, updates in place)
|
||||
→ `fds__createInvoice_Details` again.
|
||||
|
||||
`GenerateInvoicePdf` (still in `InvoiceService`) builds `FuchsPdf.FdsTextBlocks`
|
||||
`GenerateInvoicePdfAsync` (still in `InvoiceService`) builds `FuchsPdf.FdsTextBlocks`,
|
||||
resolves any whitelisted mfr-portal images from the line-item text (ADR 0018),
|
||||
and calls `IPdfService.WriteLetterAsync` + `ApplyInvoice`, which internally
|
||||
uses `InvoiceSetPricing.Build(...)` to turn the posted item contract into
|
||||
ordered, priced/unpriced lines. While the invoice is **not yet final**
|
||||
@@ -160,7 +161,7 @@ sequenceDiagram
|
||||
C->>S: RegisterInvoiceAsync(invoice, change, invId)
|
||||
S->>DB: fds__createInvoice / fds__setInvoice + fds__createInvoice_Details
|
||||
DB-->>S: registered invoice row (Id, ...)
|
||||
S->>S: GenerateInvoicePdf (draft=true -> watermark, no GiroCode)
|
||||
S->>S: GenerateInvoicePdfAsync (draft=true -> watermark, no GiroCode)
|
||||
S-->>C: MigraDoc Document
|
||||
C-->>JS: {id, img[] (base64 pages), total}
|
||||
JS->>U: show PDF preview modal (confirm / cancel)
|
||||
|
||||
Reference in New Issue
Block a user