Nordlet

← Documentacao / Guias

Migrar a partir de outro sistema

Transfira a contabilidade de uma empresa numa única chamada - plano de contas, parceiros, saldos de abertura ou histórico completo, faturas pendentes, ativos fixos e inventário.

Quando uma empresa transita para o Nordlet a partir de outro programa de contabilidade, a sua contabilidade não começa do zero. O importador de histórico contabilístico recolhe tudo o que o sistema antigo deixa e grava-o numa única chamada, numa única transação de base de dados: se uma única linha falhar uma validação, nada é guardado. O mesmo pacote pode ser executado primeiro num endpoint de validação (check-only), que efetua todas as validações e reverte a operação.

POST /v1/migration/books/validate   # valida tudo, nao grava nada
POST /v1/migration/books/import     # grava tudo ou nada

A aplicação web dispõe dos mesmos dois botões em Conta → Migração (colar o JSON ou carregar um ficheiro). A chave de API (API key) necessita de ledger:write juntamente com o âmbito de escrita de cada secção incluída (partners:write, catalog:write, sales:write, purchases:write, assets:write, inventory:write). Ambos os endpoints aceitam corpos até 32 MB.

A data de transição

Selecione a data de transição (cut-over date): o primeiro dia em que a empresa opera no Nordlet. Tudo o que precede esta data permanece no sistema antigo (ou é importado como histórico, consulte abaixo); tudo a partir desse dia é introduzido no Nordlet através dos endpoints normais. Todos os montantes do pacote referem-se à "situação do dia anterior à transição": o balancete de encerramentos, as faturas ainda por pagar, o inventário ainda em armazém e os ativos ainda em cadastro.

Antes de importar, execute os seguintes passos no Nordlet:

  1. Crie a empresa e aplique o modelo de plano de contas (ledger/accounts/apply-template) - ou liste as contas necessárias na secção accounts do pacote.
  2. Crie pelo menos um armazém (inventory/warehouses/create) caso importe inventário.
  3. Execute o pacote através de migration/books/validate até que o sistema não reporte erros e aceite os respetivos avisos.

O pacote

Todas as secções são opcionais; inclua apenas as que possui. Todas as referências entre secções são efetuadas por código (código de conta, código de parceiro, código de artigo, código de grupo de ativos, código de armazém), podendo um código referir-se a um registo já existente no Nordlet ou a um registo criado numa secção anterior do mesmo pacote.

{
  "cutoverDate": "2026-01-01",
  "source": "Rivilė GAMA",
  "accounts": [
    { "code": "6210", "name": "Advertising expenses", "type": "expense", "parentCode": "6" }
  ],
  "partners": [
    { "code": "301111222", "name": "UAB Klientas", "vatCode": "LT100001112223", "isCustomer": true },
    { "code": "302222333", "name": "UAB Tiekėjas", "isCustomer": false, "isSupplier": true }
  ],
  "items": [
    { "code": "SKU-1", "name": "Widget", "type": "product", "unit": "vnt", "vatRatePercent": "21" }
  ],
  "assetGroups": [
    { "code": "TRANSP", "name": "Vehicles", "assetAccountCode": "1230", "depreciationAccountCode": "1239",
      "defaultUsefulLifeMonths": 60 }
  ],
  "openingBalances": {
    "balancingAccountCode": "3410",
    "entries": [
      { "accountCode": "2710", "debit": "5000.00" },
      { "accountCode": "2410", "debit": "1500.00" },
      { "accountCode": "2040", "debit": "300.00" },
      { "accountCode": "1230", "debit": "12000.00" },
      { "accountCode": "1239", "credit": "2400.00" },
      { "accountCode": "4430", "credit": "700.00" },
      { "accountCode": "3010", "credit": "10000.00" }
    ]
  },
  "openReceivables": [
    { "partnerCode": "301111222", "number": "SF-1050", "issueDate": "2025-12-10", "dueDate": "2026-01-09",
      "grossTotal": "1210.00", "vatTotal": "210.00" },
    { "partnerCode": "301111222", "number": "SF-1049", "issueDate": "2025-11-20",
      "grossTotal": "500.00", "outstanding": "290.00" }
  ],
  "openPayables": [
    { "partnerCode": "302222333", "documentNumber": "T-77", "documentDate": "2025-12-15", "grossTotal": "700.00" }
  ],
  "fixedAssets": [
    { "groupCode": "TRANSP", "code": "CAR-1", "name": "Delivery van", "acquisitionDate": "2025-01-01",
      "acquisitionCost": "12000.00", "accumulatedDepreciation": "2400.00", "depreciatedMonths": 12 }
  ],
  "stock": [
    { "itemCode": "SKU-1", "quantity": "30", "unitCost": "10" }
  ]
}

