[SOA]: Bugbash for releases 28.x - Contact unable to find due to Qasim map to Megan, different names - #10036
[SOA]: Bugbash for releases 28.x - Contact unable to find due to Qasim map to Megan, different names#10036tomasevicst wants to merge 9 commits into
Conversation
- Updated instructions for selecting contacts and customers in the Sales Order Agent. - Introduced a new codeunit for contact search implementation. - Refactored email message handling to utilize mapped contact emails. - Added support for alternative email addresses in contact list and filters. - Implemented event triggers for contact search in the Contact List page.
Pull request was closed
Agentic PR Review - Round 1Recommendation: Accept with SuggestionsWhat this PR doesThis PR fixes contact lookup and reply routing in the Sales Order Agent when the incoming sender's email is mapped to a different contact. When a user chooses "Use another contact once", the selected contact is stored in The core design is correct. SuggestionsS1 - Page customization overrides dynamic E-Mail 2 visibility S2 - No test files in the diff S3 - Comment in Risk assessment and necessityRisk: Security filtering is the most sensitive area. Necessity: The scenario is valid and important: a mapped contact (Qasim → Megan) caused the agent to stall at contact selection because the selected contact did not match the sender identity. The fix cleanly addresses the root cause by extending the lookup and filtering to honor both the task override and the E-Mail 2 mapping, rather than patching the agent instructions alone. The scope is appropriate.
|
|
When an override or uniquely-matched contact exists but its primary email is blank, GetSentMessageToAddress falls back to SentAgentTaskMessage.From and still returns true. That makes the message history and page show the original sender as the reply target, even though SOASendReply later rejects the same mapping with MappedContactEmailMissingErr. Reuse the same mapped-contact validation here and surface the mapping problem instead of silently displaying a different address than what would actually be used. Agent judgement — not directly backed by a BCQuality knowledge article. Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.31.4 |
…g contact validation, and refining email reply logic
…, refining email handling, and improving error messaging
|
The new OnBeforeFindRecord subscriber (FindRecordContact) issues Agent Task Message and SOA Task Contact Override database reads on every Contact List find/navigation once AgentTaskID is set, with no caching of the resolved contact or short-circuit for repeated calls within the same page instance. Because OnFindRecord/OnBeforeFindRecord is invoked on every list navigation step (paging, search, refresh), this re-runs the same lookup chain repeatedly instead of resolving once per page open. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.31.4 |
… trusted contact overrides
…and optimize matched contact storage
| /// Ensures that a mapping is changed only for an existing input message by its configured owner or agent. | ||
| /// Internal procedures are not an authorization boundary, so every override and alternate-email write path calls this validation. | ||
| /// </summary> | ||
| local procedure ValidateContactMappingAccess(TaskID: BigInteger; TaskMessageID: Guid) |
There was a problem hiding this comment.
The owner/agent identity-resolution rule ("use SOA Setup's Owner User Security ID, falling back to User Security ID when null, then compare against the acting identity") is independently re-implemented three times: SOASendReply.Codeunit.al's IsAuthorizedUserSecurityID (line 133), SOAFiltersImpl.Codeunit.al's IsContactOverrideTrusted (line 128), and SOAFiltersImpl.Codeunit.al's ValidateContactMappingAccess (line 307). All three gate security-sensitive actions (sending a redirected reply, trusting a contact override, and changing a contact mapping). Because the logic is copy-pasted rather than centralized, a future change to the ownership/fallback rule (e.g., adding a delegate or co-owner concept) risks being applied to only some call sites, silently reintroducing an authorization bypass in the others. Extract this rule into a single shared procedure (e.g., on "SOA Setup" or a shared helper codeunit) and have all three call sites use it.
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.31.4
Agentic PR Review - Round 2Recommendation: Accept with SuggestionsWhat this PR doesThis PR extends the round-1 changes with authorization and provenance guards, BCC-preservation in mapped replies, and a refactored email-lookup layer shared across all callers. The key additions are The round-2 changes are correct. The Status of previous suggestions
New observations (commits since round 1)No new High-confidence findings. One low-priority observation below. S4 - Reply fails silently when source email record is deleted Risk assessment and necessityRisk: The provenance check ( Necessity: The round-2 changes are necessary. Without the provenance and authorization guards, a user with contact write rights could create or modify an override row and affect security filtering or reply routing for another user's SOA session. The shared
|
What & why
Fixes contact lookup and reply routing for Sales Order Agent tasks when the sender’s email address is mapped to a different contact.
When an unknown sender is handled with Use another contact once, the selected contact is stored in SOA Task Contact Override. The Contact List now exposes a find-record event that is handled only during Sales Order Agent sessions. The handler resolves the override for the latest active input message and surfaces the mapped contact to the agent, even when its name or email address differs from the original sender.
When Use another contact always is selected, the sender’s address is stored in the contact’s E-Mail 2 field. Contact lookup, security filtering, known-sender classification, and message recipient resolution now consider both E-Mail and E-Mail 2. The additional email field is displayed on the Contact List only during an active Sales Order Agent session.
Reply routing also respects these mappings. Replies remain in the original email thread but are addressed to the mapped contact’s primary email address, while preserving the original CC and BCC recipients. When no mapping exists, the existing Reply All behavior remains unchanged.
The contact-search subscriber is manually bound from SOA Session Events, so it affects only Sales Order Agent sessions. Agent instructions were also updated to accept the mapped contact as authoritative and continue quote creation without requesting assistance solely because the selected contact does not match the sender’s identity.
Linked work
Fixes AB#640657
How I validated this
What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)
Risk & compatibility
The change is limited to Sales Order Agent sessions. The contact-search subscriber is manually bound during SOA session initialization, and the E-Mail 2 field is visible on the Contact List only while an SOA agent task is active. Standard Contact List behavior remains unchanged for non-agent sessions.
The new Contact List OnBeforeFindRecord integration event is added to both W1 and APAC Base App implementations. When no subscriber handles the event, the page continues using its existing Rec.Find(Which) behavior.
Contact matching now includes E-Mail 2. Existing contacts without an alternate email retain their current behavior. If the same email matches multiple contacts, the existing duplicate-contact handling remains in effect rather than selecting a mapped recipient ambiguously.
Reply routing changes only when an exact task-message override exists or the sender uniquely matches a contact through E-Mail 2. In that case, the reply is intentionally addressed to the mapped contact’s primary email while preserving the original thread and CC/BCC recipients. Without a mapping, the existing Reply All path is unchanged.
The Contact List override is resolved against the latest active input message using the full (Task ID, Task Message ID) identity. This avoids selecting an older or unrelated mapping in tasks containing multiple messages.