Skip to content

Commit

Permalink
[postal-savings-rs] Add fetchExchangeRates
Browse files Browse the repository at this point in the history
  • Loading branch information
osipxd committed Apr 23, 2024
1 parent 67a8dde commit c112900
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { convertExchangeRates } from '../../../converters'

const input = `
<tr>
<td align="center" colspan="9">E- BANKING EXCHANGE RATE LIST NO.: 66<br></br>APPLICABLE AS AT: 05.04.2024.</td>
</tr>
<tr>
<td align="center" width="5%" rowspan="2">Currency code</td>
<td align="center" width="5%" rowspan="2">Currency designation</td>
<td align="center" width="15%" rowspan="2">Country</td>
<td align="center" width="10%" rowspan="2">Unit</td>
<td align="center" colspan="3" width="30%">For foreign exchange</td>
<td align="center" colspan="2" width="20%">For foreign cash</td>
</tr><tr>
<td align="center" width="12%">Buying exchange rate</td>
<td align="center" width="12%">Middle exchange rate</td>
<td align="center" width="12%">Selling exchange rate</td>
<td align="center" width="12%">Buying exchange rate</td>
<td align="center" width="12%">Selling exchange rate</td>
</tr>
<tr valign="top">
<td align="center">978<br></br></td>
<td align="center">EUR<br></br></td>
<td align="left"><img src='../slike2/EUR.gif' height="11" width="16"/>&nbsp;E M U <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 116.7883<br></br></td>
<td align="center"> 117.1397<br></br></td>
<td align="center"> 117.4911<br></br></td>
<td align="center"> 116.7883<br></br></td>
<td align="center"> 117.6083<br></br></td>
</tr>
<tr valign="top">
<td align="center">036<br></br></td>
<td align="center">AUD<br></br></td>
<td align="left"><img src='../slike2/AUD.gif' height="11" width="16"/>&nbsp;AUSTRALIJA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 70.0520<br></br></td>
<td align="center"> 71.1188<br></br></td>
<td align="center"> 72.1856<br></br></td>
<td align="center"> 70.0520<br></br></td>
<td align="center"> 72.1856<br></br></td>
</tr>
<tr valign="top">
<td align="center">124<br></br></td>
<td align="center">CAD<br></br></td>
<td align="left"><img src='../slike2/CAD.gif' height="11" width="16"/>&nbsp;KANADA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 78.5289<br></br></td>
<td align="center"> 79.7248<br></br></td>
<td align="center"> 80.9207<br></br></td>
<td align="center"> 78.5289<br></br></td>
<td align="center"> 80.9207<br></br></td>
</tr>
<tr valign="top">
<td align="center">208<br></br></td>
<td align="center">DKK<br></br></td>
<td align="left"><img src='../slike2/DKK.gif' height="11" width="16"/>&nbsp;DANSKA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 15.4678<br></br></td>
<td align="center"> 15.7034<br></br></td>
<td align="center"> 15.9390<br></br></td>
<td align="center"> 15.4678<br></br></td>
<td align="center"> 15.9390<br></br></td>
</tr>
<tr valign="top">
<td align="center">578<br></br></td>
<td align="center">NOK<br></br></td>
<td align="left"><img src='../slike2/NOK.gif' height="11" width="16"/>&nbsp;NORVESKA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 9.9009<br></br></td>
<td align="center"> 10.0517<br></br></td>
<td align="center"> 10.2025<br></br></td>
<td align="center"> 9.9009<br></br></td>
<td align="center"> 10.2025<br></br></td>
</tr>
<tr valign="top">
<td align="center">643<br></br></td>
<td align="center">RUB<br></br></td>
<td align="left"><img src='../slike2/RUB.gif' height="11" width="16"/>&nbsp;RUSIJA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 1.1140<br></br></td>
<td align="center"> 1.1726<br></br></td>
<td align="center"> 1.2312<br></br></td>
<td align="center"> 0.0000<br></br></td>
<td align="center"> 0.0000<br></br></td>
</tr>
<tr valign="top">
<td align="center">752<br></br></td>
<td align="center">SEK<br></br></td>
<td align="left"><img src='../slike2/SEK.gif' height="11" width="16"/>&nbsp;SVEDSKA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 9.9941<br></br></td>
<td align="center"> 10.1463<br></br></td>
<td align="center"> 10.2985<br></br></td>
<td align="center"> 9.9941<br></br></td>
<td align="center"> 10.2985<br></br></td>
</tr>
<tr valign="top">
<td align="center">756<br></br></td>
<td align="center">CHF<br></br></td>
<td align="left"><img src='../slike2/CHF.gif' height="11" width="16"/>&nbsp;SVAJCARSKA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 118.0506<br></br></td>
<td align="center"> 119.8483<br></br></td>
<td align="center"> 121.6460<br></br></td>
<td align="center"> 118.0506<br></br></td>
<td align="center"> 121.6460<br></br></td>
</tr>
<tr valign="top">
<td align="center">826<br></br></td>
<td align="center">GBP<br></br></td>
<td align="left"><img src='../slike2/GBP.gif' height="11" width="16"/>&nbsp;VEL. BRITANIJA <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 134.5570<br></br></td>
<td align="center"> 136.6061<br></br></td>
<td align="center"> 138.6552<br></br></td>
<td align="center"> 134.5570<br></br></td>
<td align="center"> 138.6552<br></br></td>
</tr>
<tr valign="top">
<td align="center">840<br></br></td>
<td align="center">USD<br></br></td>
<td align="left"><img src='../slike2/USD.gif' height="11" width="16"/>&nbsp;S A D <br></br></td>
<td align="center"> 1<br></br></td>
<td align="center"> 106.5299<br></br></td>
<td align="center"> 108.1522<br></br></td>
<td align="center"> 109.7745<br></br></td>
<td align="center"> 106.5299<br></br></td>
<td align="center"> 109.7745<br></br></td>
</tr>
`

