Skip to content

Commit 3a181f1

Browse files
fix: Salesforce Stricter Website querying to prevent wrong account match during contact owner check (#20133)
* Make website check stricter in contact ownership flow as well * Add test
1 parent c3abfa5 commit 3a181f1

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

packages/app-store/salesforce/lib/CrmService.test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -511,4 +511,13 @@ describe("SalesforceCRMService", () => {
511511
});
512512
});
513513
});
514+
515+
describe("getAllPossibleAccountWebsiteFromEmailDomain", () => {
516+
it("should return all possible account websites from email domain", () => {
517+
const result = service.getAllPossibleAccountWebsiteFromEmailDomain("example.com");
518+
expect(result).toEqual(
519+
"example.com, www.example.com, http://www.example.com, http://example.com, https://www.example.com, https://example.com"
520+
);
521+
});
522+
});
514523
});

packages/app-store/salesforce/lib/CrmService.ts

+35-8
Original file line numberDiff line numberDiff line change
@@ -883,20 +883,34 @@ export default class SalesforceCRMService implements CRM {
883883
});
884884
}
885885

886+
public getAllPossibleAccountWebsiteFromEmailDomain(emailDomain: string) {
887+
return [
888+
emailDomain,
889+
`www.${emailDomain}`,
890+
`http://www.${emailDomain}`,
891+
`http://${emailDomain}`,
892+
`https://www.${emailDomain}`,
893+
`https://${emailDomain}`,
894+
].join(", ");
895+
}
896+
886897
private async getAccountIdBasedOnEmailDomainOfContacts(email: string) {
887898
const conn = await this.conn;
888899
const emailDomain = email.split("@")[1];
889900
const log = logger.getSubLogger({ prefix: [`[getAccountIdBasedOnEmailDomainOfContacts]:${email}`] });
890901
log.info("getAccountIdBasedOnEmailDomainOfContacts", safeStringify({ email, emailDomain }));
891902
// First check if an account has the same website as the email domain of the attendee
892903
const accountQuery = await conn.query(
893-
`SELECT Id, Website FROM Account WHERE Website IN ('${emailDomain}', 'www.${emailDomain}',
894-
'http://www.${emailDomain}', 'http://${emailDomain}',
895-
'https://www.${emailDomain}', 'https://${emailDomain}') LIMIT 1`
904+
`SELECT Id, Website FROM Account WHERE Website IN (${this.getAllPossibleAccountWebsiteFromEmailDomain(
905+
emailDomain
906+
)}) LIMIT 1`
896907
);
897908
if (accountQuery.records.length > 0) {
898-
const account = accountQuery.records[0] as { Id: string };
899-
log.info("Found account based on email domain", safeStringify({ accountId: account.Id }));
909+
const account = accountQuery.records[0] as { Id: string; Website: string };
910+
log.info(
911+
"Found account based on email domain",
912+
safeStringify({ emailDomain, accountWebsite: account.Website, accountId: account.Id })
913+
);
900914
return account.Id;
901915
}
902916

@@ -923,13 +937,26 @@ export default class SalesforceCRMService implements CRM {
923937
log.info("Querying first account matching email domain", safeStringify({ emailDomain }));
924938
// First check if an account has the same website as the email domain of the attendee
925939
const accountQuery = await conn.query(
926-
`SELECT Id, OwnerId, Owner.Email FROM Account WHERE Website LIKE '%${emailDomain}%' LIMIT 1`
940+
`SELECT Id, OwnerId, Owner.Email FROM Account WHERE Website IN (${this.getAllPossibleAccountWebsiteFromEmailDomain(
941+
emailDomain
942+
)}) LIMIT 1`
927943
);
928944

929945
if (accountQuery.records.length > 0) {
930-
log.info("Found account matching email domain", safeStringify({ emailDomain }));
946+
const account = accountQuery.records[0] as {
947+
Id?: string;
948+
OwnerId?: string;
949+
Owner?: { Email?: string };
950+
Website?: string;
951+
};
952+
953+
log.info(
954+
"Found account matching email domain",
955+
safeStringify({ emailDomain, accountWebsite: account.Website, accountId: account.Id })
956+
);
957+
931958
return {
932-
...(accountQuery.records[0] as { Id?: string; OwnerId?: string; Owner?: { Email?: string } }),
959+
...account,
933960
Email: undefined,
934961
};
935962
}

packages/app-store/salesforce/lib/__tests__/CrmService.integration.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ describe("SalesforceCRMService", () => {
178178

179179
it("(Lookup-3) should fallback to account having most number of contacts matched by emailDomain when Lookup-1 and Lookup-2 fails", async () => {
180180
const crmService = new SalesforceCRMService(credential, appOptions);
181-
const account1OwnerEmail = "contact-account-owner1@example.com";
182-
const account2OwnerEmail = "contact-account-owner2@example.com";
181+
const account1OwnerEmail = "account1-owner@example.com";
182+
const account2OwnerEmail = "account2-owner@example.com";
183183
const emailDomain = "example.com";
184184
const lookingForEmail = `test@${emailDomain}`;
185185
const account1 = salesforceMock.addAccount({

packages/app-store/salesforce/lib/__tests__/salesforceMock.ts

+10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const createSalesforceMock = () => {
4545
// Query parser and responder
4646
const handleQuery = (query: string) => {
4747
// Simple SOQL parser
48+
console.log({ query });
4849
const fromMatch = query.match(/FROM\s+(\w+)/i);
4950
const whereMatch = query.match(/WHERE\s+(.+?)(?:\s+LIMIT|\s+ORDER|\s*$)/i);
5051
const limitMatch = query.match(/LIMIT\s+(\d+)/i);
@@ -77,6 +78,7 @@ export const createSalesforceMock = () => {
7778
return { records: [] };
7879
}
7980

81+
console.log({ whereClause });
8082
// Apply where clause filtering (basic implementation)
8183
if (whereClause) {
8284
if (whereClause.includes("Email =")) {
@@ -134,6 +136,14 @@ export const createSalesforceMock = () => {
134136
}
135137
}
136138

139+
if (whereClause.includes("Website IN")) {
140+
const websitesMatch = whereClause.match(/Website IN \((.+)\)/i);
141+
if (websitesMatch) {
142+
const websites = websitesMatch[1].split(",").map((w) => w.trim());
143+
result = result.filter((r) => websites.includes(r.Website));
144+
}
145+
}
146+
137147
if (whereClause.includes("IsActive = true")) {
138148
result = result.filter((r) => r.IsActive === true);
139149
}

0 commit comments

Comments
 (0)