← Документация / Ръководства
Мигриране от друга система
Прехвърлете счетоводството на дадена компания с едно заявка - сметкоплан, контрагенти, начални салда или пълна история, открити фактури, дълготрайни активи и стокови наличности.
Когато дадена компания преминава към Nordlet от друга счетоводна програма, нейните книги не започват от нулата. Импортерът на исторически данни (historical-books importer) взема всичко, което старата система оставя, и го записва в рамките на едно извикване, една единствена база данни транзакция: ако дори и един ред не издържи проверката, нищо не се запазва. Същият пакет може първо да бъде пуснат през ендпойнт само за проверка (check-only), който изпълнява всички валидации и прави откат (rollback).
POST /v1/migration/books/validate # проверява всичко, не записва нищо
POST /v1/migration/books/import # записва всичко или нищо
Уеб приложението има същите два бутона в раздел Профил → Миграция (поставете JSON или качете файл). API ключът изисква права ledger:write, както и правата за запис на всеки включен раздел (partners:write, catalog:write, sales:write, purchases:write, assets:write, inventory:write). И двата ендпойнта приема заявки с размер до 32 MB.
Дата на преход (cut-over)
Изберете датата на преход (cut-over date): първия ден, в който компанията започва да работи в Nordlet. Всичко преди тази дата остава в старата система (или се прехвърля като история, вижте по-долу); всичко от този ден нататък се въвежда в Nordlet чрез стандартните ендпойнтове. Всички суми в пакета са „към деня преди прехода“: оборотната ведомост към края на периода, фактурите, които все още са платени, стоките на склад и активите в инвентарната книга.
Преди да извършите импорта, направете следното в Nordlet:
- Създайте компанията и приложете шаблона на сметкоплана (
ledger/accounts/apply-template) - или избройте сметките, от които се нуждаете, в разделаaccountsна пакета. - Създайте поне един склад (
inventory/warehouses/create), ако импортирате стокови наличности. - Стартирайте пакета през
migration/books/validate, докато той не покаже липса на грешки и не приемете предупрежденията му.
Пакетът с данни
Всеки раздел е опционален; включете тези, с които разполагате. Всички връзки между разделите се осъществяват чрез код (код на сметка, код на контрагент, код на артикул, код на група активи, код на склад), като даден код може да се отнася както за запис, който вече съществува в Nordlet, така и за такъв, създаден от предходен раздел на същия пакет.
{
"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" }
]
}
Сумите са десетични низове (decimal strings), както навсякъде в API. source е свободен текст, който се записва в описанието на транзакцията за начални салда и в бележките на мигрираните фактури.
accounts
Редове на сметкоплана: code (код), name (име), type (тип - asset [актив], liability [пасив], equity [собствен капитал], income [приход], expense [разход]), опционални полета parentCode и isPostable. Съществуващите кодове остават непроменени и се отчитат като existing. Използвайте този раздел, когато сметкопланът на старата система се различава от шаблона, или го пропуснете и първо приложете шаблона.
partners и items
Клиенти, доставчици и номенклатурни позиции, индексирани по code. В Литва кодът на контрагента обикновено е ЕИК (код по регистъра на компаниите); за физически лица използвайте произволен код, който е уникален в рамките на компанията. Съществуващите кодове се пропускат, а не се актуализират. Артикулите поддържат полетата type (product [продукт] или service [услуга]), unit (единица мярка), barcode (баркод), vatRatePercent (данъчна ставка по ДДС), salePriceExclVat (продажна цена без ДДС), purchasePriceExclVat (доставна цена без ДДС).
openingBalances
Заключителната оборотна ведомост на старата система, по един ред за всяка сметка: accountCode заедно с debit или credit. Редовете се контират като една счетоводна статия (journal transaction) с дата openingBalances.date (по подразбиране е датата на преход) и тип на документа migration_opening. Редовете трябва да сочат към сметки, по които е разрешено контиране (postable accounts).
Статията трябва да бъде балансирана. Ако оборотната ведомост на старата система не е балансирана - поради закръглявания, печалба, която никога не е била отнесена към собствения капитал, или липсваща сметка - задайте balancingAccountCode (обикновено неразпределена печалба, 3410 в литовския шаблон) и разликата ще бъде отнесена там; отговорът показва сумата като balancingAmount.
За всяка компания може да съществува само една статия за начални салда. Втори импорт с openingBalances се отхвърля (код 409). Корекции след факта се правят чрез обикновени ръчни счетоводни статии (ledger/journal/transactions/create); осчетоводените статии са неизменни, така че оригиналът остава такъв, какъвто е импортиран.
journal - пълна история вместо или в допълнение към салдата
Ако искате транзакциите от старата система да бъдат в Nordlet (за да работят отчетите за предходни периоди), изпратете ги тук: по един обект за всяка транзакция с полета date, опционални description и reference, както и entries, съдържащи accountCode + debit/credit. Всяка транзакция трябва да бъде балансирана сама за себе си. Те се осчетоводяват с тип на документа migration.
Датите трябва да бъдат преди датата на преход. Когато пакетът съдържа и openingBalances, историята трябва да бъде с дата на или след openingBalances.date - обичайният модел е начални салда към началото на предходната финансова година плюс транзакциите за тази година, като преходът е на първия ден от текущата година. Не изпращайте салда и история за един и същ период, тъй като салдата ще бъдат отчетени двукратно.
Всеки месец, засегнат от началните салда или историята, трябва да бъде отворен счетоводен период (в противен случай се връща грешка 409).
openReceivables и openPayables
Фактури, които все още са били неплатени (изцяло или частично) към датата на преход. Те се създават като издадени фактури за продажби и регистрирани фактури за покупки с paidAmount = grossTotal − outstanding, така че съпоставянето с банкови извлечения (bank/transactions/match, bank/transactions/suggest-matches), отчетът за стари задължения (debt-aging) и уеб хуковете за плащане да работят с тях както при всяка друга фактура.
outstandingе равен наgrossTotalпо подразбиране;vatTotalе равен на0по подразбиране (данъчната основа се изчислява автоматично).dueDateе датата на документа по подразбиране.currencyе валутата на фактурата на компанията по подразбиране. За всяка валута, различна от основната валута на компанията, се изискваfxRate- брой единици от тази валута за 1 единица от основната валута, със същото споразумение като в останалата част от API - и се записва във фактурата, така че последващите плащания да изчисляват правилно реализираната валутна разлика.- Номерът на фактурата за продажба (
number) е пълният номер от старата система и трябва да бъде уникален в рамките на компанията. Фактурите за покупки са уникални в рамките на контрагент иdocumentNumber. - Фактурите не се осчетоводяват повторно: тяхното салдо по вземания/задължения вече е част от началните салда. Те са обвързани с транзакцията за начални салда, поради което
openPayablesизискваopeningBalancesв същия пакет. - Редовете на фактурите не се импортират; фактурата съдържа само общи суми. Старата система остава източник за детайлите по редовете и за дневниците по ДДС за периоди преди прехода.
Ако старата система е следяла салда по клиенти без отворени позиции, създайте по една фактура за всеки контрагент за сумата на салдото (например с номер OB-301111222), за да може то да бъде затворено.
Номерацията продължава. Когато номерът на импортирана фактура за продажба е във формат PREFIX-N и датата ѝ на издаване попада в годината на преход, номенклатурната серия за този префикс и година се задава на N + 1 (никога не се намалява). Отговорът извежда получената серия numberSeries; за други случаи задайте серията сами с reference/series/create ({ documentType: "sale_invoice", prefix, year, startAt }).
assetGroups и fixedAssets
Дълготрайните активи се прехвърлят заедно с тяхната амортизация към момента: acquisitionCost (историческа цена), salvageValue (ликвидационна стойност), accumulatedDepreciation (начислена амортизация), depreciatedMonths (амортизирани месеци) и usefulLifeMonths (полезен живот в месеци) или стойността по подразбиране за групата. Процесът на линейна амортизация (assets/depreciation/post) продължава на базата на остатъчната стойност за оставащите месеци. Активите, чиято начислена амортизация вече е равна на амортизируемата стойност, се създават със статус fully_depreciated (напълно амортизирани). Нищо не се осчетоводява - стойността на придобиване и начислената амортизация са част от началните салда.
Групите се индексират по code и изискват assetAccountCode (сметка за активи) и depreciationAccountCode (сметка за амортизация, с разходна сметка по подразбиране 6206).
stock
Налични стоки по артикули: itemCode, quantity (количество), unitCost (единична цена в EUR) и опционално warehouseCode (склад по подразбиране: основният склад), както и lotNumber (партиден номер) и expiryDate (срока на годност) за артикули, проследявани по партиди или серийни номера. Всеки ред се превръща в входящо движение на стоки с дата на прехода, тип на документа migration и стартира FIFO слой на тази цена. Нищо не се осчетоводява - стойността на стоките е част от началните салда.
Проверки и предупреждения
Ендпойнта за валидиране връща грешка (422) при липсващи сметки, сметки без право на контиране, небалансирани транзакции, неразпознати кодове на контрагенти, артикули, групи или складове, дублиращи се кодове или номера в пакета, открити суми, надвишаващи брутната сума, начислена амортизация, надвишаваща амортизируемата стойност, и липсващи валутни курсове. Номера или кодове, които вече съществуват в Nordlet, връщат код 409.
В допълнение към това, и двата ендпойнта сравняват аналитичните сметки (sub-ledgers) със синтетичните счетоводни записвания в същия пакет и връщат разликите като warnings (предупреждения), вместо като грешки:
- обща сума на неплатените суми в
openReceivablesспрямо салдото по сметката за вземания (правило за контиранеsales.receivable, по подразбиране2410); - обща сума на неплатените суми в
openPayablesспрямо сметката за задължения (purchases.payables,4430); - обща стойност на
stockспрямо сметката за стоки (inventory.stock,2040); - за всяка група активи - стойността на придобиване на активите спрямо сметката за активи на групата и тяхната начислена амортизация спрямо сметката за амортизация.
Дадено предупреждение означава, че аналитичното и синтетичното отчитане на старата система не съвпадат. Коригирайте пакета (или приемете разликата съзнателно) преди импортиране.
Отговорът
{
"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": []
}
dryRun: true указва тестово изпълнение (validate run); в този случай journalTransactionId е null. Извършеният импорт се записва в одитния журнал (audit log) като migration.imported със същото обобщение.
След импорта
- Заключете периодите преди датата на преход (
ledger/periods/lock), за да предотвратите случайно осчетоводяване в мигрираната история. - Проверете оборотната ведомост и баланса към датата на преход спрямо заключителните отчети на старата система.
- Продължете със стандартния работен процес: издаване на фактури, импортиране на банкови извлечения, съпоставяне на плащания - мигрираните открити фактури се закриват като всички останали.
Какво не обхваща импортерът: редове на фактури и дневници по ДДС за минали периоди (запазете ги в старата система или нейния архив), хронология на заплатите, както и документи, различни от фактури (поръчки, товарителници, договори).