Skip to content

[SOA]: Bugbash for releases 28.x - Contact unable to find due to Qasim map to Megan, different names#9263

Open
tomasevicst wants to merge 3 commits into
mainfrom
bugs/640657_SOA_Unable_to_Find_Mapped_Contact
Open

[SOA]: Bugbash for releases 28.x - Contact unable to find due to Qasim map to Megan, different names#9263
tomasevicst wants to merge 3 commits into
mainfrom
bugs/640657_SOA_Unable_to_Find_Mapped_Contact

Conversation

@tomasevicst

@tomasevicst tomasevicst commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Issue

Bug #640657: Agent unable to find mapped contacts in Contact List

When an agent maps an unknown sender email to a contact using the "Use another contact once" option, the mapping is stored in the SOATaskContactOverride table but remains invisible in the Contact List. This prevents agents from discovering the contact-to-email relationship and finding the correct contact when browsing the list.

Root Cause

The Contact List page did not expose:

  1. Temporarily mapped emails (from "Use another contact once" option) stored in SOATaskContactOverride
  2. Permanently mapped emails (from "Use another contact always" option) stored in Contact's "E-Mail 2" field

Agents had no visibility into these mappings, making it difficult to find contacts by their mapped email addresses.

Solution

Enhanced the Contact List page with new fields visible only during agent sessions:

Changes Made

  1. Page Extension: SOAContactListExt
  • File: [SOAContactListExt.PageExt.al] (new)
  • Added two new columns visible only for agent sessions:
    • "Mapped Email" (read-only): Displays email from SOATaskContactOverride for current task
    • "E-Mail 2": Displays the contact's secondary email field
  1. Modified Contact Email Assignment
  • File: [SOAFiltersImpl.Codeunit.al]
  • Changed SelectContactAndUpdateEmail() procedure to store emails in "E-Mail 2" instead of "E-Mail"
  • Updated confirmation dialog label to ContactAlreadyHasEmail2Qst
  • Rationale: Preserves primary email while allowing multiple mappings per contact
  1. Agent Session Visibility Control
  • Leverages existing SOAKPITrackAll.IsOrderTakerAgentSession() pattern
  • Fields display only during active agent sessions
  • Non-agent users see standard Contact List without mapped email fields

User Experience Impact

Before

  • Agent sees: Contact No., Name, Email, Phone, etc. (no mapping information)
  • Cannot find contact by mapped email address
  • Mapping intent unknown

After

  • Agent sees three email columns:
    • E-Mail: Primary contact email
    • Mapped Email: Sender email from current task mapping (if "Use another contact once" was used)
    • E-Mail 2: Permanent alternate email (if "Use another contact always" was used)
  • Can now easily identify and locate mapped contacts
  • Clear visibility into email mapping status

Backward Compatibility

✓ Fully backward compatible — No breaking changes

  • New page extension fields only visible in agent sessions
  • Existing Contact record structure unchanged
  • Non-agent workflows unaffected

What & why

Linked work

Fixes AB#640657

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

Risk & compatibility

@tomasevicst tomasevicst requested a review from a team July 8, 2026 21:00
@github-actions github-actions Bot added the AL: Apps (W1) Add-on apps for W1 label Jul 8, 2026
@github-actions github-actions Bot added this to the Version 29.0 milestone Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Copilot PR Review

Iteration 3 · Outcome: completed

Knowledge source: https://github.com/microsoft/BCQuality@822cae1b2771ac25f665f73369f69093bd4fd630

Findings by domain

Findings split into Knowledge-backed (cite a BCQuality article) and Agent (the agent's own judgement, no matching BCQuality rule).

Domain Findings Knowledge-backed Agent Inline Fallback
Performance 1 1 0 1 0

Totals: 1 knowledge-backed · 0 agent findings.

Orchestrator pre-filter (13 file(s) excluded)

  • layer-disabled (knowledge) : 13 file(s)

Findings produced by the Copilot CLI agent against BCQuality at 822cae1b2771ac25f665f73369f69093bd4fd630. Reply 👎 on any inline comment to flag false positives.

if ContactList.RunModal() <> Action::LookupOK then
exit;
ContactList.GetRecord(SelectedContact);
if SelectedContact."E-Mail" <> '' then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Security} \quad \color{gray}{\texttt{\small Iteration\ 2}}$

In SelectContactAndUpdateEmail (the 'Use another contact always' flow), the sender's email is now written to Contact."E-Mail 2" instead of Contact."E-Mail".

Every read path that recognizes a contact by incoming sender address still filters exclusively on "E-Mail": GetContactsInvolvedInTask's Contact.SetFilter("E-Mail", From) (which feeds GetSecurityFiltersForContacts, the agent session's security/access filter), CreateContact's existing-contact check, SOAEmailMessage.Page.al, SOATaskMessage.Codeunit.al, and SOACreateTask.Page.al all match only on "E-Mail". No code in the app reads "E-Mail 2" for sender matching. As a result, choosing 'Use another contact always' silently stops working as 'always': the next incoming email from the same sender will no longer be recognized as belonging to this contact by the security filter or by any of the other lookup call sites, defeating the intent of the feature. Although emitted here as minor per agent-finding policy, the real-world impact is a functional/security-filter regression (major) and should be fixed before merge — either write the resolved address back to "E-Mail" as before, or update GetContactsInvolvedInTask (and the other E-Mail-based lookups) to also match against "E-Mail 2".

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

Comment thread src/Apps/W1/SalesOrderAgent/app/src/PageExtention/SOAContactListExt.PageExt.al Outdated
IsAgentSession := SOAKPITrackAll.IsOrderTakerAgentSession(AgentTaskID);
end;

trigger OnAfterGetRecord()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Performance} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

PopulateMappedEmail runs from the page's OnAfterGetRecord trigger, so it executes once per rendered Contact List row when an order-taker agent session is active.

Each invocation issues up to two FindFirst round-trips (SOA Task Contact Override, then conditionally SOA Email) against tables that grow unboundedly with agent email volume, producing the classic per-row N+1 pattern the referenced guidance flags. SetLoadFields is already applied correctly on both reads, which limits the cost per round-trip but not the round-trip count itself. Consider whether the mapped-email lookup can be resolved with a single joined/keyed read, or cached per AgentTaskID across rows, to avoid two extra queries per displayed contact.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants