-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: fetch credit card line of credit utilization #857
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -61,6 +61,11 @@ interface ScrapedAccount { | |||||||||||||||
processedDate: string; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
interface AccountCredit { | ||||||||||||||||
creditUtilization: number; | ||||||||||||||||
creditLimit: number; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
interface ScrapedLoginValidation { | ||||||||||||||||
Header: { | ||||||||||||||||
Status: string; | ||||||||||||||||
|
@@ -84,6 +89,19 @@ interface ScrapedAccountsWithinPageResponse { | |||||||||||||||
}; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
interface ScrapedCreditDataWithinPageResponse { | ||||||||||||||||
Header: { | ||||||||||||||||
Status: string; | ||||||||||||||||
}; | ||||||||||||||||
RikuzNetuneyCreditDigiBean: { | ||||||||||||||||
cardsTotal: { | ||||||||||||||||
cardNumberTail: string; | ||||||||||||||||
nitzulLoCredit: string; | ||||||||||||||||
misgeretKolelet: string; | ||||||||||||||||
}[]; | ||||||||||||||||
}; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
interface ScrapedCurrentCardTransactions { | ||||||||||||||||
txnIsrael?: ScrapedTransaction[]; | ||||||||||||||||
txnAbroad?: ScrapedTransaction[]; | ||||||||||||||||
|
@@ -98,6 +116,39 @@ interface ScrapedTransactionData { | |||||||||||||||
}>; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function getCreditUtilizationUrl(servicesUrl: string) { | ||||||||||||||||
return buildUrl(servicesUrl, { | ||||||||||||||||
queryParams: { | ||||||||||||||||
reqName: 'RikuzNetuneyCreditDigi', | ||||||||||||||||
}, | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
async function fetchCreditUtilization( | ||||||||||||||||
page: Page, | ||||||||||||||||
servicesUrl: string, | ||||||||||||||||
): Promise<_.Dictionary<AccountCredit> | null> { | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use standard types, I'm not familiar with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As lodash is already installed on the project I believed it's OK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, although I'm thinking a lot before I add But still, for the function signature, which is a kind of contract/interface, I prefer to use standard types. |
||||||||||||||||
const dataUrl = getCreditUtilizationUrl(servicesUrl); | ||||||||||||||||
const dataResult = await fetchGetWithinPage<ScrapedCreditDataWithinPageResponse>( | ||||||||||||||||
page, | ||||||||||||||||
dataUrl, | ||||||||||||||||
); | ||||||||||||||||
|
||||||||||||||||
if (!dataResult) { | ||||||||||||||||
throw new Error('Failed to fetch credit utilization data, empty response'); | ||||||||||||||||
} | ||||||||||||||||
baruchiro marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
||||||||||||||||
return _.fromPairs( | ||||||||||||||||
dataResult.RikuzNetuneyCreditDigiBean.cardsTotal.map((item) => [ | ||||||||||||||||
item.cardNumberTail, | ||||||||||||||||
{ | ||||||||||||||||
creditUtilization: parseFloat(item.nitzulLoCredit), | ||||||||||||||||
creditLimit: parseFloat(item.misgeretKolelet.replace(/,/g, '')), | ||||||||||||||||
}, | ||||||||||||||||
]), | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
function getAccountsUrl(servicesUrl: string, monthMoment: Moment) { | ||||||||||||||||
const billingDate = monthMoment.format('YYYY-MM-DD'); | ||||||||||||||||
return buildUrl(servicesUrl, { | ||||||||||||||||
|
@@ -284,6 +335,12 @@ function getExtraScrap(accountsWithIndex: ScrapedAccountsWithIndex[], page: Page | |||||||||||||||
async function fetchAllTransactions(page: Page, options: ExtendedScraperOptions, startMoment: Moment) { | ||||||||||||||||
const futureMonthsToScrape = options.futureMonthsToScrape ?? 1; | ||||||||||||||||
const allMonths = getAllMonthMoments(startMoment, futureMonthsToScrape); | ||||||||||||||||
let creditUtilization: _.Dictionary<AccountCredit> | null = null; | ||||||||||||||||
if (options.includeCreditUtilization) { | ||||||||||||||||
debug('Getting credit utilization data'); | ||||||||||||||||
creditUtilization = await fetchCreditUtilization(page, options.servicesUrl); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
const results: ScrapedAccountsWithIndex[] = await Promise.all(allMonths.map(async (monthMoment) => { | ||||||||||||||||
return fetchTransactions(page, options, startMoment, monthMoment); | ||||||||||||||||
})); | ||||||||||||||||
|
@@ -306,10 +363,17 @@ async function fetchAllTransactions(page: Page, options: ExtendedScraperOptions, | |||||||||||||||
}); | ||||||||||||||||
|
||||||||||||||||
const accounts = Object.keys(combinedTxns).map((accountNumber) => { | ||||||||||||||||
return { | ||||||||||||||||
const account: TransactionsAccount = { | ||||||||||||||||
accountNumber, | ||||||||||||||||
txns: combinedTxns[accountNumber], | ||||||||||||||||
}; | ||||||||||||||||
if (creditUtilization && creditUtilization[accountNumber]) { | ||||||||||||||||
account.credit = { | ||||||||||||||||
creditUtilization: creditUtilization[accountNumber].creditUtilization, | ||||||||||||||||
creditLimit: creditUtilization[accountNumber].creditLimit, | ||||||||||||||||
}; | ||||||||||||||||
} | ||||||||||||||||
Comment on lines
+370
to
+375
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about this?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like a better idea, Will update. |
||||||||||||||||
return account; | ||||||||||||||||
}); | ||||||||||||||||
|
||||||||||||||||
return { | ||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can declare this interface once in
transactions.ts
and import it everywhere.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though about that too, but as this is an internal type (it's used locally, not "passed" outside the file) I opted into this.
If you think otherwise - let me know.