Skip to content

Recipes

Copy-paste solutions for common tasks.

Validate a customer at onboarding

import { validateNif, entityTypeLabel, validatePortugueseIban, formatPostalCode } from 'pt-fiscal';

function validateCustomer(input: { nif: string; iban: string; postal: string }) {
  const errors: string[] = [];
  if (!validateNif(input.nif)) errors.push('Invalid NIF');
  if (!validatePortugueseIban(input.iban)) errors.push('Invalid IBAN');
  const postal = formatPostalCode(input.postal);
  if (!postal) errors.push('Invalid postal code');
  return { ok: errors.length === 0, errors, kind: entityTypeLabel(input.nif), postal };
}

Batch-check a CSV of NIFs

import { readFileSync } from 'node:fs';
import { validateNif } from 'pt-fiscal';

const rows = readFileSync('customers.csv', 'utf8').trim().split('\n');
const invalid = rows.filter((nif) => !validateNif(nif));
console.log(`${invalid.length} invalid of ${rows.length}`);

Generate an invoice QR code image

import { buildInvoiceQRCode } from 'pt-fiscal';
import QRCode from 'qrcode'; // npm i qrcode

const payload = buildInvoiceQRCode({
  issuerNif: '500000000',
  buyerNif: '999999990',
  buyerCountry: 'PT',
  docType: 'FS',
  docState: 'N',
  docDate: new Date(),
  docId: 'FS A/1',
  atcud: 'CSDF7T5H-1',
  vat: { PT: { standard: [10, 2.3] } },
  totalTaxes: 2.3,
  totalWithTax: 12.3,
  hash4: 'kIrx',            // from your certified invoicing signature
  certificateNumber: 9999,
});

await QRCode.toFile('invoice-qr.png', payload, { errorCorrectionLevel: 'M' });

Build and validate an ATCUD

import { buildAtcud, validateAtcud } from 'pt-fiscal';

const atcud = buildAtcud({ validationCode: 'CSDF7T5H', sequence: 42 }); // "CSDF7T5H-42"
validateAtcud(atcud); // true

Use in a form (React)

import { validateNif } from 'pt-fiscal';

<input
  onBlur={(e) => setNifError(validateNif(e.target.value) ? '' : 'NIF inválido')}
/>