Allow a calculated action on a to-one relation - #6687
Open
delchev wants to merge 1 commit into
Open
Conversation
A to-one relation could not express a DERIVED default. `init:` covers the fixed case (a literal target seed id), but nothing covered "read it off another record" - a sales document's currency defaulting from its company's base currency. The adjacent hooks all fall short by design: `dependsOn` is a UI-only cascade that never fires on a server-side create, and the `setRelationField` process step takes a literal id too. Authoring `calculatedActionOnCreate` on a relation looked like it should work and silently did nothing: the typed mapping is Gson, which ignores unknown properties, so the key was dropped at parse time with no error - the #6541 family, one level up from seed rows. RelationIntent gains calculatedActionOnCreate/OnUpdate + isCalculated(), and the new shared EdmIntentGenerator.putCalculatedAction emits isCalculatedProperty plus the action names from BOTH relation builders (same-model relationProperty and crossModelRelationProperty). The DAO template needed NO change, which is the point worth recording: a relation is already an ordinary property in the .model - the FK column, typed to the target's key - so the template's shared property loop and its actionAssign macro emit `entity.<Relation> = Beans.get(<class>.class).calculate(entity);` against the Integer FK with no new branch. The gap was engine-only, so consuming it needs a jar swap and no registry re-seed. The parser rejects the combination where there is no single FK to assign, or where the value is not the author's to set: a collection relation, a composition parent (preset by the layout) and an EntityStatus badge (owned by the workflow transitions - `init:` is its starting-value hook). Tests: EdmIntentGeneratorTest asserts the three emitted keys on both builders and that an action-less relation stays unmarked; IntentParserTest asserts the key binds onto the model (the typed-mapping test is the regression guard for the silent drop) and that a collection relation is rejected. Full engine-intent suite 406 green. NOT done, owed: an IntentEmissionCoverageIT case. That fixture has no calculated action of either kind today, and adding one needs a compilable custom/ class in the emission-test project - a generated repository referencing a missing class fails the whole client-Java batch and with it every REST assertion in that gate. Left for a change that can run the gate rather than guessed at.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A to-one relation could not express a DERIVED default.
init:covers the fixed case (a literal target seed id), but nothing covered "read it off another record" — a sales document's currency defaulting from its company's base currency. The adjacent hooks all fall short by design:dependsOnis a UI-only cascade that never fires on a server-side create, and thesetRelationFieldprocess step takes a literal id too.Authoring
calculatedActionOnCreateon a relation looked like it should work and silently did nothing: the typed mapping is Gson, which ignores unknown properties, so the key was dropped at parse time with no error — the #6541 family, one level up from seed rows.Changes
RelationIntentgainscalculatedActionOnCreate/OnUpdate+isCalculated().EdmIntentGenerator.putCalculatedActionemitsisCalculatedPropertyplus the action names from BOTH relation builders (same-modelrelationPropertyandcrossModelRelationProperty)..model— the FK column, typed to the target's key — so the template's shared property loop and itsactionAssignmacro emitentity.<Relation> = Beans.get(<class>.class).calculate(entity);against the Integer FK with no new branch. The gap was engine-only, so consuming it needs a jar swap and no registry re-seed.init:is its starting-value hook).Tests
EdmIntentGeneratorTestasserts the three emitted keys on both builders and that an action-less relation stays unmarked.IntentParserTestasserts the key binds onto the model (the typed-mapping test is the regression guard for the silent drop) and that a collection relation is rejected.Owed: an
IntentEmissionCoverageITcase — the fixture has no calculated action of either kind today, and adding one needs a compilablecustom/class in the emission-test project; left for a change that can run that gate.🤖 Generated with Claude Code