describe('convertExchangeRates', () => {
it('converts exchange rates', () => {
expect(convertExchangeRates(input)).toEqual(new Map([
['EUR', 117.1397],
['AUD', 71.1188],
['CAD', 79.7248],
['DKK', 15.7034],
['NOK', 10.0517],
['RUB', 1.1726],
['SEK', 10.1463],
['CHF', 119.8483],
['GBP', 136.6061],
['USD', 108.1522]
]))
})
})
19 changes: 16 additions & 3 deletions src/plugins/postal-savings-rs/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { accountDetailsToId, convertAccount, convertCardTransactions, convertTransactions } from './converters'
import { AccountDetails, PBAccount } from './models'
import { fetchAccountData, fetchCardTransactions } from './fetchApi'
import { accountDetailsToId, convertAccount, convertCardTransactions, convertExchangeRates, convertTransactions } from './converters'
import { AccountDetails, ExchangeRatesMap, PBAccount } from './models'
import { fetchAccountData, fetchCardTransactions, fetchExchangeRates } from './fetchApi'
import { Transaction } from '../../types/zenmoney'

function accountCardKey (accountId: string): string {
Expand Down Expand Up @@ -46,3 +46,16 @@ export async function fetchTransactions (account: PBAccount, fromDate: Date, toD

return accountTransactions.filter(transaction => transaction.date >= fromDate && transaction.date <= toDate)
}

const exchangeRatesByDate = new Map<Date, ExchangeRatesMap>()

async function getExcahangeRate (date: Date, currency: string): Promise<number | undefined> {
let exchangeRates = exchangeRatesByDate.get(date)
if (exchangeRates === undefined) {
const rawData = await fetchExchangeRates(date)
exchangeRates = convertExchangeRates(rawData)
exchangeRatesByDate.set(date, exchangeRates)
}

return exchangeRates.get(currency)
}
24 changes: 20 additions & 4 deletions src/plugins/postal-savings-rs/converters.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AccountOrCard, AccountType, Transaction } from '../../types/zenmoney'
import { AccountDetails, CardTransaction } from './models'
import { AccountDetails, CardTransaction, ExchangeRatesMap } from './models'
import moment from 'moment'

export function accountDetailsToId (account: AccountDetails): string {
Expand All @@ -14,9 +14,10 @@ function parseDate (s: string): Date {
return moment(s, 'DD.MM.YYYY').toDate()
}

function tableLineRegexp (columns: number): RegExp {
const cellPattern = '<td[^>]*>([^<]+)<\\/td>\\s+'
const regexStr = `<tr>\\s+${cellPattern.repeat(columns)}<\\/tr>`
function tableLineRegexp (columns: number, cellContentPattern?: string): RegExp {
cellContentPattern = cellContentPattern ?? '([^<]+)'
const cellPattern = `<td[^>]*>${cellContentPattern}<\\/td>\\s+`
const regexStr = `<tr[^>]*>\\s+${cellPattern.repeat(columns)}<\\/tr>`
return new RegExp(regexStr, 'g')
}

Expand Down Expand Up @@ -119,3 +120,18 @@ export function convertTransactions (accountId: string, data: string): Transacti

return transactions.reverse()
}

export function convertExchangeRates (data: string): ExchangeRatesMap {
const exchangeRates: ExchangeRatesMap = new Map()

const cellContentPattern = '(?:<img[^<]+/>)?([^<]+)(?:<br></br>)?'
const matches = data.matchAll(tableLineRegexp(9, cellContentPattern))

for (const t of matches) {
// Currency code, Currency designation, Country, Unit, Buying rate, Middle rate, Selling rate, Buying rate (cash), Selling rate (cash)
const [,,currency,,,,middleRate] = t
exchangeRates.set(currency, parseFloat(middleRate.trim()))
}

return exchangeRates
}
11 changes: 11 additions & 0 deletions src/plugins/postal-savings-rs/fetchApi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import moment from 'moment'
import { FetchResponse, fetch } from '../../common/network'
import { toAtLeastTwoDigitsString } from '../../common/stringUtils'
import { InvalidLoginOrPasswordError } from '../../errors'
Expand Down Expand Up @@ -122,3 +123,13 @@ export async function fetchCardTransactions (cardNumber: string, fromDate: Date,

return response.body as string
}

export async function fetchExchangeRates (date: Date): Promise<string> {
const formattedDate = moment(date).format('DD.MM.YYYY')
const response = await fetchUrl('kursl.jsp', {
method: 'POST',
body: `DATUM=${formattedDate}&check1=on`
})

return response.body as string
}
2 changes: 2 additions & 0 deletions src/plugins/postal-savings-rs/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ export interface CardTransaction {
amount: Amount
merchant: string
}

export type ExchangeRatesMap = Map<string, number>

0 comments on commit c112900

Please sign in to comment.