Description
There is no general-purpose way to read a base field from the source instance of an AssignmentRelationship. Resources that need to surface such a field must write bespoke calculation modules by hand, repeating the same traversal logic each time.
The NBN case is the clearest example: an AVC wants to surface the name of the CVC that assigned it an svlan — that name serves as the CVC ID on the AVC. The CVC is the source of an AssignmentRelationship where the AVC is the target. Without a shared calculation module the AVC must contain custom traversal code.
What we need
A calculation module Diffo.Provider.Calculations.FieldViaAssignedRelationship with arguments mirroring inherited_place / inherited_party:
via: — optional list of alias steps. When provided, filters AssignmentRelationship by target_id = current.id, alias = step. When omitted, traverses all AssignmentRelationship records where target_id = current.id with no alias filter. Multi-hop is supported by chaining steps.
field: — the field name to read from the resolved source instance (analogous to source_role: on inherited_place).
Both forms return a list of field values, consistent with inherited_place and inherited_party.
# Aliased — field from the source holding the :svlan assignment slot
calculate :cvc_id, :string,
{Diffo.Provider.Calculations.FieldViaAssignedRelationship, [via: [:svlan], field: :name]}
# Unaliased — field from any instance that assigned something to this one
calculate :assigner_name, :string,
{Diffo.Provider.Calculations.FieldViaAssignedRelationship, [field: :name]}
Why it matters
Layered service graphs routinely need to surface fields from assigning instances — CVC ID on an AVC, NNI name on a CVC, assigner name on an assigned resource. These are all the same pattern: traverse an assignment by alias (or without), read a field. A shared calculation module eliminates the repeated boilerplate and enables a consistent demo path.
Description
There is no general-purpose way to read a base field from the source instance of an
AssignmentRelationship. Resources that need to surface such a field must write bespoke calculation modules by hand, repeating the same traversal logic each time.The NBN case is the clearest example: an AVC wants to surface the name of the CVC that assigned it an svlan — that name serves as the CVC ID on the AVC. The CVC is the source of an
AssignmentRelationshipwhere the AVC is the target. Without a shared calculation module the AVC must contain custom traversal code.What we need
A calculation module
Diffo.Provider.Calculations.FieldViaAssignedRelationshipwith arguments mirroringinherited_place/inherited_party:via:— optional list of alias steps. When provided, filtersAssignmentRelationshipbytarget_id = current.id, alias = step. When omitted, traverses allAssignmentRelationshiprecords wheretarget_id = current.idwith no alias filter. Multi-hop is supported by chaining steps.field:— the field name to read from the resolved source instance (analogous tosource_role:oninherited_place).Both forms return a list of field values, consistent with
inherited_placeandinherited_party.Why it matters
Layered service graphs routinely need to surface fields from assigning instances — CVC ID on an AVC, NNI name on a CVC, assigner name on an assigned resource. These are all the same pattern: traverse an assignment by alias (or without), read a field. A shared calculation module eliminates the repeated boilerplate and enables a consistent demo path.