From bdf4dc8aa5d8b74ea18f5b4802181ce6df798b48 Mon Sep 17 00:00:00 2001 From: Christophe Francois Date: Mon, 16 Nov 2020 16:43:43 +0100 Subject: [PATCH] [cmso] Fix find_account method for market accounts The previous method used the account label and owner to find it on the market accounts page. However sometimes the same owner can have two accounts with the same label, and the matching fails. This was used to fetch invests, history and market orders, but also to determine the account's id. We can get the same id from the accounts page so we do that instead and we use it for the matching. --- modules/cmso/par/browser.py | 6 ++--- modules/cmso/par/pages.py | 50 +++++++++++++------------------------ 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/modules/cmso/par/browser.py b/modules/cmso/par/browser.py index 6df6c779ec..ca67bec0af 100644 --- a/modules/cmso/par/browser.py +++ b/modules/cmso/par/browser.py @@ -411,7 +411,7 @@ def iter_history(self, account): elif account.type in (Account.TYPE_PEA, Account.TYPE_MARKET): try: self._go_market_history('historiquePortefeuille') - if not self.page.go_account(account.label, account._owner): + if not self.page.go_account(account.id): return if not self.page.go_account_full(): @@ -511,7 +511,7 @@ def iter_investment(self, account): elif account.type in (Account.TYPE_MARKET, Account.TYPE_PEA): try: self._go_market_history('situationPortefeuille') - if self.page.go_account(account.label, account._owner): + if self.page.go_account(account.id): return self.page.iter_investment() return [] finally: @@ -526,7 +526,7 @@ def iter_market_orders(self, account): try: self._go_market_history('carnetOrdre') - if self.page.go_account(account.label, account._owner): + if self.page.go_account(account.id): orders_list_url = self.url error_message = self.page.get_error_message() if error_message: diff --git a/modules/cmso/par/pages.py b/modules/cmso/par/pages.py index 114e8f5b96..ce62ecf8e1 100644 --- a/modules/cmso/par/pages.py +++ b/modules/cmso/par/pages.py @@ -261,7 +261,7 @@ def obj_id(self): if number: return number elif type in (Account.TYPE_PEA, Account.TYPE_MARKET): - number = self.get_market_number() + number = Dict('idTechnique')(self)[5:] # first 5 characters are the bank id if number: return number @@ -287,14 +287,6 @@ def obj_ownership(self): return AccountOwnership.OWNER return AccountOwnership.ATTORNEY - def get_market_number(self): - label = Field('label')(self) - try: - page = self.page.browser._go_market_history('historiquePortefeuille') - return page.get_account_id(label, Field('_owner')(self)) - finally: - self.page.browser._return_from_market() - def get_lifenumber(self): index = Dict('index')(self) data = json.loads(self.page.browser.redirect_insurance.open(accid=index).text) @@ -583,7 +575,7 @@ def obj_diff_ratio(self): class MarketPage(LoggedPage, HTMLPage): - def find_account(self, acclabel, accowner): + def find_account(self, account_id): # Depending on what we're fetching (history, invests or orders), # the parameter to choose the account has a different name. if 'carnetOrdre' in self.url: @@ -591,23 +583,20 @@ def find_account(self, acclabel, accowner): else: param_name = 'indiceCompte' # first name and last name may not be ordered the same way on market site... - accowner = sorted(accowner.lower().split()) - def get_ids(ref, acclabel, accowner, param_name): - ids = None + def get_ids(ref, account_id, param_name): + # Market account IDs contain 3 parts: + # - the first 5 and last 2 digits identify the account + # - the 9 digits in the middle identify the owner of the account + # These info are separated on the page so we need to get them from the id to match the account. + owner_id = account_id[5:14] + account_number = '%s%s' % (account_id[:5], account_id[-2:]) for a in self.doc.xpath('//a[contains(@%s, "%s")]' % (ref, param_name)): self.logger.debug("get investment from %s" % ref) - label = CleanText('.')(a) - owner = CleanText('./ancestor::tr/preceding-sibling::tr[@class="LnMnTiers"][1]')(a) - owner = re.sub(r' \(.+', '', owner) - owner = sorted(owner.lower().split()) - if label == acclabel and owner == accowner: - ids = list( - re.search(r'%s[^\d]+(\d+).*idRacine[^\d]+(\d+)' % param_name, Attr('.', ref)(a)).groups() - ) - ids.append(CleanText('./ancestor::td/preceding-sibling::td')(a)) - self.logger.debug("assign value to ids: {}".format(ids)) - return ids + number = CleanText('./ancestor::td/preceding-sibling::td')(a).replace(' ', '') + if number in (account_id, account_number): + index = re.search(r'%s[^\d]+(\d+).*idRacine' % param_name, Attr('.', ref)(a)).group(1) + return [index, owner_id, number] # Check if history is present if CleanText(default=None).filter(self.doc.xpath('//body/p[contains(text(), "indisponible pour le moment")]')): @@ -615,22 +604,17 @@ def get_ids(ref, acclabel, accowner, param_name): ref = CleanText(self.doc.xpath('//a[contains(@href, "%s")]' % param_name))(self) if not ref: - return get_ids('onclick', acclabel, accowner, param_name) + return get_ids('onclick', account_id, param_name) else: - return get_ids('href', acclabel, accowner, param_name) - - def get_account_id(self, acclabel, owner): - account = self.find_account(acclabel, owner) - if account: - return account[2].replace(' ', '') + return get_ids('href', account_id, param_name) - def go_account(self, acclabel, owner): + def go_account(self, account_id): if 'carnetOrdre' in self.url: param_name = 'idCompte' else: param_name = 'indiceCompte' - ids = self.find_account(acclabel, owner) + ids = self.find_account(account_id) if not ids: return -- GitLab