Os montantes são representados como cadeias de caracteres decimais (decimal strings), tal como em toda a API. O campo source é uma etiqueta livre que é incluída na descrição do lançamento de saldos de abertura e nas notas das faturas migradas.

accounts

Linhas do plano de contas (chart of accounts): code, name, type (asset, liability, equity, income, expense), com os campos opcionais parentCode e isPostable. Os códigos já existentes não são modificados e são contabilizados como existing. Utilize esta opção quando o plano do sistema antigo difere do modelo, ou ignore-a e aplique o modelo primeiro.

partners e items

Clientes, fornecedores e artigos de catálogo, indexados por code. Na Lituânia, o código de parceiro corresponde normalmente ao código do registo comercial da empresa; para particulares, utilize qualquer código que seja único dentro da empresa. Os códigos existentes são ignorados e não atualizados. Os artigos aceitam os campos type (product ou service), unit, barcode, vatRatePercent, salePriceExclVat, purchasePriceExclVat.

openingBalances

O balancete de encerramento do sistema antigo, com uma linha por conta: accountCode acompanhado por debit ou credit. As linhas são lançadas como uma única transação de diário com a data openingBalances.date (por omissão, a data de transição) e o tipo de documento migration_opening. As linhas devem referenciar contas com permissão de lançamento.

A transação deve estar equilibrada. Se o balancete do sistema antigo não estiver equilibrado - devido a arredondamentos, a um resultado líquido nunca transferido para capitais próprios, ou a uma conta em falta -, indique balancingAccountCode (tipicamente resultados transitados, 3410 no modelo lituano) e a diferença será lançada nessa conta; a resposta reporta o montante através de balancingAmount.

Apenas pode existir uma transação de saldos de abertura por empresa. Uma segunda importação com openingBalances será recusada (409). Quaisquer correções posteriores devem ser efetuadas através de lançamentos de diário manuais ordinários (ledger/journal/transactions/create); as transações lançadas são imutáveis, pelo que a versão original permanece tal como foi importada.

journal - histórico completo em vez de, ou em adição aos, saldos

Se pretender transferir as transações do sistema antigo para o Nordlet (para que os relatórios de períodos anteriores funcionem), envie-as para esta secção: um objeto por transação com date, os campos opcionais description e reference, e as entries compostas por accountCode + debit/credit. Cada transação deve estar equilibrada de forma autónoma. São lançadas com o tipo de documento migration.

As datas devem ser anteriores à data de transição. Se o pacote também incluir openingBalances, o histórico deve ter uma data igual ou posterior a openingBalances.date - o procedimento habitual consiste em incluir os saldos no início do exercício financeiro anterior e as transações desse mesmo ano, com a transição a ocorrer no primeiro dia do ano corrente. Não envie saldos e histórico para o mesmo período, pois os saldos seriam contabilizados em duplicado.

Todos os meses afetados pelos saldos de abertura ou pelo histórico devem corresponder a um período contabilístico aberto (caso contrário, obterá um erro 409).

openReceivables e openPayables

Faturas que permaneciam por pagar (total ou parcialmente) à data de transição. São criadas como faturas de venda emitidas (issued) e faturas de compra registadas (registered) com paidAmount = grossTotal − outstanding, permitindo que a reconciliação bancária (bank/transactions/match, bank/transactions/suggest-matches), o relatório de antiguidade de saldos (debt-aging report) e os webhooks de pagamento funcionem da mesma forma que para qualquer outra fatura.

  • O campo outstanding assume por omissão o valor de grossTotal; vatTotal assume por omissão 0 (o valor líquido é calculado automaticamente).
  • O campo dueDate assume por omissão a data do documento.
  • O campo currency assume por omissão a moeda de faturação da empresa. Para qualquer moeda diferente da moeda base da empresa, é obrigatório indicar fxRate - unidades dessa moeda por 1 unidade da moeda base, seguindo a mesma convenção do resto da API -, que fica armazenada na fatura para que os pagamentos futuros calculem corretamente a diferença de câmbio realizada.
  • O number da fatura de venda corresponde ao número completo do sistema antigo e deve ser único na empresa. As faturas de compra são únicas por parceiro e por documentNumber.
  • As faturas não são lançadas novamente: o respetivo saldo de clientes/fornecedores já faz parte dos saldos de abertura. Encontram-se associadas à transação de saldos de abertura, razão pela qual openPayables requer a presença de openingBalances no mesmo pacote.
  • As linhas das faturas não são importadas; a fatura contém apenas os totais. O sistema antigo continua a ser a fonte para o detalhe das linhas e para os registos de IVA de períodos anteriores à transição.

Se o sistema antigo controlava os saldos de clientes sem faturas pendentes, crie uma fatura por parceiro pelo montante do saldo (por exemplo, com o número OB-301111222) para permitir a respetiva liquidação.

