Файлы QBO: INTU.BID, FITID и почему импорт срывается
Файл .qbo — это OFX 1.02 с двумя прикрученными особенностями Intuit. Именно они порождают те две жалобы, которые у людей действительно есть. Всё изложенное вычитано из экспортёра этого конвертера, src/export/qbo.ts, а не с маркетинговой страницы другого конвертера.
QuickBooks подписывает мой импорт не тем банком
Из-за одного числа. Файл .qbo несёт элемент <INTU.BID>, и QuickBooks сверяет его с реестром Intuit — списком банков, у которых есть соглашение Web Connect. Произвольный идентификатор отвергается, поэтому каждый конвертер по умолчанию кладёт зарегистрированный, а самый ходовой, 3000, принадлежит Wells Fargo. Вот почему выписка Chase может импортироваться под подписью Wells Fargo.
Это косметика. Идентификатор определяет название и логотип банка, которые видны при импорте. Он не определяет, куда попадут операции, — реальный счёт в QuickBooks вы всё равно выбираете в диалоге импорта. Файл с чужой подписью сбивает с толку, но не является неверным.
Этот конвертер ставит 3000 по той же причине, что и все, говорит об этом прямо на странице вместо того, чтобы прятать, и позволяет заменить: поле ID банка для QBO рядом с кнопками скачивания, ?intuBid= в API или --intu-bid в CLI. Чтобы найти идентификатор своего банка, откройте .qbo, который банк выдал сам, и прочитайте строку <INTU.BID> — это единственный достоверный источник, и единственный, на который мы будем ссылаться.
Я сконвертировал выписку заново, и ничего не импортировалось
Это работает <FITID>. Каждая операция несёт идентификатор операции банка, и QuickBooks навсегда запоминает те, что уже видел по этому счёту. Операция, чей FITID импортировался раньше, молча пропускается. Именно это не даёт повторному импорту задвоить ваш журнал.
Значит, идентификатор обязан быть устойчивым между выгрузками одной выписки и уникальным внутри одной. Здесь это sha1(номер счёта | дата | сумма в копейках | первые 48 символов назначения), усечённый до 24 шестнадцатеричных знаков, со счётчиком -1, -2 в конце, когда выписка действительно перечисляет одну и ту же операцию дважды в один день.
Следствие, которое стоит знать: идентификатор выводится из операции, поэтому если вы исправите сумму перед выгрузкой, FITID этой строки изменится, и QuickBooks сочтёт её новой операцией. Сначала исправьте, потом импортируйте один раз.
Поля, от которых зависит, откроется ли файл вообще
| Элемент | За что отвечает | Что пишет этот конвертер |
|---|---|---|
INTU.BID | Идентификатор банка; должен быть известен Intuit | 3000, если вы не заменили |
FITID | Идентификатор операции; отсекает дубли при повторном импорте | sha1 операции, устойчивый |
BANKID | Маршрутный номер | 000000000, если вы не заменили |
ACCTTYPE | CHECKING / SAVINGS / MONEYMRKT / CREDITLINE | ваш выбор; задаёт набор сообщений |
DTSTART / DTEND | Период, который покрывает список операций | расширен так, чтобы вместить каждую строку файла |
TRNAMT | Сумма со знаком | отрицательная для расхода |
Источник: src/export/qbo.ts.
Кредитная карта — не банковский счёт
OFX кладёт выписки по картам в другой набор сообщений: <CREDITCARDMSGSRSV1> с <CCACCTFROM>, а не <BANKMSGSRSV1> с <BANKACCTFROM>. Выгрузите карточную выписку как расчётный счёт — и QuickBooks предложит импортировать её в банковский счёт. Выбор кредитной карты меняет весь конверт, а не подпись.
DTSTART и DTEND умеют молча терять строки
Импортёр вправе игнорировать операции с датой вне объявленного периода, а выписки регулярно содержат строку, проведённую за день до начала периода. Этот конвертер расширяет период так, чтобы он покрывал каждую операцию, реально попавшую в файл, — это исправленная нами ошибка, а не возможность.
XML-валидатору файл кажется сломанным
Так и задумано. OFX 1.02 — это SGML, а не XML: у листовых элементов нет закрывающего тега, поэтому <TRNAMT>-84.97 заканчивается переводом строки. Валидатор, ожидающий </TRNAMT>, читает не ту спецификацию. Заголовочный блок над <OFX> — тоже простые строки «ключ — значение».
Кириллица и акценты выходят упрощёнными
Заголовок объявляет ENCODING:USASCII, поэтому тело обязано быть настоящим ASCII. Латиница с диакритикой транслитерируется (Zürich → Zurich), кириллица романизируется (Оплата → Oplata); то, чему нет соответствия в ASCII, становится ?. Имена получателей вдобавок обрезаются до 32 символов — это предел OFX для <NAME>, — а полное назначение платежа пишется в <MEMO>, куда и уходит остаток обрезанного текста.
QuickBooks Online принимает и CSV — это другой зверь
Файл .qbo предназначен для Web Connect в QuickBooks Desktop. Ручная загрузка в QuickBooks Online принимает CSV и допускает ровно две раскладки: три колонки (Date, Description, Amount, расход отрицательный) или четыре (Date, Description, Credit, Debit). Две вещи в ней удивляют всех:
- Направление в четырёх колонках перевёрнуто. Собственная инструкция Intuit требует класть платежи под
Credit, а поступления подDebit— это взгляд учёта на счёт, а не взгляд банка. Файлы, собранные «очевидным» образом, импортируются с обратными знаками, и, поскольку импорт проходит успешно, этого никто не замечает до сверки. - Загрузка ограничена 1000 строк и 350 КБ. Более длинную выписку приходится делить на части, каждую со своей строкой заголовка.
В CSV-выгрузке этого конвертера есть предустановка QuickBooks Online: она отдаёт обе раскладки в направлении Intuit, убирает колонки, на которых QuickBooks споткнётся, и сама делит длинные выписки на пригодные к импорту части.
Чего эта страница вам не скажет
Какой INTU.BID принадлежит именно вашему банку. Списки ходят по сети, они неофициальные, а неверный идентификатор порождает ровно ту путаницу, ради объяснения которой страница и написана. Прочитайте его из .qbo, выданного вашим собственным банком.