paypal: Proper multi-currency support

An account per currency.
And fix xpath (missing ".").
This commit is contained in:
Laurent Bachelier 2013-02-04 18:11:06 +01:00
commit 395d7e5e5d
3 changed files with 45 additions and 20 deletions

View file

@ -47,8 +47,7 @@ class PaypalBackend(BaseBackend, ICapBank):
self.config['password'].get()) self.config['password'].get())
def iter_accounts(self): def iter_accounts(self):
for account in self.browser.get_accounts(): return self.browser.get_accounts().itervalues()
yield account
def get_account(self, _id): def get_account(self, _id):
with self.browser: with self.browser:

View file

@ -56,12 +56,12 @@ class Paypal(BaseBrowser):
raise BrowserIncorrectPassword() raise BrowserIncorrectPassword()
def get_accounts(self): def get_accounts(self):
yield self.get_account(u"1") if not self.is_on_page(AccountPage):
self.location('/en/cgi-bin/webscr?cmd=_account&nav=0.0')
return self.page.get_accounts()
def get_account(self, _id): def get_account(self, _id):
if _id != u"1":
return None
if not self.is_on_page(AccountPage): if not self.is_on_page(AccountPage):
self.location('/en/cgi-bin/webscr?cmd=_account&nav=0.0') self.location('/en/cgi-bin/webscr?cmd=_account&nav=0.0')

View file

@ -19,7 +19,7 @@
from decimal import Decimal from decimal import Decimal
from weboob.tools.browser import BasePage from weboob.tools.browser import BasePage, BrokenPageError
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.capabilities.bank.transactions import FrenchTransaction
@ -40,29 +40,55 @@ class LoginPage(BasePage):
class AccountPage(BasePage): class AccountPage(BasePage):
def get_account(self, _id): def get_account(self, _id):
assert _id == u"1" # Only one "account" supported for now return self.get_accounts().get(_id)
account = Account()
account.id = _id
account.label = unicode(self.browser.username)
account.type = Account.TYPE_CHECKING
def get_accounts(self):
accounts = {}
content = self.document.xpath('//div[@id="main"]//div[@class="col first"]')[0] content = self.document.xpath('//div[@id="main"]//div[@class="col first"]')[0]
# Total currency balance. # Total currency balance.
# If there are multiple currencies, this balance is all currencies # If there are multiple currencies, this balance is all currencies
# converted to the main currency. # converted to the main currency.
balance = content.xpath('//h3/span[@class="balance"]')[0].text_content().strip() balance = content.xpath('.//h3/span[@class="balance"]')[0].text_content().strip()
account.balance = clean_amount(balance)
account.currency = account.get_currency(balance) # Primary currency account
primary_account = Account()
primary_account.type = Account.TYPE_CHECKING
primary_account.balance = clean_amount(balance)
primary_account.currency = Account.get_currency(balance)
primary_account.id = unicode(primary_account.currency)
primary_account.label = u'%s %s*' % (self.browser.username, balance.split()[-1])
accounts[primary_account.id] = primary_account
# The following code will only work if the user enabled multiple currencies.
balance = content.xpath('.//div[@class="body"]//ul/li[@class="balance"]/span')
table = content.xpath('.//table[@id="balanceDetails"]//tbody//tr')
# sanity check
if bool(balance) is not bool(table):
raise BrokenPageError('Unable to find all required multiple currency entries')
# Primary currency balance. # Primary currency balance.
# If the user enabled multiple currencies, we get this one instead. # If the user enabled multiple currencies, we get this one instead.
# An Account object has only one currency; secondary currencies should be other accounts. # An Account object has only one currency; secondary currencies should be other accounts.
balance = content.xpath('//div[@class="body"]//ul/li[@class="balance"]/span')
if balance: if balance:
balance = balance[0].text_content().strip() balance = balance[0].text_content().strip()
account.balance = clean_amount(balance) primary_account.balance = clean_amount(balance)
# The primary currency of the "head balance" is the same; ensure we got the right one # The primary currency of the "head balance" is the same; ensure we got the right one
assert account.currency == account.get_currency(balance) assert primary_account.currency == primary_account.get_currency(balance)
return account for row in table:
balance = row.xpath('.//td')[-1].text_content().strip()
account = Account()
account.type = Account.TYPE_CHECKING
account.balance = clean_amount(balance)
account.currency = Account.get_currency(balance)
account.id = unicode(account.currency)
account.label = u'%s %s' % (self.browser.username, balance.split()[-1])
if account.id == primary_account.id:
assert account.balance == primary_account.balance
assert account.currency == primary_account.currency
elif account.currency:
accounts[account.id] = account
return accounts