Skip to content
ERPNext Data Model
Esc
navigateopen⌘Jpreview
On this page

HSN Code & UOM Mapping Validation

A design reference for the master-data checks that keep item classification and party identity numbers usable for GST filing

1. Requirements

1.1 Functional requirements

  • The system must maintain a master list of HSN/SAC classification codes, each with a valid statutory digit length, and let an operator attach default tax templates to a code so items classified under it inherit sensible taxes automatically.
  • Every sales-relevant item must carry an HSN/SAC code of the correct length before it can be used in a submitted transaction, though the strictness of that check must be configurable, since not every installation files under a regime that requires it.
  • The system must translate an item’s ordinary unit of measure into the statutory unit-of-measure code the government expects on filed data, using an explicit per-installation mapping where one has been configured, and a best-effort fallback where it has not.
  • The system must recognize a party’s Permanent Account Number (PAN) both as a directly entered value and as a value implicitly carried inside a GST registration number, validating its format in either case, and separately track that number’s publicly reported status once available.

1.2 Non-functional requirements

  • No transaction should ever be blocked by a code the system cannot classify. A unit of measure with no configured statutory mapping must still produce some value on filed data rather than fail the transaction outright.
  • Validation strictness must be a deliberate, visible setting, not an accident of code path — an installation that does not need HSN enforcement must be able to turn it off entirely rather than work around scattered checks.

1.3 Constraints

  • All three checks are pure master-data or format validators; none of them talks to a government system directly, and none of them is itself part of the reconciliation or filing pipelines documented separately — they are consulted by those pipelines, not the other way around.

2. High-Level Design

2.1 Component diagram


3. Deep Dive

3.1 Data model

HSN/SAC Code Master — one row per classification code, holding a description and a child table of default tax templates (each with a validity date and a minimum/maximum net-rate range) that get copied onto an item’s own tax rows the first time a matching code is assigned and the item has no tax rows of its own yet. Whether a code is even reachable by validation depends on a single per-installation toggle plus a companion setting choosing which digit lengths (4, 6, or 8) count as valid; the two settings are linked so the length choice is only meaningful — and only shown — while the toggle is on.

UOM-to-Statutory-Code Map — a small, optional, per-installation table pairing an ordinary unit of measure with one of the government’s fixed statutory unit codes. It is consulted, never enforced: a lookup that finds no explicit mapping falls back to treating the unit’s own name as the statutory code if it happens to already match one, and falls back again to a generic “Others” code if it does not. Nothing about this lookup can fail a transaction — it always returns something.

PAN — two independent mechanisms share this one term, and only one of them does real validation:

  • A fixed-pattern format check (five letters, four digits, one letter) applied wherever a party record’s PAN is entered directly, or derived by extracting the middle ten characters of a registration number. A directly entered value that fails the pattern is rejected outright at save time. A value derived from a registration number is not re-validated against the same pattern — if the extraction does not look like a valid PAN, the field is silently cleared instead of raising an error.
  • A separate cached-status record, one per PAN, intended to hold a periodically refreshed, publicly reported status. The lookup this record depends on is currently disabled at its source — the function that would fetch a fresh status returns nothing before ever making a request — so in its present state this record can only ever reflect whatever was cached before that lookup was turned off; it performs no format validation of its own and is a bare status cache, not an active validator.

3.2 What actually blocks a transaction

The HSN check is the only one of the three with real teeth, and its strictness genuinely varies by where it runs: on the item master itself, a sales item with a missing or wrong-length code is rejected unconditionally whenever the toggle is on. On an ordinary transaction line, the same check is advisory (a warning) while the document is still a draft, but becomes an unconditional hard block the moment the document is submitted, regardless of whether the specific calling code asked for a hard block earlier. One caller — a purchase invoice in an import-relevant category — asks for the hard block even before submission, since a missing code there would make it impossible to determine whether an import-duty document is even required.

The UOM lookup and the PAN status record, by contrast, never block anything by themselves. The UOM lookup is explicitly designed to always produce a usable value. The PAN status record is a cache with no live source behind it in its current state.


4. Scale and Reliability

  • Each of the three checks is a cheap, synchronous, in-process lookup against a small master table — none of them has a load profile worth discussing separately from the transaction that triggers them.
  • The PAN status record’s dependency on a disabled external lookup means its data only ever gets staler over time; nothing currently re-enables or replaces that source.

5. Trade-off Analysis

Decision Trade-off
A single toggle plus a length list, rather than per-transaction-type HSN rules Simple to configure and reason about, but cannot express “require it for sales, not for purchases” without going around the setting entirely, as the import-purchase caller does.
UOM mapping with silent fallback rather than a hard requirement Filed data is never blocked by a missing mapping, but a genuinely wrong fallback (an unusual unit silently reported as “Others”) is invisible unless someone reviews the filed output by hand.
PAN format enforced only on direct entry, not on GSTIN-derived extraction Avoids rejecting a save over a registration number the operator did not type the PAN portion of directly, but means a malformed registration number can silently produce a blank PAN rather than surfacing the underlying problem.

6. What to Revisit as the System Grows

  • The PAN status record’s lookup is dead in its current state — the fetch it depends on returns before attempting anything. Either restore a working source or remove the “update status” action, since as written it can mislead an operator into thinking a refresh happened.
  • The UOM fallback path is invisible by design. A report surfacing which items are filing under a guessed statutory code, rather than an explicitly configured one, would catch a wrong guess before it reaches filed data instead of after.
  • This document is deliberately short: apart from the tax-template default copied from an HSN code, none of the three mechanisms here does more than validate a format or translate a code, and the source does not support asserting anything richer.

Was this page helpful?