Create an information register
Updated
An information register is a point on the time axis: the value that was
in force on a date. The table is IR_{Name}. It is not an
accumulation register (TR_ / TB_, deltas,
balances). Kind: Information register.
Note
The same combination of key dimensions at the same
Periodupdates the row. A laterPeriodcloses the previous slice. Read withSliceLast/SliceFirst. Do not write it from a posting script withtransactions.Add.
How to#
1. The register — Registers/<Name>/<Name>.object.json with
registerEngineType: "Information". Cuts are physical dimensions, not
dynamic analytics. Resources are values of any EDT (number, string,
date, reference, boolean), not deltas.
A dimension that points at master data (item, tax, warehouse) is a
Reference EDT. The IR_ column stores the record Guid;
the slice journal opens the card. A scalar String is only for a value that
has no record of its own (a rate, a mode flag).
Do not set isDoubleEntry, useBalanceTable, or totalDriverMetaId — the
designer hides them. Changing the engine later drops the old table;
data does not migrate.
2. Write and read from a script, not from IRegisterMovementService:
var info = GetService<IInformationRegisterService>();
await info.SetAsync(new TaxRate
{
Period = document.DocumentDate,
TaxCode = line.TaxCode,
Rate = line.Rate,
RecorderMetaId = document.MetaId,
});
var slice = await info.SliceLastAsync<TaxRate>(document.DocumentDate,
new Dictionary<string, object?> { ["TaxCode"] = line.TaxCode });
SliceLast — last row with Period <= asOf per key. SliceFirst — first
with Period >= asOf. Cancelling the document deletes rows with that
RecorderMetaId. A Period in a closed period is refused the same way a
movement is — the posting boundary.
In a test: Db.SetInformationAsync / Db.SliceLastAsync. The generated
POCO is [Table("IR_TaxRate")]; class name = register name.
3. Menu item in the model's Registers subgroup — the journal shows
slices, not a totals report. Bump modelVersion in the same change.
Warning
A dated interval with gaps (
ValidFrom/ValidTo) is a dictionary or a link table, not this engine. A slice pulls the last value forward forever. A closed window ends, and after it there is no value. You cannot express "the price expired" in Information without a sentinel row.
A live Sales example: AbcClassification (profile + subject Guid), written
by IAbcClassifier and the RecalcAbcClassifications job —
ABC/XYZ.
The longer contract — IR_ columns, HTTP, rights, schema cleanup — is
the information register.
What's not there yet#
IRegisterMovementService and ITotalsManager throw
NotSupportedException on Information. There is no object card in the
catalog for this kind yet; the long page is the authority for the IR_
shape.