diff --git a/Services/BankStatementProcessor/HDFC.js/bankStatementProcessor-HDFC.js b/Services/BankStatementProcessor/HDFC.js/bankStatementProcessor-HDFC.js new file mode 100644 index 0000000..d2106ad --- /dev/null +++ b/Services/BankStatementProcessor/HDFC.js/bankStatementProcessor-HDFC.js @@ -0,0 +1,230 @@ +/** + * Generated by Gemini AI - Attempt 1 + * Processes bank statement data from Excel + * @param {Array} rawData - Array of objects from bank statement Excel + * @returns {Object} Processed bank statement data + */ +function processBankStatement(rawData) { + const bank_details = { + bank_name: null, + opening_balance: 0, + ifsc: null, + address: null, + city: null, + account_no: null, + account_holder_name: null, + branch_name: null, + branch_code: null + }; + const transactions = []; + let headerRowIndex = -1; + let headerKeys = {}; + let voucher_number = 1; + + // Helper function to format dates + const formatDate = (dateString) => { + if (!dateString) return null; + + // Attempt to parse different date formats + let date = new Date(dateString); + + if (isNaN(date.getTime())) { + // Try parsing as DD/MM/YYYY + const parts = dateString.split('/'); + if (parts.length === 3) { + date = new Date(`${parts[2]}-${parts[1]}-${parts[0]}`); + } + } + + if (isNaN(date.getTime())) { + // Try parsing as DD-MM-YYYY + const parts = dateString.split('-'); + if (parts.length === 3) { + date = new Date(`${parts[2]}-${parts[1]}-${parts[0]}`); + } + } + + if (isNaN(date.getTime())) { + return null; + } + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + }; + + // Extract bank details and find the header row + for (let i = 0; i < rawData.length; i++) { + const row = rawData[i]; + for (const key in row) { + if (typeof row[key] === 'string') { + const lowerCaseValue = row[key].toLowerCase(); + if (lowerCaseValue.includes('ifsc') || lowerCaseValue.includes('ifs code') || lowerCaseValue.includes('ifsc code')) { + const ifscValue = row[key].split(':').pop().trim() || ""; + bank_details.ifsc = ifscValue; + } else if (lowerCaseValue.includes('account no') || lowerCaseValue.includes('account number') || lowerCaseValue.includes('accountnumber')) { + const accountValue = row[key].split(':').pop().trim() || ""; + bank_details.account_no = accountValue; + } + + + } + if (row[key] === "Date" || row[key] === "Narration" || row[key] === "Narration or Details" || row[key] === "Withdrawal Amt." || row[key] === "Withdrawal Amt. or Debit" || row[key] === "Deposit Amt." || row[key] === "Deposit Amt. or Credit" || row[key] === "Closing Balance" || row[key] === "Closing Balance or Balance") { + headerRowIndex = i; + break; + } + } + + if (headerRowIndex !== -1) { + break; // Header row found, exit the loop + } + } + + //Extract Bank Details + for (let i = 0; i < headerRowIndex; i++){ + const row = rawData[i]; + for(const key in row){ + const value = row[key]; + if(typeof value === 'string'){ + if(!bank_details.bank_name && value.toLowerCase().includes('bank')){ + bank_details.bank_name = value.split(' ')[0]; + } + + if(!bank_details.account_holder_name && value.toLowerCase().includes('mr') || value.toLowerCase().includes('mrs')|| value.toLowerCase().includes('ms')){ + bank_details.account_holder_name = value + } + + if(!bank_details.address && value.toLowerCase().includes('address')){ + bank_details.address = row["__EMPTY_3"] + bank_details.city = rawData[i+2]["__EMPTY_3"] + + } + } + if(bank_details.ifsc == null){ + const row = rawData[i]; + for(const key in row){ + const value = row[key]; + if(typeof value == 'string'){ + if(value.toLowerCase().includes('ifsc') || value.toLowerCase().includes('rtgs/neft ifsc')|| value.toLowerCase().includes('ifs code') || value.toLowerCase().includes('ifsc code')){ + const ifscValue = value.split(':').pop().trim() || ""; + bank_details.ifsc = ifscValue.split(' ')[0] + break; + } + + } + + + } + + } + + if(bank_details.ifsc == null){ + const row = rawData[i]; + for(const key in row){ + + if(typeof row["__EMPTY_3"] == 'string'){ + const value = row["__EMPTY_3"] + if(value.toLowerCase().includes('ifsc') || value.toLowerCase().includes('rtgs/neft ifsc')|| value.toLowerCase().includes('ifs code') || value.toLowerCase().includes('ifsc code')){ + const ifscValue = value.split(':').pop().trim() || ""; + bank_details.ifsc = ifscValue.split(' ')[0] + break; + } + } + } + + } + } + + } + + if (headerRowIndex !== -1) { + const headerRow = rawData[headerRowIndex]; + for (const key in headerRow) { + const headerValue = headerRow[key]; + + if (typeof headerValue === 'string') { + const lowerCaseHeader = headerValue.toLowerCase(); + + if (lowerCaseHeader === "date") { + headerKeys.date = key; + } else if (lowerCaseHeader === "narration" || lowerCaseHeader === "narration or details") { + headerKeys.desc = key; + } else if (lowerCaseHeader.includes("withdrawal")) { + headerKeys.withdrawal = key; + } else if (lowerCaseHeader.includes("deposit")) { + headerKeys.deposit = key; + } else if (lowerCaseHeader.includes("balance")) { + headerKeys.balance = key; + } else if(lowerCaseHeader === "chq./ref.no."){ + headerKeys.ref = key; + } + + } + } + } + + // Process transactions + for (let i = headerRowIndex + 1; i < rawData.length; i++) { + const row = rawData[i]; + if (!row) continue; + + let date = null; + if(headerKeys.date){ + date = formatDate(row[headerKeys.date]); + } + + if (!date) continue; // Skip if date is missing or invalid + + const desc = row[headerKeys.desc] || null; + let type = null; + let amount = null; + + if (headerKeys.withdrawal && row[headerKeys.withdrawal] !== null && row[headerKeys.withdrawal] !== undefined) { + type = "withdrawal"; + amount = Number(row[headerKeys.withdrawal]) || null; + + } else if (headerKeys.deposit && row[headerKeys.deposit] !== null && row[headerKeys.deposit] !== undefined) { + type = "deposit"; + amount = Number(row[headerKeys.deposit]) || null; + } + + if (amount === null || isNaN(amount)) { + // If amount is not valid, attempt to extract it from the narration + if(desc){ + const amountRegex = /(\d{1,3}(,\d{3})*(\.\d+)?|\.\d+)/; + const amountMatch = desc.match(amountRegex); + if (amountMatch) { + amount = Number(amountMatch[0].replace(/,/g, '')); // Remove commas and convert to number + } + } + + if (amount === null || isNaN(amount)) continue; //Skip row for invalid amount + } + + let balance = null; + if (headerKeys.balance && row[headerKeys.balance] !== null && row[headerKeys.balance] !== undefined ) { + balance = Number(row[headerKeys.balance]) || null; + if(isNaN(balance)) { + balance = null + } + } + + const transaction = { + date, + voucher_number, + amount, + desc, + from: null, + to: null, + type, + balance + }; + transactions.push(transaction); + voucher_number++; + } + + return { bank_details, transactions }; +} + +module.exports = processBankStatement; \ No newline at end of file