Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the PDF parsing utility options by replacing resultPrefix with a more flexible resultTransform function, and integrates the PC Mastercard statement parser into the main finances documents framework while removing the old standalone script. Feedback on the changes highlights that the new transformMonthNameToNumber implementation is fragile compared to the previous version because it relies on exact substring matches of hardcoded month names. A more robust regex-based prefix-matching approach is suggested to handle variations in month abbreviations.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const monthNumberByName = Object.freeze({ | ||
| "Jan.": "01", | ||
| "Feb.": "02", | ||
| "Mar.": "03", | ||
| "Apr.": "04", | ||
| May: "05", | ||
| June: "06", | ||
| July: "07", | ||
| "Aug.": "08", | ||
| "Sept.": "09", | ||
| "Oct.": "10", | ||
| "Nov.": "11", | ||
| "Dec.": "12", | ||
| } as const); | ||
|
|
||
| function transformMonthNameToNumber(s: string): string | DocumentParseError { | ||
| const replacements: Array<{ monthName: string; monthNumber: string }> = []; | ||
|
|
||
| const months = Object.entries(monthNumberByName) as Readonly< | ||
| Array<Readonly<[keyof typeof monthNumberByName, string]>> | ||
| >; | ||
| for (const [monthName, monthNumber] of months) { | ||
| if (s.includes(monthName)) { | ||
| replacements.push({ monthName, monthNumber }); | ||
| } | ||
| } | ||
|
|
||
| const replacement = replacements[0]; | ||
| if (!replacement) { | ||
| return { | ||
| type: "DocumentParseError", | ||
| message: | ||
| `unrecognized month name in date: ${s} ` + | ||
| `(recognized month names are: ` + | ||
| Object.getOwnPropertyNames(monthNumberByName).join(", ") + | ||
| `)`, | ||
| }; | ||
| } else if (replacements.length > 1) { | ||
| return { | ||
| type: "DocumentParseError", | ||
| message: | ||
| `${replacements.length} month names recognized in date, ` + | ||
| `but expected exactly 1: ${s} ` + | ||
| `(recognized month names: ` + | ||
| replacements.map((entry) => entry.monthName).join(", ") + | ||
| `)`, | ||
| }; | ||
| } | ||
|
|
||
| const { monthName, monthNumber } = replacement; | ||
| return s.replace(monthName, monthNumber); | ||
| } |
There was a problem hiding this comment.
The current implementation of transformMonthNameToNumber is fragile and represents a regression in robustness compared to the previous implementation in finances/pcmc.ts.
Specifically:
- It relies on exact substring matching of hardcoded month names (some with dots like
'Jan.', others without like'May'). - If a PDF statement uses a different abbreviation (e.g.,
'Sep.'instead of'Sept.', or'Jul.'instead of'July'), or omits/adds a period, the parsing will fail with aDocumentParseError. - The previous implementation was much more robust: it extracted the month name, took the first 3 characters, lowercased them, and mapped them.
We can restore and improve upon that robustness by matching the leading month word with a regular expression, extracting its 3-letter prefix, and replacing it safely using string slicing.
const monthNumberByPrefix: Record<string, string> = {
jan: '01',
feb: '02',
mar: '03',
apr: '04',
may: '05',
jun: '06',
jul: '07',
aug: '08',
sep: '09',
oct: '10',
nov: '11',
dec: '12',
};
function transformMonthNameToNumber(s: string): string | DocumentParseError {
const match = s.match(/^([A-Za-z]+)(\\.?)/);
if (!match) {
return {
type: 'DocumentParseError',
message: 'unrecognized date format: ' + s,
};
}
const [fullMatch, monthStr] = match;
const prefix = monthStr.toLowerCase().substring(0, 3);
const monthNumber = monthNumberByPrefix[prefix];
if (!monthNumber) {
return {
type: 'DocumentParseError',
message:
'unrecognized month name in date: ' + s + ' ' +
'(recognized month prefixes are: ' +
Object.keys(monthNumberByPrefix).join(', ') +
')',
};
}
return monthNumber + s.slice(fullMatch.length);
}
No description provided.