Quentin Defenouillere
Committed by Romain Bignon

[bolden] Remodelled module with one main account and investments

The money borrowed on Bolden should be considered as investments, no
individual accounts, with the available money retrieved as liquidities.
Only the borrowed money that is still ongoing should be considered, the
other investment lines without valuation are expired investments.
With this model, the sum of investment valuation + liquidities actually
fits the main account balance.

Closes: 7716@zendesk, 8244@zendesk
......@@ -23,6 +23,7 @@ from datetime import timedelta, datetime
from weboob.browser import LoginBrowser, need_login, URL
from weboob.capabilities.bill import Document
from weboob.tools.capabilities.bank.investments import create_french_liquidity
from .pages import (
LoginPage, HomeLendPage, PortfolioPage, OperationsPage, MAIN_ID, ProfilePage,
......@@ -51,13 +52,16 @@ class BoldenBrowser(LoginBrowser):
return self.page.iter_accounts()
def iter_investments(self):
yield create_french_liquidity(self.page.get_liquidity())
for inv in self.page.iter_investments():
yield inv
def iter_history(self, account):
if account.id != MAIN_ID:
return []
return self._iter_all_history()
def _iter_all_history(self):
end = datetime.now()
while True:
start = end - timedelta(days=365)
......@@ -86,14 +90,13 @@ class BoldenBrowser(LoginBrowser):
def iter_documents(self):
for acc in self.iter_accounts():
if acc.id == MAIN_ID:
for inv in self.iter_investments():
if inv.label == "Liquidités":
doc = Document()
doc.id = acc.id
doc.url = acc._docurl
doc.label = 'Contrat %s' % acc.label
doc.id = inv.id
doc.url = inv._docurl
doc.label = 'Contrat %s' % inv.label
doc.type = 'other'
doc.format = 'pdf'
yield doc
......@@ -22,7 +22,7 @@ from __future__ import unicode_literals
from weboob.tools.backend import Module, BackendConfig
from weboob.tools.value import ValueBackendPassword
from weboob.capabilities.bank import CapBank, Account
from weboob.capabilities.bank import CapBankWealth, Account
from weboob.capabilities.base import find_object
from weboob.capabilities.bill import (
CapDocument, Subscription, SubscriptionNotFound, DocumentNotFound, Document,
......@@ -35,7 +35,7 @@ from .browser import BoldenBrowser
__all__ = ['BoldenModule']
class BoldenModule(Module, CapBank, CapDocument, CapProfile):
class BoldenModule(Module, CapBankWealth, CapDocument, CapProfile):
NAME = 'bolden'
MAINTAINER = 'Vincent A'
......@@ -59,6 +59,9 @@ class BoldenModule(Module, CapBank, CapDocument, CapProfile):
def iter_history(self, account):
return self.browser.iter_history(account)
def iter_investment(self, account):
return self.browser.iter_investments()
def get_profile(self):
return self.browser.get_profile()
......@@ -19,15 +19,14 @@
from __future__ import unicode_literals
from decimal import Decimal
from weboob.browser.elements import ListElement, ItemElement, method, TableElement
from weboob.browser.filters.html import TableCell, Link, Attr
from weboob.browser.filters.standard import (
CleanText, CleanDecimal, Slugify, Date, Field, Format,
from weboob.browser.pages import HTMLPage, LoggedPage
from weboob.capabilities.bank import Account, Transaction
from weboob.capabilities.base import NotAvailable
from weboob.capabilities.bank import Account, Transaction, Investment
from weboob.capabilities.profile import Profile
from weboob.exceptions import BrowserIncorrectPassword
from weboob.tools.compat import urljoin
......@@ -55,37 +54,46 @@ class HomeLendPage(LoggedPage, HTMLPage):
class PortfolioPage(LoggedPage, HTMLPage):
class iter_accounts(ListElement):
class get_main(ItemElement):
class item(ItemElement):
klass = Account
obj_id = MAIN_ID
obj_label = 'Compte Bolden'
obj_type = Account.TYPE_CHECKING
obj_type = Account.TYPE_MARKET
obj_currency = 'EUR'
obj_balance = CleanDecimal('//div[p[has-class("investor-state") and contains(text(),"Fonds disponibles :")]]/p[has-class("investor-status")]', replace_dots=True)
#obj_coming = CleanDecimal('//div[p[has-class("investor-state") and contains(text(),"Capital restant dû :")]]/p[has-class("investor-status")]', replace_dots=True)
obj_balance = CleanDecimal('//div[p[has-class("investor-state") and contains(text(),"Total compte Bolden :")]]/p[has-class("investor-status")]', replace_dots=True)
obj_valuation_diff = CleanDecimal('//p[has-class("rent-amount strong dashboard-text")]', replace_dots=True)
class iter_investments(TableElement):
head_xpath = '//div[@class="tab-wallet"]/table/thead//td'
class iter_lends(TableElement):
head_xpath = '//div[@class="tab-wallet"]/table/thead//td'
col_label = 'Emprunteur'
col_valuation = 'Capital restant dû'
col_doc = 'Contrat'
col_diff = 'Intérêts perçus'
col_label = 'Emprunteur'
col_coming = 'Capital restant dû'
col_doc = 'Contrat'
item_xpath = '//div[@class="tab-wallet"]/table/tbody/tr'
item_xpath = '//div[@class="tab-wallet"]/table/tbody/tr'
class item(ItemElement):
klass = Investment
class item(ItemElement):
klass = Account
obj_label = CleanText(TableCell('label'))
obj_id = Slugify(Field('label'))
obj_valuation = CleanDecimal(TableCell('valuation'), replace_dots=True)
obj_diff = CleanDecimal(TableCell('diff'), replace_dots=True)
obj_code = NotAvailable
obj_code_type = NotAvailable
def condition(self):
# Investments without valuation are expired.
return CleanDecimal(TableCell('valuation'))(self)
obj_label = CleanText(TableCell('label'))
obj_id = Slugify(Field('label'))
obj_type = Account.TYPE_SAVINGS
obj_currency = 'EUR'
obj_coming = CleanDecimal(TableCell('coming'), replace_dots=True)
obj_balance = Decimal('0')
def obj__docurl(self):
return urljoin(self.page.url, Link('.//a')(TableCell('doc')(self)[0]))
def obj__docurl(self):
return urljoin(self.page.url, Link('.//a')(TableCell('doc')(self)[0]))
def get_liquidity(self):
return CleanDecimal('//div[p[contains(text(), "Fonds disponibles")]]/p[@class="investor-status strong"]', replace_dots=True)(self.doc)
class OperationsPage(LoggedPage, HTMLPage):