Parse a multi-line invoice using reusable money, date, and payment-term specifications.
What it shows
- Imports reusable money, date, and payment-term specifications.
InvoiceNumbercombines a letter prefix with an integer sequence.InvoiceHeaderandInvoiceSectionseparate document structure from individual values.Invoicecontains one header and repeated sections.
Try changing Net 30 to Due on Receipt, or Total Amount to Total.
Specs
types/number.yml
Number:
Decimal: '\d+(,\d{3})*\.\d+'
Integer: '\d+(,\d{3})*'types/currency.yml
Currency:
USD: [ 'USD', 'US\$', '\$' ]
EUR: [ 'EUR', '€' ]
GBP: [ 'GBP', '£' ]types/money.yml
$imports: [ 'number', 'currency' ]
$flags: 'OPTIONAL_WHITESPACE'
Money:
$fields:
currency: Currency
amount: Number
$patterns:
- '#{currency} #{amount}'
- '#{amount} #{currency}'types/date.yml
$imports: 'number'
Date:
YearMonthDay:
$fields:
year: { $type: Number::Integer, $match: '\d{4}' }
month: { $type: Number::Integer, $match: '0[1-9]|1[0-2]' }
day: { $type: Number::Integer, $match: '0[1-9]|[12]\d|3[01]' }
$patterns: '#{year}-#{month}-#{day}'types/payment-terms.yml
$imports: 'number'
PaymentTerms:
NetDays:
$fields:
days: Number::Integer
$patterns: 'Net #{days}'
DueOnReceipt: 'Due on Receipt'spec.yml
$imports: [ 'types/money', 'types/date', 'types/payment-terms' ]
$flags: [ 'CASE_INSENSITIVE', 'MULTILINE', 'FLEXIBLE_WHITESPACE' ]
InvoiceNumber: '[A-Z]{2,5}-${Number::Integer}'
InvoiceHeader:
$fields:
invoiceNumber: InvoiceNumber
$patterns: 'Invoice (No\.?|#):\s*#{invoiceNumber}'
InvoiceSection:
DateLine:
$fields:
invoiceDate: Date
$patterns: 'Invoice Date:\s*#{invoiceDate}'
BillingRecipientLine:
$types:
ClientName: '.*?'
$fields:
billingRecipient: ClientName
$patterns: 'Bill To:\s*#{billingRecipient}$'
SubtotalLine:
$fields:
subtotal: Money
$patterns: 'Subtotal:\s*#{subtotal}'
TaxLine:
$fields:
tax: Money
$patterns: 'Tax:\s*#{tax}'
TotalLine:
$fields:
total: Money
$patterns: 'Total( Amount)?:\s*#{total}'
PaymentTermsLine:
$fields:
paymentTerms: PaymentTerms
$patterns: 'Payment Terms:\s*#{paymentTerms}'
Invoice: '${InvoiceHeader}( ${InvoiceSection})+'
Try it liveOpen Invoice Parsing in StudioTweak the spec, paste your own input, and see the parse tree update in real time.