You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while working #1826 (the field-no-consumers display gaps). ⛔ Out of that card's scope — filed rather than fixed there.
The finding
crm_opportunity_line_item.line_number is Field.number({ readonly: true }). Grep the tree for every site that names it, and nothing writes it:
no hook — opportunity_line_item.hook.ts and the shared _line-item-price-fill.ts never touch it;
no flow node, no action;
readonly: true means a user cannot type it either, and since @objectstack/objectql@17.4.0 a static readonly field is stripped from a non-system caller's INSERT as well, so an ordinary rep creating a line cannot seed it even by accident.
The only values that exist are the 19 rows in src/data/, which the seed loader writes as a system caller. test/seed-consistency.test.ts pins those to be 1..n within each parent — a pin on the seed fixture, not evidence of a runtime writer.
Why it matters beyond a blank column
src/flows/billing-handoff.flow.ts puts line_number in LINE_ITEM_FIELDS, the projection that composes the billing payload for both closed_won and contract-activated hand-offs. That payload is described in content/docs/revenue/billing-handoff.mdx (three locales) with "line_number": 1 in the worked example.
So the app hands the billing system a field that is null on every line item created in the product, and non-null only on demo seed rows. The docblock on that flow is explicit that the payload "IS the contract with the billing system" and is authored field-by-field so it cannot silently drift — this is a drift it did not catch, because the field is declared and merely never filled.
The decision this needs
Two coherent answers, and it is a product call, not a mechanical one:
Retire the ordinal. If the ordering a reader wants is the related list's own sort, the column is a promise nothing keeps. Removal has to clean the declaration plus its carrier sites and drop the key from LINE_ITEM_FIELDS and the three billing-handoff doc pages.
⚠️ Note the twin: crm_quote_line_item.line_number has exactly the same gap, and is the reason that field is reported standing on #1826 rather than given a view column — a column there would render blank on every row a user creates. Whichever answer is chosen should cover both objects, since the two line-item objects deliberately mirror each other.
Found while working #1826 (the
field-no-consumersdisplay gaps). ⛔ Out of that card's scope — filed rather than fixed there.The finding
crm_opportunity_line_item.line_numberisField.number({ readonly: true }). Grep the tree for every site that names it, and nothing writes it:opportunity_line_item.hook.tsand the shared_line-item-price-fill.tsnever touch it;readonly: truemeans a user cannot type it either, and since@objectstack/objectql@17.4.0a static readonly field is stripped from a non-system caller's INSERT as well, so an ordinary rep creating a line cannot seed it even by accident.The only values that exist are the 19 rows in
src/data/, which the seed loader writes as a system caller.test/seed-consistency.test.tspins those to be1..nwithin each parent — a pin on the seed fixture, not evidence of a runtime writer.Why it matters beyond a blank column
src/flows/billing-handoff.flow.tsputsline_numberinLINE_ITEM_FIELDS, the projection that composes the billing payload for bothclosed_wonand contract-activated hand-offs. That payload is described incontent/docs/revenue/billing-handoff.mdx(three locales) with"line_number": 1in the worked example.So the app hands the billing system a field that is null on every line item created in the product, and non-null only on demo seed rows. The docblock on that flow is explicit that the payload "IS the contract with the billing system" and is authored field-by-field so it cannot silently drift — this is a drift it did not catch, because the field is declared and merely never filled.
The decision this needs
Two coherent answers, and it is a product call, not a mechanical one:
_line-item-price-fill.tsalready establishes for this pair of objects. Because the field isreadonly, the writer has to be a system-context path — which puts it under AGENTS.md house rule 9 (elevate as little as possible), the same question Migrate this repo onto the @objectstack/* 17.4.0 line — the whole-line pin bump, the spec rename via the platform's own codemod, and the two contract changes it surfaces (epic #1579) #1807 settled forcrm_campaign_member.added_date. A line then carries a stable ordinal and the billing payload becomes truthful.LINE_ITEM_FIELDSand the three billing-handoff doc pages.crm_quote_line_item.line_numberhas exactly the same gap, and is the reason that field is reported standing on #1826 rather than given a view column — a column there would render blank on every row a user creates. Whichever answer is chosen should cover both objects, since the two line-item objects deliberately mirror each other.Refs: #1826 · #1807 (the readonly + elevation precedent) · #1667.