A numeração tem continuidade. Quando o número de uma fatura de venda importada tem o formato PREFIX-N e a respetiva data de emissão pertence ao ano de transição, a série de numeração para esse prefixo e ano é definida como N + 1 (nunca é reduzida). A resposta lista o campo numberSeries resultante; para outros casos, configure a série manualmente através de reference/series/create ({ documentType: "sale_invoice", prefix, year, startAt }).

assetGroups e fixedAssets

Os ativos fixos são transferidos juntamente com a respetiva depreciação acumulada à data: acquisitionCost, salvageValue, accumulatedDepreciation, depreciatedMonths e usefulLifeMonths (ou o valor por omissão do grupo). O cálculo de depreciação linear (assets/depreciation/post) prossegue com base no valor residual e nos meses remanescentes. Os ativos cuja depreciação acumulada já seja igual ao valor depreciável são criados com o estado fully_depreciated. Nenhum valor é lançado - o custo e a depreciação acumulada já fazem parte dos saldos de abertura.

Os grupos são indexados por code e requerem assetAccountCode e depreciationAccountCode (conta de gastos por omissão 6206).

stock

Inventário em stock por artigo: itemCode, quantity, unitCost (custo unitário em EUR) e, opcionalmente, warehouseCode (por omissão: o armazém predefinido), lotNumber e expiryDate para artigos controlados por lote ou número de série. Cada linha resulta num movimento de entrada de stock com data igual à data de transição, tipo de documento migration, e inicia uma camada FIFO com esse custo. Nenhum valor é lançado - o valor do inventário faz parte dos saldos de abertura.

Verificações e avisos (checks and warnings)

O endpoint de validação devolve um erro (422) caso detete contas em falta, contas sem permissão de lançamento, transações desequilibradas, códigos desconhecidos de parceiro, artigo, grupo ou armazém, códigos ou números duplicados dentro do pacote, montantes pendentes superiores ao total bruto, depreciação acumulada superior ao valor depreciável, ou taxas de câmbio em falta. Números ou códigos que já existam no Nordlet originam um erro 409.

Adicionalmente, ambos os endpoints comparam as subcontas (sub-ledgers) com os lançamentos do razão geral (ledger entries) incluídos no mesmo pacote, devolvendo as divergências sob a forma de warnings (avisos) em vez de erros:

  • total pendente de openReceivables em comparação com o saldo da conta de clientes (regra de lançamento sales.receivable, 2410 por omissão);
  • total pendente de openPayables em comparação com a conta de fornecedores (purchases.payables, 4430);
  • custo total de stock em comparação com a conta de inventário (inventory.stock, 2040);
  • por grupo de ativos, o custo dos ativos em comparação com a conta de ativos do grupo e a respetiva depreciação acumulada em comparação com a conta de depreciação.

A existência de um aviso significa que a subconta e o razão geral do sistema antigo não coincidem. Corrija o pacote (ou aceite a diferença conscientemente) antes de efetuar a importação.

A resposta

{
  "dryRun": false,
  "cutoverDate": "2026-01-01",
  "accounts": { "created": 1, "existing": 0 },
  "partners": { "created": 2, "existing": 0 },
  "items": { "created": 1, "existing": 0 },
  "assetGroups": { "created": 1, "existing": 0 },
  "openingBalances": { "journalTransactionId": "…", "date": "2026-01-01", "entries": 8,
                        "debitTotal": "18800.00", "creditTotal": "18800.00", "balancingAmount": "5700.00" },
  "journal": { "transactions": 0, "entries": 0 },
  "openReceivables": { "created": 2, "outstandingTotal": "1500.00" },
  "openPayables": { "created": 1, "outstandingTotal": "700.00" },
  "fixedAssets": { "created": 1, "costTotal": "12000.00", "accumulatedDepreciationTotal": "2400.00" },
  "stock": { "movements": 1, "costTotal": "300.00" },
  "numberSeries": [],
  "warnings": []
}

O parâmetro dryRun: true identifica uma execução de validação; nesse caso, journalTransactionId assume o valor null. Uma importação fica registada no registo de auditoria (audit log) como migration.imported com o respetivo resumo.

Após a importação

  • Bloqueie os períodos anteriores à data de transição (ledger/periods/lock) para evitar lançamentos acidentais no histórico migrado.
  • Verifique o balancete e o balanço à data de transição em comparação com os relatórios de encerramento do sistema antigo.
  • Prosseguir com o fluxo normal: emitir faturas, importar extratos bancários, reconciliar pagamentos - as faturas pendentes migradas liquidam-se tal como qualquer outra.

O que o importador não abrange: linhas de fatura e registos de IVA de períodos anteriores (mantenha-os no sistema antigo ou no respetivo arquivo), histórico de salários e vencimentos, e documentos que não sejam faturas (encomendas, guias de remessa, contratos).