refactor: standardize quotation marks across all files and improve code consistency
This commit is contained in:
@@ -1,40 +1,45 @@
|
||||
import type { OFXAccount, OFXTransaction } from "./types"
|
||||
import type { OFXAccount, OFXTransaction } from "./types";
|
||||
|
||||
export function parseOFX(content: string): OFXAccount | null {
|
||||
try {
|
||||
// Remove SGML header and clean up
|
||||
const xmlStart = content.indexOf("<OFX>")
|
||||
if (xmlStart === -1) return null
|
||||
const xmlStart = content.indexOf("<OFX>");
|
||||
if (xmlStart === -1) return null;
|
||||
|
||||
let xml = content.substring(xmlStart)
|
||||
let xml = content.substring(xmlStart);
|
||||
|
||||
// Convert SGML to XML-like format
|
||||
xml = xml.replace(/<(\w+)>([^<]+)(?=<)/g, "<$1>$2</$1>")
|
||||
xml = xml.replace(/<(\w+)>([^<]+)(?=<)/g, "<$1>$2</$1>");
|
||||
|
||||
// Extract account info
|
||||
const bankId = extractValue(xml, "BANKID") || extractValue(xml, "ORG") || "UNKNOWN"
|
||||
const accountId = extractValue(xml, "ACCTID") || "UNKNOWN"
|
||||
const accountType = extractValue(xml, "ACCTTYPE") || "CHECKING"
|
||||
const balanceStr = extractValue(xml, "BALAMT") || "0"
|
||||
const balance = Number.parseFloat(balanceStr)
|
||||
const balanceDate = extractValue(xml, "DTASOF") || new Date().toISOString()
|
||||
const currency = extractValue(xml, "CURDEF") || "EUR"
|
||||
const bankId =
|
||||
extractValue(xml, "BANKID") || extractValue(xml, "ORG") || "UNKNOWN";
|
||||
const accountId = extractValue(xml, "ACCTID") || "UNKNOWN";
|
||||
const accountType = extractValue(xml, "ACCTTYPE") || "CHECKING";
|
||||
const balanceStr = extractValue(xml, "BALAMT") || "0";
|
||||
const balance = Number.parseFloat(balanceStr);
|
||||
const balanceDate = extractValue(xml, "DTASOF") || new Date().toISOString();
|
||||
const currency = extractValue(xml, "CURDEF") || "EUR";
|
||||
|
||||
// Extract transactions
|
||||
const transactions: OFXTransaction[] = []
|
||||
const stmtTrnRegex = /<STMTTRN>([\s\S]*?)<\/STMTTRN>/gi
|
||||
let match
|
||||
const transactions: OFXTransaction[] = [];
|
||||
const stmtTrnRegex = /<STMTTRN>([\s\S]*?)<\/STMTTRN>/gi;
|
||||
let match;
|
||||
|
||||
while ((match = stmtTrnRegex.exec(xml)) !== null) {
|
||||
const trnXml = match[1]
|
||||
const trnXml = match[1];
|
||||
|
||||
const fitId = extractValue(trnXml, "FITID") || `${Date.now()}-${Math.random()}`
|
||||
const dateStr = extractValue(trnXml, "DTPOSTED") || ""
|
||||
const amountStr = extractValue(trnXml, "TRNAMT") || "0"
|
||||
const name = extractValue(trnXml, "NAME") || extractValue(trnXml, "MEMO") || "Unknown"
|
||||
const memo = extractValue(trnXml, "MEMO")
|
||||
const checkNum = extractValue(trnXml, "CHECKNUM")
|
||||
const type = extractValue(trnXml, "TRNTYPE") || "OTHER"
|
||||
const fitId =
|
||||
extractValue(trnXml, "FITID") || `${Date.now()}-${Math.random()}`;
|
||||
const dateStr = extractValue(trnXml, "DTPOSTED") || "";
|
||||
const amountStr = extractValue(trnXml, "TRNAMT") || "0";
|
||||
const name =
|
||||
extractValue(trnXml, "NAME") ||
|
||||
extractValue(trnXml, "MEMO") ||
|
||||
"Unknown";
|
||||
const memo = extractValue(trnXml, "MEMO");
|
||||
const checkNum = extractValue(trnXml, "CHECKNUM");
|
||||
const type = extractValue(trnXml, "TRNTYPE") || "OTHER";
|
||||
|
||||
transactions.push({
|
||||
fitId,
|
||||
@@ -44,7 +49,7 @@ export function parseOFX(content: string): OFXAccount | null {
|
||||
memo: memo ? cleanString(memo) : undefined,
|
||||
checkNum: checkNum ?? undefined,
|
||||
type,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -55,37 +60,39 @@ export function parseOFX(content: string): OFXAccount | null {
|
||||
balanceDate: parseOFXDate(balanceDate),
|
||||
currency,
|
||||
transactions,
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error parsing OFX:", error)
|
||||
return null
|
||||
console.error("Error parsing OFX:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function extractValue(xml: string, tag: string): string | null {
|
||||
const regex = new RegExp(`<${tag}>([^<]+)`, "i")
|
||||
const match = xml.match(regex)
|
||||
return match ? match[1].trim() : null
|
||||
const regex = new RegExp(`<${tag}>([^<]+)`, "i");
|
||||
const match = xml.match(regex);
|
||||
return match ? match[1].trim() : null;
|
||||
}
|
||||
|
||||
function parseOFXDate(dateStr: string): string {
|
||||
if (!dateStr || dateStr.length < 8) return new Date().toISOString()
|
||||
if (!dateStr || dateStr.length < 8) return new Date().toISOString();
|
||||
|
||||
const year = dateStr.substring(0, 4)
|
||||
const month = dateStr.substring(4, 6)
|
||||
const day = dateStr.substring(6, 8)
|
||||
const year = dateStr.substring(0, 4);
|
||||
const month = dateStr.substring(4, 6);
|
||||
const day = dateStr.substring(6, 8);
|
||||
|
||||
return `${year}-${month}-${day}`
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
function mapAccountType(type: string): "CHECKING" | "SAVINGS" | "CREDIT_CARD" | "OTHER" {
|
||||
const upper = type.toUpperCase()
|
||||
if (upper.includes("CHECK") || upper.includes("CURRENT")) return "CHECKING"
|
||||
if (upper.includes("SAV")) return "SAVINGS"
|
||||
if (upper.includes("CREDIT")) return "CREDIT_CARD"
|
||||
return "OTHER"
|
||||
function mapAccountType(
|
||||
type: string,
|
||||
): "CHECKING" | "SAVINGS" | "CREDIT_CARD" | "OTHER" {
|
||||
const upper = type.toUpperCase();
|
||||
if (upper.includes("CHECK") || upper.includes("CURRENT")) return "CHECKING";
|
||||
if (upper.includes("SAV")) return "SAVINGS";
|
||||
if (upper.includes("CREDIT")) return "CREDIT_CARD";
|
||||
return "OTHER";
|
||||
}
|
||||
|
||||
function cleanString(str: string): string {
|
||||
return str.replace(/\s+/g, " ").trim()
|
||||
return str.replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user