Skip to content

finances: pcmc.ts converted to new format#17

Merged
denversc merged 1 commit into
mainfrom
unify3
Jun 23, 2026
Merged

finances: pcmc.ts converted to new format#17
denversc merged 1 commit into
mainfrom
unify3

Conversation

@denversc

Copy link
Copy Markdown
Owner

No description provided.

@denversc
denversc merged commit 0743b6a into main Jun 23, 2026
3 checks passed
@denversc
denversc deleted the unify3 branch June 23, 2026 14:18

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Comment on lines +54 to +105
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);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The current implementation of transformMonthNameToNumber is fragile and represents a regression in robustness compared to the previous implementation in finances/pcmc.ts.

Specifically:

  1. It relies on exact substring matching of hardcoded month names (some with dots like 'Jan.', others without like 'May').
  2. 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 a DocumentParseError.
  3. 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);
}

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant