Основы модели данных для GST‑счёта: минимальные поля, обработка HSN и админ‑экраны, необходимые для выписки соответствующих требованиям счетов и упрощения сверки.

Большинство проблем со счетами GST — это не «сложная налоговая логика», а отсутствие или несоответствие данных. Аудит проваливается, когда счёт нельзя однозначно связать с тем, что было продано, кому, где поставлено и как был рассчитан налог.
Частая причина — отсутствие HSN, его устаревшая версия или применение не на том уровне. Команды могут хранить HSN в карточке продукта, но строка счёта формируется из другого имени SKU или варианта, поэтому HSN не попадает в итоговый документ. Ещё одна распространённая ошибка — неверная разбивка налога: взимание IGST вместо CGST+SGST (или наоборот), если «место поставки» было определено по адресу доставки без сохранения кода штата, использованного для решения.
Финансы чувствуют это сразу. Сверка превращается в ежедневную ручную работу: суммы счёта не сходятся с заказом, заказ не совпадает с отчётом платёжного шлюза, а возвраты становятся цепочкой пометок. Даже небольшие отличия округления по строкам могут создавать расхождения между PDF счётом, налоговыми отчётами и бухгалтерской книгой.
Ниже — шаблоны, которые чаще всего вызывают проблемы:
Цель модели данных GST проста: хранить минимальный набор полей заказа, продукта, сторон, налога, счёта и кредит‑ноты, чтобы каждое число можно было воспроизвести и объяснить позже. Держите модель компактной, но не исключайте юридически важные поля, которые определяют тип налога, ставку и отчётность.
Чтобы генерировать корректные счета GST и упрощать последующую сверку, начните с небольшого набора объектов и сделайте так, чтобы каждый из них выполнял одну задачу. Чистая модель данных GST — это не множество таблиц, а устойчивость фактов во времени.
Основные записи, которые большинству команд нужны с первого дня:
Invoice должна быть отдельной от Order. Заказы меняются (адреса редактируют, позиции отменяют, частично выполняют). Счета не должны меняться: им нужны стабильные номера, даты и суммы, которые не «поплывут», если кто‑то обновит заказ позже.
Якорь точности налога — это Line Items. Каждая строка заказа (и затем строка счёта) должна содержать точное количество, цену за единицу, скидку и разбивку налога для конкретного товара. Именно туда следует переносить HSN/SAC и ставки GST.
Одна деталь, которая экономит время финансам: храните снимки. При генерации счёта скопируйте описание продукта, HSN/SAC, ставку налога и цену в строки счёта. Не полагайтесь на текущую карточку продукта: названия и ставки меняются.
Опционно, но часто полезно добавить с самого начала отдельные записи для Returns, Refunds и Credit Notes. Например: если клиент возвращает один товар из двух, удобнее выписать кредит‑ноту, ссылающуюся на строку исходного счёта, а запись возврата по платёжному шлюзу — на транзакцию. Явные объекты предотвращают ручные правки в сводках по GST в конце месяца.
Если вы строите это в Koder.ai, рассматривайте каждый объект сначала как простой экран (создать, просмотреть, редактировать), а генерацию счёта включайте только после того, как снимки и поля на уровне строки будут готовы.
HSN (для товаров) и SAC (для услуг) — это не «только поля в счёте». Они начинаются в описании продукта или услуги, а затем копируются в каждую строку счёта при его формировании. Это сохраняет корректность смешанных корзин и облегчает аудит, потому что каждая строка самодостаточна.
Практически минимальная модель данных:
Размещение HSN/SAC в карточке Product помогает администратору поддерживать данные в одном месте. Копирование в InvoiceLine делает прошлые счета стабильными: даже если продукт изменится позже, счёт покажет, что было верно на момент продажи. Это ядро модели данных GST, которая не ломается при сверке.
Для хранения HSN держите всё просто: код обязателен, описание — опционально, а effective_from date — опционально для истории изменений. Большинству команд не нужно описание на каждой строке, но оно помогает при проверке исключений.
Смешанные корзины — нормальное дело: один счёт может содержать несколько строк с разными HSN/SAC. Не пытайтесь навязать один код на весь счёт. Суммы агрегируются на уровне счёта, а классификация остаётся на уровне строки.
Управление изменениями — где чаще всего появляются проблемы. Простые правила:
С точки зрения админ‑экранов достаточно одного места для редактирования налоговых полей Product и только чтения в строке счёта, чтобы подтвердить, что было захвачено при выпуске. Для быстрого построения экранов инструменты вроде Koder.ai могут сгенерировать базовые CRUD‑страницы и таблицы данных по этой модели с минимальными усилиями.
Ошибка модели данных GST чаще всего кроется в деталях сторон. Если данные покупателя или продавца хоть немного неверны, счёт может выглядеть корректным, но затем создавать проблемы в отчётности и сверке.
Начинайте с разделения «seller», «buyer» и «ship-to» как отдельных сущностей, даже если это один и тот же человек. Это предотвращает костыли, когда клиент добавляет другой адрес доставки или когда вы продаёте из нескольких регистраций GST.
Держите поля простыми и явными — те, что обычно нужны в счёте и отчётах:
Храните штат как человеко‑читаемое название и как код штата, потому что отчётность и правила места поставки часто зависят от кода.
Фиксируйте и биллинг, и адрес доставки в самом заказе, а не только в профиле клиента. Профили меняются; счёта — нет.
Место поставки должно копироваться в виде конкретного кода штата в счёт (скопированного из заказа на момент выпуска). Не «пересчитывайте» его позже. Если правило — «по адресу доставки», сохраните этот результат и код штата, использованный для решения. Это упрощает аудит и споры.
Для B2B GSTIN покупателя обычно обязателен и должен валидироваться по длине и формату при вводе. Для B2C GSTIN может быть пустым, но всё равно нужен полный адрес и штат, чтобы определить, действует ли CGST/SGST или IGST.
Простое правило, работающее в большинстве систем: если GSTIN покупателя присутствует — считать как B2B; если нет — как B2C. При необходимости храните явное поле customer_type.
Если у вас есть филиалы или юниты с разными регистрациями GST, моделируйте «Seller Entity» как отдельную запись с собственным GSTIN и адресом. Каждый заказ должен ссылаться ровно на одну такую сущность, а счёт копировать эти данные, чтобы исторические счета оставались корректными даже при изменениях адреса продавца.
Инструменты вроде Koder.ai могут быстро сгенерировать админ‑формы, но ключевой момент — структура: отдельная сущность продавца, снимки на момент заказа и явный код штата места поставки.
Самая распространённая логика простая: если место поставки в том же штате, что и поставщик, налог — CGST + SGST. Если штат другой — IGST. Система не должна «пересчитывать позже из сумм», потому что небольшие отличия (округление, скидки, доставка) именно и создают несоответствия.
Минимум — хранить налоговые числа на уровне строки счёта, а не только в заголовке. Тогда вы сможете объяснить каждую рупию на счёте и связать её с продуктом, HSN и выручкой.
Практический минимум на строку счёта выглядит так:
Скидки — типичная зона путаницы. Выберите одно правило и явно его сохраняйте. Если скидки уменьшают цену до налогообложения (обычно для скидок на товар и купонов), храните исходную валовую сумму, сумму скидки и итоговую облагаемую стоимость. При купоне на уровне заказа распределяйте его по строкам (обычно пропорционально налогооблагаемой стоимости каждой строки) и храните аллокацию по каждой строке, чтобы налоговая математика оставалась понятной.
Округление должно быть последовательным и зафиксированным. Выберите, округляете ли вы на уровне строки или только на уровне счёта, а затем сохраняйте округлённые значения, которые вы показывали. Многие команды считают налог по строкам, округляют до 2 знаков, затем применяют итоговое поле invoice_rounding_adjustment для достижения точной платёжной суммы.
Доставка и обработка не должны быть скрытыми доплатами. Обрабатывайте их как отдельную строку счёта с собственным HSN/кодов услуг и правилами налогообложения. Тогда заказ с двумя товарами и доставкой станет тремя строками, каждая со своей облагаемой стоимостью и налоговым компонентом, что облегчает сверку.
После расчёта налога счёт всё ещё требует полей документа, делающих его действительным, аудируемым и лёгким для сверки. В модели данных GST относитесь к заголовку счёта как к юридической записи: он должен быть стабильным, даже если данные продукта или клиента изменятся.
Начиная с базовых полей: номер счёта, дата выставления (issue date), тип счёта (tax invoice, export, B2B, B2C и т.д.) и валюта. Даже если вы в основном выставляете в INR, хранение валюты избегает сложных случаев для экспорта или мультивалютных маркетплейсов.
Нумерация — где чаще всего наступают проблемы. Держите серию или префикс (например «FY25-INV-»), храните финансовый год и обеспечьте уникальность на уровне базы данных. Храните контроллы «next number» по каждой серии в админке, чтобы два администратора не выпустили одинаковый номер одновременно.
Итоги должны храниться явно, а не только выводиться. Сохраняйте subtotal (облагаемая сумма), total tax, grand total и отдельную сумму округления. Если вы пересчитываете из строк, небольшое изменение правила может привести к несовпадению старых счетов с поданными декларациями.
Статусы должны отражать реальный жизненный цикл и блокировать запись при необходимости:
Также храните метаданные сгенерированных артефактов: версия шаблона PDF, время генерации и идентификатор файла. Хэш опционален, но полезен, если надо доказать, что PDF не был изменён.
Например: если агент поддержки регенерирует PDF после обновления шаблона, суммы и номер счёта должны оставаться идентичными, а версия шаблона объяснит визуальные отличия.
Если хотите чистые GST‑счета, не начинайте со страницы счёта. Начните с админ‑страниц, которые его наполняют. Хорошая модель данных GST остаётся компактной, когда входные данные контролируются и согласованы.
Карточка продукта — источник большинства будущих несоответствий, поэтому держите её строгой. Каждый SKU должен иметь ровно один дефолтный HSN (или SAC для услуг), дефолтную ставку GST и возможные исключения по датам.
Практический экран продукта обычно требует:
Избегайте UI‑калькулятора. Храните входные данные, которые система применит последовательно: таблицы ставок, правила места поставки и логику определения intra‑state vs inter‑state (обычно сравнение штата поставщика и штата доставки).
Фокус экрана налогов: ставка по категории/группе HSN, даты вступления в силу и поведение при наличии валидного GSTIN покупателя или при его отсутствии.
Экран клиента должен фиксировать GSTIN и статус его валидации, а также дефолтные биллинг и адрес доставки. Не позволяйте пользователям свободно вводить названия штатов; используйте контролируемый список, чтобы «KA» и «Karnataka» не стали двумя разными значениями.
Экран профиля компании не менее важен: юридическое наименование, GSTIN, адрес регистрации и настройки серии счётов (префикс, следующий номер и границы финансового года). Ограничьте права на эти поля, поскольку изменения влияют на все будущие документы.
Не требуется сложной системы, но нужен след. Логируйте, кто менял HSN/SAC, ставки, настройки серии счётов или GSTIN компании, вместе со старым значением, новым, меткой времени и причиной.
Если строите экраны в Koder.ai, делайте аудит и даты вступления в силу первоочередными полями. Это недорого в реализации и экономит часы на проверках у финансов.
Соответствующий счёт — это скорее фиксация правильных фактов в нужный момент, чем красивое оформление. Если вы проектируете модель данных GST вокруг этого потока, работа финансов станет простой сверкой, а не еженедельным расследованием.
До расчёта налога заблокируйте снимок заказа: позиции, количества, цены за единицу, скидки, доставка/обработка, GSTIN покупателя (если есть), биллинг и доставка, а также признаки места поставки. Этот снимок не должен меняться даже если цена продукта или сопоставление HSN изменится позже.
Посчитайте налоги и сгенерируйте строки счёта из снимка. Каждая строка должна скопировать HSN/SAC, ставку налога, облагаемую стоимость и суммы налога, использованные в момент выпуска, вместо того чтобы смотреть эти данные живьём позже.
Присвойте номер счёта и дату выпуска, затем пометьте счёт как issued. С этого момента блокируйте правки цен, ставок налога, HSN и адресов в записи счёта. Если что‑то разрешено менять — только нефинансовые заметки и внутренние теги.
Сгенерируйте PDF/печатный вид из выпущенного счёта, затем сохраните финальные итоги, которые будете отчётывать: облагаемая сумма, суммы CGST/SGST/IGST, округление и итоговая сумма. Для дополнительной безопасности храните версию документа или контрольную сумму, чтобы доказать соответствие печатной версии и сохранённых чисел.
После выпуска изменения должны происходить через официальные документы, а не правкой записи:
Если вы встроите этот поток в админ‑экраны (режим планирования Koder.ai полезен для картирования шагов перед реализацией), команда сможет быстро генерировать счета без нарушения последующей сверки.
Сверка усложняется, когда платежи трактуются как простое «оплачен/не оплачен» в заказе. Храните платежи и возвраты как отдельные записи, связанные с заказом и счётом, чтобы финансы могли свести банковские выписки без переписывания истории.
Соответствующий счёт должен оставаться стабильным после выпуска. Если клиент платит частями или вы делаете возврат позже, фиксируйте это как запись платежа или возврата, а не как изменение итогов счёта.
Минимальные поля, упрощающие сверку:
Если клиент возвращает один товар, не уменьшайте счёт. Выпишите кредит‑ноту и свяжите её с исходным счётом. Реестр счётов останется чистым, а возврат будет привязан к кредит‑ноте.
Дайте финансам один экран, который отвечает на вопросы: что выпущено, что оплачено, что открыто и что отменено. Включите ageing (0‑7, 8‑30, 31‑60, 60+ дней) и возможность детального просмотра связанных платежей и возвратов.
Выгрузки, которые нужны большинству команд ежемесячно:
Пример: заказ на Rs 10,000, оплачено Rs 6,000 сегодня и Rs 4,000 на следующей неделе. Счёт остаётся Rs 10,000. Представление для финансов показывает баланс Rs 4,000 до второго расчёта, затем помечает счёт как полностью оплаченный без изменения выпущенного документа.
Большинство проблем со счетами GST — это не «логика налога», а учёт: числа в PDF не совпадают с выгрузками, или счёт нельзя объяснить спустя месяцы.
Первая ловушка — вычислять GST только при просмотре. Если вы пересчитываете CGST/SGST/IGST при каждом открытии счёта, со временем вы получите разные результаты после изменения ставки, правила округления или исправления ошибки. Храните вычисленную налоговую разбивку, использованную при выпуске, даже если вы сохраняете и входные данные.
Вторая ловушка — разрешать правки выпущенного счёта. После финализации изменения должны проходить через кредит‑ноту или новый документ с аудиторским следом. Иначе вы получите вопросы «почему PDF клиента не совпадает с книгами?».
Частые паттерны несоответствий:
Быстрый пример: вы продаёте клиенту в Karnataka, но адрес доставки — Maharashtra. Если система по ошибке берёт штат биллинга как место поставки, вы можете начислить CGST+SGST вместо IGST. Если при этом вы пересчитываете налог на лету, ошибка может «автоматически» исправиться позже, оставив финансы с числами, не совпадающими с выпущенным документом.
При разработке админ‑экранов добавьте простые защитные меры: блокируйте выпущенные счета, показывайте входные данные места поставки рядом с вычисленным типом налога и храните неизменяемый снимок HSN, ставки и округления, использованных при выпуске.
Перед тем как отправить счёт клиенту или пометить его как «issued», прогоняйте быстрые проверки. Именно здесь маленькие ошибки превращаются в большие проблемы при сверке. Если вы строите модель данных GST, стоит внедрить эти проверки как валидации и в админ‑интерфейс.
Простой пример: клиент обновил адрес доставки после оплаты, и штат изменился. Если вы перевыпустите тот же номер счёта с новым налогом, регистр и платёжные записи перестанут сходиться. Безопаснее — оставить исходный счёт неизменным и создать корректирующий документ.
Следующие шаги: реализуйте экраны и валидации в первую очередь, затем итерационно улучшайте. В Koder.ai начните с Planning Mode, чтобы набросать записи и админ‑экраны (продукты с маппингом HSN/SAC, данные клиентов/GSTIN, налоговые правила и счета). Сгенерируйте приложение, протестируйте несколько реальных заказов end‑to‑end, затем используйте снимки и откаты, чтобы безопасно отточить процесс. Когда потребуется более глубокая кастомизация, экспортируйте исходный код и продолжайте развивать приложение обычным способом.