class item(ItemElement): klass = Account TYPES = { u'assurance vie': Account.TYPE_LIFE_INSURANCE, u'perp': Account.TYPE_PERP, u'epargne retraite agipi pair': Account.TYPE_PERP, u'novial avenir': Account.TYPE_MADELIN, u'epargne retraite novial': Account.TYPE_LIFE_INSURANCE, } condition = lambda self: Field('balance')(self) is not NotAvailable obj_id = Regexp(CleanText('.//span[has-class("small-title")]'), r'([\d/]+)') obj_label = CleanText('.//h3[has-class("card-title")]') obj_balance = CleanDecimal.French('.//p[has-class("amount-card")]') obj_valuation_diff = CleanDecimal.French( './/p[@class="performance"]', default=NotAvailable) def obj_url(self): url = Attr('.', 'data-route')(self) # The Assurance Vie xpath recently changed so we must verify that all # the accounts now have "/savings/" instead of "/assurances-vie/". assert "/savings/" in url return url obj_currency = Currency('.//p[has-class("amount-card")]') obj__acctype = "investment" obj_type = MapIn(Lower(Field('label')), TYPES, Account.TYPE_UNKNOWN)
class item(ItemElement): klass = Transaction TRANSACTION_TYPES = { 'FACTURE CB': Transaction.TYPE_CARD, 'RETRAIT CB': Transaction.TYPE_WITHDRAWAL, "TRANSACTION INITIALE RECUE D'AVOIR": Transaction.TYPE_PAYBACK, } obj_label = CleanText(Dict('Raison sociale commerçant')) obj_amount = CleanDecimal.French(Dict('Montant EUR')) obj_original_currency = CleanText(Dict("Devise d'origine")) obj_rdate = Date(CleanText(Dict("Date d'opération")), dayfirst=True) obj_date = Date(CleanText(Dict('Date débit-crédit')), dayfirst=True) obj_type = MapIn(CleanText(Dict('Libellé opération')), TRANSACTION_TYPES) def obj_commission(self): commission = CleanDecimal.French(Dict('Commission'))(self) if commission != 0: # We don't want to return null commissions return commission return NotAvailable def obj_original_amount(self): original_amount = CleanDecimal.French( Dict("Montant d'origine"))(self) if original_amount != 0: # We don't want to return null original_amounts return original_amount return NotAvailable def obj__coming(self): return Field('date')(self) >= date.today()
class item(ItemElement): klass = Account TYPES = { 'assurance vie': Account.TYPE_LIFE_INSURANCE, 'perp': Account.TYPE_PERP, 'epargne retraite agipi pair': Account.TYPE_PERP, 'epargne retraite agipi far': Account.TYPE_MADELIN, 'epargne retraite ma retraite': Account.TYPE_PER, 'novial avenir': Account.TYPE_MADELIN, 'epargne retraite novial': Account.TYPE_LIFE_INSURANCE, } obj_id = Regexp(CleanText('.//span[has-class("small-title")]'), r'([\d/]+)') obj_number = obj_id obj_label = CleanText('.//h3[has-class("card-title")]') obj_balance = CleanDecimal.French('.//p[has-class("amount-card")]') obj_valuation_diff = CleanDecimal.French( './/p[@class="performance"]', default=NotAvailable) obj_currency = Currency('.//p[has-class("amount-card")]') obj__acctype = "investment" obj_type = MapIn(Lower(Field('label')), TYPES, Account.TYPE_UNKNOWN) obj_url = Attr('.', 'data-module-open-link--link') obj_ownership = AccountOwnership.OWNER
class item(ItemElement): klass = Account # If user has professional accounts, owner_type must be defined OWNER_TYPE = { 'Mes avoirs professionnels': AccountOwnerType.ORGANIZATION, 'Mes avoirs personnels': AccountOwnerType.PRIVATE, 'Mes crédits personnels': AccountOwnerType.PRIVATE, } # MapIn because, in case of private account, we actually catch "Mes avoirs personnels Mes crédits personnels" with CleanText which both can be use to recognize the owner_type as PRIVATE obj_owner_type = MapIn(CleanText('.//form[@id]/ancestor::div/h2'), OWNER_TYPE, NotAvailable) obj_label = Label( CleanText( './/form[@id]/preceding-sibling::p/span[@class="hsbc-pib-text hsbc-pib-bloc-account-name" or @class="hsbc-pib-text--small"]' )) obj_type = AccountsType(Field('label')) obj_url = CleanText('.//form/@action') obj_currency = Currency('.//form[@id]/following-sibling::*[1]') obj__is_form = bool(CleanText('.//form/@id')) obj__amount = CleanDecimal.French( './/form[@id]/following-sibling::*[1]') def obj_balance(self): if Field('type')(self) == Account.TYPE_CARD: return Decimal(0) elif 'Mes crédits' in CleanText( './/ancestor::div[1]/preceding-sibling::*')(self): return -abs(Field('_amount')(self)) return Field('_amount')(self) def obj_coming(self): if Field('type')(self) == Account.TYPE_CARD: return Field('_amount')(self) return NotAvailable def obj_id(self): # Investment accounts and main account can have the same id _id = CleanText('.//form[@id]/preceding-sibling::*[1]/span[2]', replace=[('.', ''), (' ', '')])(self) if "Scpi" in Field('label')(self): return _id + ".SCPI" # Same problem with scpi accounts. if Field('type')(self) == Account.TYPE_MARKET: return _id + ".INVEST" # Cards are displayed like '4561 00XX XXXX 5813 - Carte à débit différé' if 'Carte' in _id: _id = Regexp(pattern=r'(.*)-Carte').filter(_id) return _id
class item(ItemElement): klass = Account balance_xpath = './/span[contains(text(), "Montant total")]/following-sibling::span' obj_label = CleanText('./tbody/tr/th//div') obj_balance = MyDecimal(balance_xpath) obj_currency = Currency(balance_xpath) obj_type = MapIn(Field('label'), ACCOUNTS_TYPES, Account.TYPE_UNKNOWN) def obj_id(self): # Use customer number + label to build account id number = Regexp(CleanText('//div[@id="ei_tpl_fullSite"]//div[contains(@class, "ei_tpl_profil_content")]/p'), r'(\d+)$', '\\1')(self) return Field('label')(self) + number
def obj_type(self): return MapIn(Upper(Field('label')), self.page.TYPES, Account.TYPE_UNKNOWN)(self)
def obj_type(self): return MapIn(Field('label'), self.page.ACCOUNT_TYPES, Account.TYPE_UNKNOWN)(self)