Skip to content

Commit da2f356

Browse files
committed
cleaned up the matching logic
1 parent 11c155e commit da2f356

2 files changed

Lines changed: 35 additions & 22 deletions

File tree

functions/src/ocpf/matchOcpfMembers.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import {
1313
OcpfMemberMappingFlagsEntry
1414
} from "./types"
1515

16-
// TODO: Convert to onCall once tested. Use checkAuth(context) + checkAdmin(context)
17-
// from ../common.ts — both utilities handle admin role checking automatically.
1816
export const matchOcpfMembers = functions.https.onRequest(async (req, res) => {
17+
if (req.method !== "POST") {
18+
res.status(405).send("Method Not Allowed. Use POST.")
19+
return
20+
}
1921
if (process.env.FUNCTIONS_EMULATOR !== "true") {
2022
const authHeader = req.headers.authorization
2123
if (!authHeader?.startsWith("Bearer ")) {
@@ -50,39 +52,51 @@ export const matchOcpfMembers = functions.https.onRequest(async (req, res) => {
5052

5153
if (!branch || (branch !== "Senate" && branch !== "House")) continue
5254

53-
const lastNameMatches = filers.filter(
55+
const lastNameAndBranchMatches = filers.filter(
5456
f =>
5557
f.lastName.toLowerCase() === lastName.toLowerCase() &&
5658
f.officeSought === branch
5759
)
5860

5961
// Narrow by first name: compare first word of each (e.g. "Daniel" from "Daniel J. Ryan"
60-
// vs "Daniel" from "Daniel Joseph"). Falls back to all last-name matches if none align.
62+
// vs "Daniel" from "Daniel Joseph"). If none align, falls back to matches by last name and branch.
6163
const mapleFirstName = member.Name.trim().split(/\s+/)[0].toLowerCase()
62-
const firstNameMatches = lastNameMatches.filter(
64+
const firstNameMatches = lastNameAndBranchMatches.filter(
6365
f => f.firstName.trim().split(/\s+/)[0].toLowerCase() === mapleFirstName
6466
)
6567
const candidates =
66-
firstNameMatches.length > 0 ? firstNameMatches : lastNameMatches
68+
firstNameMatches.length > 0 ? firstNameMatches : lastNameAndBranchMatches
6769

68-
if (candidates.length === 1) {
69-
if (firstNameMatches.length === 0) {
70-
functions.logger.warn("Last name matched but first name did not align", {
71-
memberCode: member.MemberCode,
72-
name: member.Name,
73-
district: member.District,
74-
branch,
75-
ocpfFirstName: candidates[0].firstName,
76-
ocpfLastName: candidates[0].lastName
77-
})
78-
}
70+
if (firstNameMatches.length === 1) {
7971
const entry: OcpfMemberMappingEntry = {
8072
cpfId: candidates[0].cpfId,
8173
name: member.Name
8274
}
8375
mapping[member.MemberCode] = entry
76+
77+
// Matching was likley fixed manually
78+
} else if (member.MemberCode in existingMapping) {
79+
continue
80+
81+
// Single last name match but first name didn't align. Flag rather than auto-match,
82+
// since the OCPF filer may be a different person (e.g. original member changed office sought,
83+
// and another person with same last name is running for original office).
84+
} else if (candidates.length === 1 && firstNameMatches.length === 0) {
85+
ambiguous.push({ memberCode: member.MemberCode, name: member.Name })
86+
functions.logger.warn(
87+
"Single last-name match but first name did not align",
88+
{
89+
memberCode: member.MemberCode,
90+
name: member.Name,
91+
district: member.District,
92+
branch,
93+
ocpfFirstName: candidates[0].firstName,
94+
ocpfLastName: candidates[0].lastName,
95+
ocpfDistrict: candidates[0].district,
96+
ocpfOfficeSought: candidates[0].officeSought
97+
}
98+
)
8499
} else if (candidates.length === 0) {
85-
if (member.MemberCode in existingMapping) continue
86100
unmatched.push({ memberCode: member.MemberCode, name: member.Name })
87101
functions.logger.warn("No OCPF match", {
88102
memberCode: member.MemberCode,
@@ -91,7 +105,6 @@ export const matchOcpfMembers = functions.https.onRequest(async (req, res) => {
91105
branch
92106
})
93107
} else {
94-
if (member.MemberCode in existingMapping) continue
95108
ambiguous.push({ memberCode: member.MemberCode, name: member.Name })
96109
functions.logger.warn("Ambiguous OCPF match", {
97110
memberCode: member.MemberCode,
@@ -102,7 +115,8 @@ export const matchOcpfMembers = functions.https.onRequest(async (req, res) => {
102115
cpfId: c.cpfId,
103116
firstName: c.firstName,
104117
lastName: c.lastName,
105-
district: c.district
118+
district: c.district,
119+
officeSought: c.officeSought
106120
}))
107121
})
108122
}
@@ -165,7 +179,6 @@ async function downloadAndParseFilers(): Promise<OcpfFilerRow[]> {
165179
"closedDate"
166180
])
167181

168-
169182
// Values in the file are wrapped in double quotes — strip them after splitting
170183
const col = (cols: string[], idx: number) =>
171184
(cols[idx] ?? "").trim().replace(/^"|"$/g, "")

functions/src/ocpf/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ export interface MembersFinanceBreakdown {
4040
committee: FinanceBreakdownEntry
4141
union: FinanceBreakdownEntry
4242
unitemized: { amount: number }
43-
}
43+
}

0 commit comments

Comments
 (0)