August 20, 2026

Decoding TRANS.iType in Yardi Voyager: The Complete Code Map

Every posted transaction in Yardi Voyager lands in one table: TRANS. What kind of transaction it is — a tenant charge, a vendor payment, a bank transfer, a journal entry — is not a separate table, a separate module, or a readable label. It's a single integer column, iType, and if you decode it wrong your query still runs. It just returns the wrong answer, silently, forever.

That's the landmine with every integer-coded discriminator field in Voyager: iType = 7 compiles fine whether or not you know that 7 means "AR charge." Nothing throws an error when you filter for iType = 6 thinking it's a deposit instead of a tenant receipt. The rent roll runs. The number is just wrong, and it stays wrong until someone reconciles it against the general ledger and can't figure out why.

Why this specific field is worse than most

Most Voyager status fields at least have a matching decoder view somewhere in the schema — tenstatus for TENANT.iStatus, for instance. TRANS.iType doesn't hand you that convenience. It's a bare integer with no companion lookup table shipped in the standard schema, which means the decode has to come from somewhere else: either institutional memory, or execution-verified testing against a live database.

That's also why it's a landmine and not just an inconvenience. TRANS sits at the center of Voyager's financial spine — the SQL Query Assistant's schema knowledge describes it as the header table that DETAIL (line items) and GLDETAIL (ledger postings) both hang off. Get iType wrong at the header and the error propagates through every join built on top of it: AR aging, AP aging, GL activity, delinquency reports. One misread code, many wrong reports.

The complete map

PropETL's schema knowledge base carries a decoded, execution-verified map of TRANS.iType — the same one referenced on the SQL Query Assistant page as "the complete 14-code TRANS.iType map." Fourteen distinct values have been observed on live Voyager transaction data. Eight of them carry confirmed semantic labels:

The remaining six observed values (9, 11, 12, 15, 16, 19) are lower-volume codes that have been profiled against live data but don't yet have confirmed semantics beyond "not an AP invoice." That distinction matters: a decode that's honest about what it doesn't know is more useful than one that guesses a plausible-sounding label and gets baked into a report. If you're drafting ySQL against TRANS.iType and land on one of those six, the correct move is to filter by the observed value and hold off on labeling it — not invent a name for it.

The trap hiding one level down: HPERSON is polymorphic

Getting iType right isn't the end of it. TRANS.HPERSON — the column that tells you who the transaction belongs to — changes meaning depending on which iType you're looking at:

That last one is the classic version of a trap that shows up all over Voyager's schema: a foreign-key-shaped column whose actual target table depends on a sibling discriminator column, not on the column name. (We've written up the general form of this — the HMYPERSON subtype trap — separately, because it isn't unique to TRANS.)

There's a second, quieter trap in the bank-type rows. iType = 5 and iType = 18 transactions carry NULL in both HPROP and the post-date column — which means any query that joins through property or filters by month will silently drop them. They aren't missing from the database; they're just invisible to the join pattern most reports use by default.

What this looks like as a query

A correctly scoped charge query filters iType = 7 explicitly rather than assuming every TRANS row is a charge:

SELECT p.sCode, t.cAmount, t.dtDate
FROM   TRANS t
JOIN   PROPERTY p ON p.hMy = t.hProp
WHERE  p.sCode = '{PROPERTY_CODE}'
  AND  t.iType = 7  -- AR charge
  AND  t.dtDate >= '{START_DATE}'

The comment isn't decoration. Without it, the next person to touch this query — including a future version of you — has no way to know why 7 is the right number, or what happens if it silently becomes 6.

Stop keeping this in your head

The traditional fix for this is a private cheat sheet, usually incomplete, usually undocumented, usually lost when the person who built it changes jobs. The SQL Query Assistant ships the decode as queryable knowledge instead — 228 install-invariant decode rows across 32 decoders, including the full TRANS.iType map, so you can ask "what does iType = 13 mean and should I include it in this report?" and get the verified answer along with the trap it's attached to, right inside Claude.

It's included in every PropETL tier. Start the free 7-day trial — no credit card — and ask it to decode the next magic number your report turns up.