- Shipped
- August 5, 2026 at 12:10 AM UTC
- Author
- Kamo
- Commit
- 7727c77
An approver can hand an opportunity — and the commission with it — to a different agent. PRIMARY_AGENT_MEMBER_ID is who holds it now; REQUESTED_BY_MEMBER_ID is never written again, because who found the deal is a fact about the past and overwriting it would erase the only record that the original agent brought it in. Null means "never reassigned", which is a different statement from "reassigned back to the requester" — so existing rows are left alone rather than backfilled. effectiveAgentMemberId() is the holder, and it is what now decides who may ask for an extension and who the lead header treats as the owner. Once an opportunity moves, the original requester is a name in the history, not a claim on it. Nine canonical templates cover the lifecycle: a request or extension request goes to everyone who can decide it; every approval, denial, edit, extension ruling, expiry and close goes to the agent holding it, the agent who asked if that is now someone else, and every colleague on a commission split. They share one generated shell so the layout cannot drift between them, and one variable set so a template can reference anything without a matching Java change — which matters because a missing variable renders as an empty string with only a WARN, and ships an email reading "reserved until ".