From 10f96073ece4e227f21996b9aca598ae93f8a83a Mon Sep 17 00:00:00 2001 From: Louis Choquel Date: Sat, 7 Nov 2026 18:14:24 +0100 Subject: [PATCH 1/3] invoice_extraction returns its currency and its line items Each Invoice gains currency, an ISO 4217 code read from the document and left empty when the document does not determine it, and line_items, a list of the new InvoiceLineItem concept (label, quantity, unit_price, amount). description becomes a one-line summary and vat_rates are stated as percentages. The package gets a README describing its output. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019TF9N18ABj9hxXJX1vChAU --- CHANGELOG.md | 10 +++ README.md | 2 +- methods/invoice_extraction/README.md | 78 +++++++++++++++++++ .../invoice_extraction.mthds | 29 +++++-- 4 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 methods/invoice_extraction/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index eceaf4c..77efe29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [Unreleased] + +### Added + +- **`invoice_extraction` returns the currency and the line items**: each `Invoice` gains `currency`, the ISO 4217 code its amounts are expressed in, read from the document and left empty when the document does not determine it, and `line_items`, a list of the new `InvoiceLineItem` concept (`label`, `quantity`, `unit_price`, `amount`) holding every priced line in the order printed, fees and discounts included and the subtotal, tax, total and payment lines never. `description` becomes a one-line summary of the purchase, and every existing field keeps its name and its type, so a caller moving its address from `v0.2.0` keeps working. + +### Changed + +- **`invoice_extraction` states `vat_rates` as percentages**: a rate of 20 % reads `20`, where the field's description previously left the model free to answer `0.2`. + ## [v0.2.0] - 2026-10-16 ### Changed diff --git a/README.md b/README.md index 07e3744..c97a4c4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This repository is the public library of packaged [MTHDS](https://mthds.ai) meth | [`documents`](methods/documents/) | Document extraction toolbox: text pages, markdown pages, page contents with images and page views, single-text concatenation | `extract_document_markdown` | | [`doc_summarizer`](methods/doc_summarizer/) | Deep document summarization: profile the document and extract importance-ranked key points in parallel, then synthesize a structured summary with themes and open questions | `summarize_document` | | [`cv_analyzer`](methods/cv_analyzer/) | End-to-end candidate screening: match a CV against a job offer, then generate tailored interview questions or draft a courteous refusal email | `screen_candidate` | -| [`invoice_extraction`](methods/invoice_extraction/) | Classify each page as bill or receipt, then extract structured invoice data (amounts, VAT, vendor, buyer) from OCR text and page views | `process_invoice` | +| [`invoice_extraction`](methods/invoice_extraction/) | Classify each page as bill or receipt, then extract structured invoice data (amounts with their currency, VAT, vendor, buyer and the purchase line by line) from OCR text and page views | `process_invoice` | | [`table_extraction`](methods/table_extraction/) | Turn a screenshot of a table into faithful HTML, with a vision review pass to correct text and formatting | `extract_html_table_and_review` | | [`slide_designer`](methods/slide_designer/) | Turn a rough slide-deck brief into design proposals: multiple visual themes, a rendered mockup image for each, and an HTML report presenting them all | `generate_design_proposals_from_rough_brief` | | [`image_generation`](methods/image_generation/) | Generate images from text: render a description directly, or refine it into an optimized image prompt first | `illustrate` | diff --git a/methods/invoice_extraction/README.md b/methods/invoice_extraction/README.md new file mode 100644 index 0000000..b7a19ac --- /dev/null +++ b/methods/invoice_extraction/README.md @@ -0,0 +1,78 @@ +# Invoice Extraction + +`invoice_extraction` reads a document holding invoices or receipts and returns what each page says: the vendor and the buyer, the dates, the totals and the tax, the currency the amounts are in, and the purchase line by line. It works from both the text extracted from each page and a picture of the page, so a scanned receipt reads as well as a generated PDF. + +``` +github.com/Pipelex/methods/invoice_extraction +``` + +## What it takes + +`process_invoice`, the package's entry pipe, takes one input: + +| Input | Concept | What to give | +|---|---|---| +| `document` | `Document` | A PDF or an image of one or more invoices or receipts. | + +The sample [`inputs.json`](inputs.json) points at a scanned take-out receipt. + +## What it returns + +A list of `Invoice`, **one per page** of the document. Each page is first classified as a formal bill or a simple receipt, then read on its own, so an invoice whose lines run over two pages comes back as two results, each carrying that page's lines. + +### `Invoice` + +| Field | Type | Meaning | +|---|---|---| +| `invoice_id` | text | A unique identifier for the invoice. | +| `invoice_number` | text | The invoice number as shown on the document. | +| `issue_date` | date | The date the invoice was issued. | +| `time` | text | The time of the transaction, when the document prints one. | +| `amount_incl_tax` | number | The total including taxes, in `currency`. | +| `amount_excl_tax` | number | The net amount excluding taxes, in `currency`. | +| `vat_amount` | number | The total VAT or tax amount, in `currency`. | +| `currency` | text | The ISO 4217 code of the currency every amount is expressed in, such as `EUR` or `USD`. Empty when the document does not determine it (see below). | +| `vat_rates` | list of numbers | The VAT rates applied, as percentages: `20` for 20 %. | +| `vendor` | text | The vendor's name. | +| `vendor_address` | text | The vendor's address. | +| `vendor_siret` | text | The vendor's SIRET number, for a French company. | +| `vendor_vat_number` | text | The vendor's VAT registration number. | +| `company_name` | text | The purchasing company's name. | +| `company_address` | text | The purchasing company's address. | +| `description` | text | A one-line summary of what was purchased. | +| `line_items` | list of `InvoiceLineItem` | The priced lines of the invoice, in the order printed (see below). | +| `category` | `InvoiceDetails` | Whether the page is a `bill` or a `receipt`, with the reason. | +| `text` | text | The raw text extracted from the page. | + +Every field may be empty when the page does not show it. + +### `InvoiceLineItem` + +| Field | Type | Meaning | +|---|---|---| +| `label` | text | What the line is for, as printed: the product, service, fee or discount. Always present. | +| `quantity` | number | How many units, or how much, as printed. Fractional for a weighed or measured item. Empty when the line prints no quantity. | +| `unit_price` | number | The price of one unit, in `currency`, when the line prints it. | +| `amount` | number | The line's total, in `currency`, as printed. Negative for a discount or a refund. | + +## How the currency is determined + +The method reads the currency from the document and never assumes one. It takes, in this order: + +1. a currency code printed on the document, such as `EUR` or `CHF`; +2. otherwise, a symbol that names one currency only, such as `€` or `£`; +3. otherwise, for a symbol several currencies share, such as `$`, `¥` or `kr`, where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header, its phone number's format, its tax identifiers or the name its tax goes by. + +When none of these settles it, `currency` stays empty: a missing currency is safer to display than a wrong one. A document is read as expressed in one currency; a second currency on it, such as a converted total, is not represented. + +## Which lines are line items + +Every priced line of the itemized part of the document, in the order printed, including fees, deposits, surcharges, shipping and discounts. The subtotal, tax, total, payment, tender and change lines are never line items: the totals and the tax are the invoice's own amounts, and the payment lines describe how it was paid rather than what was bought. A line's values are taken as printed and never recomputed, so a line that prints no unit price has none, and line amounts are before or after tax exactly as the document itemizes them. + +## Running it + +```bash +pipelex run bundle methods/invoice_extraction -i methods/invoice_extraction/inputs.json +``` + +Or by its address on the hosted API, pinned to a library tag, as the [library's README](../../README.md#running-a-method-by-address) describes. diff --git a/methods/invoice_extraction/invoice_extraction.mthds b/methods/invoice_extraction/invoice_extraction.mthds index 0e2dbcc..a7b56ad 100644 --- a/methods/invoice_extraction/invoice_extraction.mthds +++ b/methods/invoice_extraction/invoice_extraction.mthds @@ -12,6 +12,15 @@ category = { type = "text", description = "The category of the invoice", choices ] } explanation = { type = "text", description = "Explanation of the classification" } +[concept.InvoiceLineItem] +description = "One priced line of an invoice or a receipt, as printed: a product, a service, a fee or a discount" + +[concept.InvoiceLineItem.structure] +label = { type = "text", description = "What the line is for, as printed: the product, service, fee or discount", required = true } +quantity = { type = "number", description = "How many units, or how much, as printed; may be fractional for a weighed or measured item. Empty when the line prints no quantity" } +unit_price = { type = "number", description = "Price of one unit, in the invoice's currency, when the line prints it" } +amount = { type = "number", description = "Total of the line, in the invoice's currency, as printed; negative for a discount or a refund" } + [concept.Invoice] description = "Invoice information extracted from text, supporting both formal bills and receipts" @@ -20,17 +29,19 @@ invoice_id = { type = "text", description = "Unique identifier for the in invoice_number = { type = "text", description = "Invoice number as shown on the document" } issue_date = { type = "date", description = "Date when the invoice was issued" } time = { type = "text", description = "Time of the transaction if available" } -amount_incl_tax = { type = "number", description = "Total amount including taxes" } -amount_excl_tax = { type = "number", description = "Net amount excluding taxes" } -vat_amount = { type = "number", description = "Total VAT/tax amount" } -vat_rates = { type = "list", item_type = "number", description = "List of VAT rates applied" } +amount_incl_tax = { type = "number", description = "Total amount including taxes, in the invoice's currency" } +amount_excl_tax = { type = "number", description = "Net amount excluding taxes, in the invoice's currency" } +vat_amount = { type = "number", description = "Total VAT or tax amount, in the invoice's currency" } +currency = { type = "text", description = "ISO 4217 code of the currency every amount on the invoice is expressed in, three uppercase letters such as EUR, USD or GBP. Empty when the document does not determine it" } +vat_rates = { type = "list", item_type = "number", description = "VAT rates applied, as percentages: 20 for 20 %" } vendor = { type = "text", description = "Name of the vendor/seller" } vendor_address = { type = "text", description = "Complete address of the vendor" } vendor_siret = { type = "text", description = "SIRET number of the vendor (French company registration)" } vendor_vat_number = { type = "text", description = "VAT registration number of the vendor" } company_name = { type = "text", description = "Name of the purchasing company" } company_address = { type = "text", description = "Address of the purchasing company" } -description = { type = "text", description = "Description of goods or services purchased" } +description = { type = "text", description = "One-line summary of what was purchased; the purchase line by line is in line_items" } +line_items = { type = "list", item_type = "concept", item_concept_ref = "invoice_extraction.InvoiceLineItem", description = "The priced lines of the invoice, in the order printed, fees and discounts included; never the subtotal, tax, total or payment lines" } category = { type = "concept", concept_ref = "invoice_extraction.InvoiceDetails", description = "Category or type of expense" } text = { type = "text", description = "Raw text extracted from the invoice" } @@ -80,7 +91,13 @@ inputs = { invoice_details = "InvoiceDetails", invoice_page = "Page" } output = "Invoice" model = "$vision" prompt = """ -Extract invoice information from this invoice: +Extract invoice information from this invoice. + +Currency: give the ISO 4217 code of the currency the amounts are expressed in. Take it from a currency code printed on the document; otherwise from a symbol that names one currency only, such as € or £; otherwise, for a symbol several currencies share, such as the dollar sign, the yen sign or kr, from where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header (an airport, a station), its phone number's format, its tax identifiers or the name its tax goes by. When nothing on the document settles it, leave the currency empty rather than guess. + +Line items: list every priced line of the itemized part of the document, in the order printed, including fees, deposits, surcharges, shipping and discounts, a discount or a refund having a negative amount. Never list the subtotal, tax, total, payment, tender or change lines. Take each line's quantity, unit price and amount as printed, leave out what the line does not print, and never compute a value the document does not show. + +Description: summarize what was purchased in one line, without listing the items. The category of this invoice is: $invoice_details.category. From f4d86a08d413bb84a10f7fb19b3d4c3c8c517f0c Mon Sep 17 00:00:00 2001 From: Louis Choquel Date: Sat, 7 Nov 2026 18:23:38 +0100 Subject: [PATCH 2/3] invoice_extraction: a surcharge below the subtotal is a line item, and the pound sign is a shared symbol Line items are every priced line wherever it is printed, a fee or surcharge in the totals block included, never a per-category subtotal. The pound sign is shared by sterling and the Gibraltar, Falklands, Saint Helena, Egyptian, Lebanese, Syrian and Sudanese pounds, so it is resolved by where the document was issued; the rupee sign takes its place as a one-currency example. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019TF9N18ABj9hxXJX1vChAU --- methods/invoice_extraction/README.md | 6 +++--- methods/invoice_extraction/invoice_extraction.mthds | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/methods/invoice_extraction/README.md b/methods/invoice_extraction/README.md index b7a19ac..1c253ac 100644 --- a/methods/invoice_extraction/README.md +++ b/methods/invoice_extraction/README.md @@ -60,14 +60,14 @@ Every field may be empty when the page does not show it. The method reads the currency from the document and never assumes one. It takes, in this order: 1. a currency code printed on the document, such as `EUR` or `CHF`; -2. otherwise, a symbol that names one currency only, such as `€` or `£`; -3. otherwise, for a symbol several currencies share, such as `$`, `¥` or `kr`, where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header, its phone number's format, its tax identifiers or the name its tax goes by. +2. otherwise, a symbol that names one currency only, such as `€` or `₹`; +3. otherwise, for a symbol several currencies share, such as `$`, `£`, `¥` or `kr`, where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header, its phone number's format, its tax identifiers or the name its tax goes by. When none of these settles it, `currency` stays empty: a missing currency is safer to display than a wrong one. A document is read as expressed in one currency; a second currency on it, such as a converted total, is not represented. ## Which lines are line items -Every priced line of the itemized part of the document, in the order printed, including fees, deposits, surcharges, shipping and discounts. The subtotal, tax, total, payment, tender and change lines are never line items: the totals and the tax are the invoice's own amounts, and the payment lines describe how it was paid rather than what was bought. A line's values are taken as printed and never recomputed, so a line that prints no unit price has none, and line amounts are before or after tax exactly as the document itemizes them. +Every priced line of the document, in the order printed: each product or service, and each fee, deposit, surcharge, shipping charge or discount wherever it is printed, a surcharge below the subtotal included. The subtotal, tax, total, payment, tender and change lines are never line items, and neither is a line that only sums lines already listed, such as a subtotal per category: the totals and the tax are the invoice's own amounts, and the payment lines describe how it was paid rather than what was bought. A line's values are taken as printed and never recomputed, so a line that prints no unit price has none, and line amounts are before or after tax exactly as the document itemizes them. ## Running it diff --git a/methods/invoice_extraction/invoice_extraction.mthds b/methods/invoice_extraction/invoice_extraction.mthds index a7b56ad..713ff23 100644 --- a/methods/invoice_extraction/invoice_extraction.mthds +++ b/methods/invoice_extraction/invoice_extraction.mthds @@ -93,9 +93,9 @@ model = "$vision" prompt = """ Extract invoice information from this invoice. -Currency: give the ISO 4217 code of the currency the amounts are expressed in. Take it from a currency code printed on the document; otherwise from a symbol that names one currency only, such as € or £; otherwise, for a symbol several currencies share, such as the dollar sign, the yen sign or kr, from where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header (an airport, a station), its phone number's format, its tax identifiers or the name its tax goes by. When nothing on the document settles it, leave the currency empty rather than guess. +Currency: give the ISO 4217 code of the currency the amounts are expressed in. Take it from a currency code printed on the document; otherwise from a symbol that names one currency only, such as € or ₹; otherwise, for a symbol several currencies share, such as the dollar sign, the pound sign, the yen sign or kr, from where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header (an airport, a station), its phone number's format, its tax identifiers or the name its tax goes by. When nothing on the document settles it, leave the currency empty rather than guess. -Line items: list every priced line of the itemized part of the document, in the order printed, including fees, deposits, surcharges, shipping and discounts, a discount or a refund having a negative amount. Never list the subtotal, tax, total, payment, tender or change lines. Take each line's quantity, unit price and amount as printed, leave out what the line does not print, and never compute a value the document does not show. +Line items: list every priced line of the document, in the order printed: each product or service, and each fee, deposit, surcharge, shipping charge or discount wherever it is printed, below the subtotal included, a discount or a refund having a negative amount. Never list the subtotal, tax, total, payment, tender or change lines, nor a line that only sums lines already listed, such as a subtotal per category. Take each line's quantity, unit price and amount as printed, leave out what the line does not print, and never compute a value the document does not show. Description: summarize what was purchased in one line, without listing the items. From 3f358aad754f6a7029cf1add76f2f7e71b356d60 Mon Sep 17 00:00:00 2001 From: Louis Choquel Date: Sat, 7 Nov 2026 18:35:20 +0100 Subject: [PATCH 3/3] Read the currency from the invoice's own amounts, and mark vat_rates breaking The currency rule took any currency code printed on the document first, so a converted total or a card slip in the cardholder's currency could name the currency of amounts expressed in another. The prompt, the field description and the package README now read the currency only from what qualifies the invoice's totals and lines, and leave it empty when those are themselves in more than one currency. The vat_rates change turns a fraction a caller may have received into a percentage, which breaks a caller that computes with it, so the changelog marks it breaking and says what such a caller must do. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019TF9N18ABj9hxXJX1vChAU --- CHANGELOG.md | 4 ++-- methods/invoice_extraction/README.md | 10 +++++----- methods/invoice_extraction/invoice_extraction.mthds | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77efe29..c61aa2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,11 @@ ### Added -- **`invoice_extraction` returns the currency and the line items**: each `Invoice` gains `currency`, the ISO 4217 code its amounts are expressed in, read from the document and left empty when the document does not determine it, and `line_items`, a list of the new `InvoiceLineItem` concept (`label`, `quantity`, `unit_price`, `amount`) holding every priced line in the order printed, fees and discounts included and the subtotal, tax, total and payment lines never. `description` becomes a one-line summary of the purchase, and every existing field keeps its name and its type, so a caller moving its address from `v0.2.0` keeps working. +- **`invoice_extraction` returns the currency and the line items**: each `Invoice` gains `currency`, the ISO 4217 code its totals and lines are expressed in, read from the document, never taken from a converted amount or a card payment in another currency, and left empty when the document does not determine it, and `line_items`, a list of the new `InvoiceLineItem` concept (`label`, `quantity`, `unit_price`, `amount`) holding every priced line in the order printed, fees and discounts included and the subtotal, tax, total and payment lines never. `description` becomes a one-line summary of the purchase. Every existing field keeps its name and its type. ### Changed -- **`invoice_extraction` states `vat_rates` as percentages**: a rate of 20 % reads `20`, where the field's description previously left the model free to answer `0.2`. +- **`invoice_extraction` states `vat_rates` as percentages (Breaking)**: a rate of 20 % reads `20`, where the field's description previously left the model free to answer `0.2`. A caller that moves its address from `v0.2.0` and computes with a rate as a fraction, multiplying an amount by it, must divide the rate by 100 first, or its tax comes out a hundred times too large. ## [v0.2.0] - 2026-10-16 diff --git a/methods/invoice_extraction/README.md b/methods/invoice_extraction/README.md index 1c253ac..1fd62b1 100644 --- a/methods/invoice_extraction/README.md +++ b/methods/invoice_extraction/README.md @@ -31,7 +31,7 @@ A list of `Invoice`, **one per page** of the document. Each page is first classi | `amount_incl_tax` | number | The total including taxes, in `currency`. | | `amount_excl_tax` | number | The net amount excluding taxes, in `currency`. | | `vat_amount` | number | The total VAT or tax amount, in `currency`. | -| `currency` | text | The ISO 4217 code of the currency every amount is expressed in, such as `EUR` or `USD`. Empty when the document does not determine it (see below). | +| `currency` | text | The ISO 4217 code of the currency the invoice's totals and lines are expressed in, such as `EUR` or `USD`. Empty when the document does not determine it (see below). | | `vat_rates` | list of numbers | The VAT rates applied, as percentages: `20` for 20 %. | | `vendor` | text | The vendor's name. | | `vendor_address` | text | The vendor's address. | @@ -57,13 +57,13 @@ Every field may be empty when the page does not show it. ## How the currency is determined -The method reads the currency from the document and never assumes one. It takes, in this order: +The method reads the currency from the document and never assumes one. It is the currency of the invoice's own amounts, its totals and its lines, and only what qualifies those amounts counts: a converted amount, an exchange rate or a card-payment line printed in another currency, such as a card slip in the cardholder's currency, is ignored. It takes, in this order: -1. a currency code printed on the document, such as `EUR` or `CHF`; -2. otherwise, a symbol that names one currency only, such as `€` or `₹`; +1. a currency code the document gives for those amounts, beside them or in a statement such as "all prices in EUR"; +2. otherwise, a symbol printed with them that names one currency only, such as `€` or `₹`; 3. otherwise, for a symbol several currencies share, such as `$`, `£`, `¥` or `kr`, where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header, its phone number's format, its tax identifiers or the name its tax goes by. -When none of these settles it, `currency` stays empty: a missing currency is safer to display than a wrong one. A document is read as expressed in one currency; a second currency on it, such as a converted total, is not represented. +When none of these settles it, or when the totals and lines are themselves in more than one currency, `currency` stays empty: a missing currency is safer to display than a wrong one. A second currency on the document, such as a converted total, is not represented. ## Which lines are line items diff --git a/methods/invoice_extraction/invoice_extraction.mthds b/methods/invoice_extraction/invoice_extraction.mthds index 713ff23..a75e318 100644 --- a/methods/invoice_extraction/invoice_extraction.mthds +++ b/methods/invoice_extraction/invoice_extraction.mthds @@ -32,7 +32,7 @@ time = { type = "text", description = "Time of the transaction if a amount_incl_tax = { type = "number", description = "Total amount including taxes, in the invoice's currency" } amount_excl_tax = { type = "number", description = "Net amount excluding taxes, in the invoice's currency" } vat_amount = { type = "number", description = "Total VAT or tax amount, in the invoice's currency" } -currency = { type = "text", description = "ISO 4217 code of the currency every amount on the invoice is expressed in, three uppercase letters such as EUR, USD or GBP. Empty when the document does not determine it" } +currency = { type = "text", description = "ISO 4217 code of the currency the invoice's totals and lines are expressed in, three uppercase letters such as EUR, USD or GBP; never the currency of a converted amount or of a card payment in another currency. Empty when the document does not determine it" } vat_rates = { type = "list", item_type = "number", description = "VAT rates applied, as percentages: 20 for 20 %" } vendor = { type = "text", description = "Name of the vendor/seller" } vendor_address = { type = "text", description = "Complete address of the vendor" } @@ -93,7 +93,7 @@ model = "$vision" prompt = """ Extract invoice information from this invoice. -Currency: give the ISO 4217 code of the currency the amounts are expressed in. Take it from a currency code printed on the document; otherwise from a symbol that names one currency only, such as € or ₹; otherwise, for a symbol several currencies share, such as the dollar sign, the pound sign, the yen sign or kr, from where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header (an airport, a station), its phone number's format, its tax identifiers or the name its tax goes by. When nothing on the document settles it, leave the currency empty rather than guess. +Currency: give the ISO 4217 code of the currency the invoice's own amounts are expressed in, its totals and its lines. Read it only from what qualifies those amounts, never from a converted amount, an exchange rate or a card-payment line printed in another currency. Take it from a currency code the document gives for those amounts, beside them or in a statement such as "all prices in EUR"; otherwise from a symbol printed with them that names one currency only, such as € or ₹; otherwise, for a symbol several currencies share, such as the dollar sign, the pound sign, the yen sign or kr, from where the document was issued, as the document itself shows it: the vendor's address, a city or a landmark in its name or header (an airport, a station), its phone number's format, its tax identifiers or the name its tax goes by. When nothing on the document settles it, or when the totals and lines are themselves in more than one currency, leave the currency empty rather than guess. Line items: list every priced line of the document, in the order printed: each product or service, and each fee, deposit, surcharge, shipping charge or discount wherever it is printed, below the subtotal included, a discount or a refund having a negative amount. Never list the subtotal, tax, total, payment, tender or change lines, nor a line that only sums lines already listed, such as a subtotal per category. Take each line's quantity, unit price and amount as printed, leave out what the line does not print, and never compute a value the document does not show.