diff --git a/modules/groupamaes/__init__.py b/modules/groupamaes/__init__.py new file mode 100644 index 00000000..46414fd5 --- /dev/null +++ b/modules/groupamaes/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 Bezleputh +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from .backend import GroupamaesBackend + + +__all__ = ['GroupamaesBackend'] diff --git a/modules/groupamaes/backend.py b/modules/groupamaes/backend.py new file mode 100644 index 00000000..675cc5d8 --- /dev/null +++ b/modules/groupamaes/backend.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 Bezleputh +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + +from weboob.capabilities.bank import ICapBank, AccountNotFound +from weboob.tools.backend import BaseBackend, BackendConfig +from weboob.tools.value import ValueBackendPassword + + +from .browser import GroupamaesBrowser + + +__all__ = ['GroupamaesBackend'] + + +class GroupamaesBackend(BaseBackend, ICapBank): + NAME = 'groupamaes' + DESCRIPTION = u'groupama-es website' + MAINTAINER = u'Bezleputh' + EMAIL = 'carton_ben@yahoo.fr' + LICENSE = 'AGPLv3+' + VERSION = '0.i' + + BROWSER = GroupamaesBrowser + + CONFIG = BackendConfig(ValueBackendPassword('login', label='Identifiant', regexp='\d{8}', masked=False), + ValueBackendPassword('password', label='Mot de passe')) + + def create_default_browser(self): + return self.create_browser(self.config['login'].get(), self.config['password'].get()) + + def iter_accounts(self): + return self.browser.get_accounts_list() + + def iter_coming(self, account): + return self.browser.get_coming() + + def iter_history(self, account): + return self.browser.get_history() + + def get_account(self, _id): + account = self.browser.get_account(_id) + if account: + return account + else: + raise AccountNotFound() diff --git a/modules/groupamaes/browser.py b/modules/groupamaes/browser.py new file mode 100644 index 00000000..4ec1dd50 --- /dev/null +++ b/modules/groupamaes/browser.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 Bezleputh +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.browser2 import LoginBrowser, URL, need_login +from weboob.tools.browser import BrowserIncorrectPassword + +from .pages import LoginPage, LoginErrorPage, AvoirPage, OperationsTraiteesPage, OperationsFuturesPage + + +__all__ = ['GroupamaesBrowser'] + + +class GroupamaesBrowser(LoginBrowser): + BASEURL = 'https://www.gestion-epargne-salariale.fr' + + login = URL('/groupama-es/fr/index.html', LoginPage) + login_error = URL('/groupama-es/fr/identification/default.cgi', LoginErrorPage) + avoir = URL('/groupama-es/fr/espace/devbavoirs.aspx.*', AvoirPage) + operations_traitees = URL('/groupama-es/fr/espace/ListeOperations.asp\?TypeOperation=T', OperationsTraiteesPage) + operations_futures = URL('/groupama-es/fr/espace/ListeOperations.asp\?TypeOperation=E', OperationsFuturesPage) + + def do_login(self): + self.login.stay_or_go() + + self.page.login(self.username, self.password) + + if not self.page.logged or self.login_error.is_here(): + raise BrowserIncorrectPassword() + + @need_login + def get_accounts_list(self): + return self.avoir.stay_or_go().iter_accounts() + + @need_login + def get_history(self): + transactions = list(self.operations_traitees.go().get_history()) + transactions.sort(key=lambda tr: tr.rdate, reverse=True) + return transactions + + @need_login + def get_coming(self): + transactions = list(self.operations_futures.go().get_list()) + transactions.sort(key=lambda tr: tr.rdate, reverse=True) + return transactions + + def get_account(self, id): + assert isinstance(id, basestring) + for a in self.get_accounts_list(): + if a.id == id: + return a diff --git a/modules/groupamaes/pages.py b/modules/groupamaes/pages.py new file mode 100644 index 00000000..c7285c98 --- /dev/null +++ b/modules/groupamaes/pages.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 Bezleputh +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.browser2.page import HTMLPage, method, TableElement, ItemElement, LoggedPage +from weboob.tools.browser2.filters import CleanText, CleanDecimal, TableCell, Date +from weboob.capabilities.bank import Account, Transaction +from weboob.tools.capabilities.bank.transactions import FrenchTransaction +from weboob.tools.date import LinearDateGuesser + +__all__ = ['LoginPage', 'LoginErrorPage', 'AvoirPage', 'OperationsFuturesPage', 'OperationsTraiteesPage'] + + +class LoginPage(HTMLPage): + def login(self, login, passwd): + form = self.get_form(nr=0) + form['_cm_user'] = login + form['_cm_pwd'] = passwd + form.submit() + + +class LoginErrorPage(HTMLPage): + pass + + +class AvoirPage(LoggedPage, HTMLPage): + @method + class iter_accounts(TableElement): + item_xpath = u'//table[@summary="Liste des échéances"]/tbody/tr' + head_xpath = u'//table[@summary="Liste des échéances"]/thead/tr/th/text()' + + col_name = u'Plan' + col_value = u'Evaluation en' + + class item(ItemElement): + klass = Account + + obj_id = CleanText(TableCell('name')) + obj_label = CleanText(TableCell('name')) + #obj_coming = CleanDecimal(TableCell('value')) + obj_balance = CleanDecimal(TableCell('value')) + obj_currency = CleanText(u'//table[@summary="Liste des échéances"]/thead/tr/th/small/text()') + obj_type = Account.TYPE_UNKNOWN + + +class OperationsFuturesPage(LoggedPage, HTMLPage): + @method + class get_list(TableElement): + head_xpath = u'//table[@summary="Liste des opérations en attente"]/thead/tr/th/text()' + item_xpath = u'//table[@summary="Liste des opérations en attente"]/tbody/tr' + + col_date = u'Date' + col_operation = u'Opération' + col_etat = u'Etat' + col_montant = u'Montant net en' + col_action = u'Action' + + class item(ItemElement): + klass = Transaction + + def condition(self): + return not u'Aucune opération en attente' in CleanText(TableCell('date'))(self) + + obj_date = Date(CleanText(TableCell('date')), LinearDateGuesser()) + obj_type = Transaction.TYPE_UNKNOWN + obj_label = CleanText(TableCell('operation')) + obj_amount = CleanDecimal(TableCell('montant')) + + +class OperationsTraiteesPage(LoggedPage, HTMLPage): + @method + class get_history(TableElement): + head_xpath = u'//table[@summary="Liste des opérations en attente"]/thead/tr/th/text()' + item_xpath = u'//table[@summary="Liste des opérations en attente"]/tbody/tr' + + col_date = u'Date' + col_operation = u'Opération' + col_montant = u'Montant net en' + + class item(ItemElement): + klass = Transaction + + def condition(self): + return not u'Aucune opération' in CleanText(TableCell('date'))(self) + + obj_date = Date(CleanText(TableCell('date')), LinearDateGuesser()) + obj_type = Transaction.TYPE_UNKNOWN + obj_label = CleanText(TableCell('operation')) + obj_amount = CleanDecimal(TableCell('montant')) diff --git a/modules/groupamaes/test.py b/modules/groupamaes/test.py new file mode 100644 index 00000000..a7bfd352 --- /dev/null +++ b/modules/groupamaes/test.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2014 Bezleputh +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.test import BackendTest + + +class GroupamaesTest(BackendTest): + BACKEND = 'groupamaes' + + def test_groupamaes(self): + l = list(self.backend.iter_accounts()) + if len(l) > 0: + a = l[0] + list(self.backend.iter_history(a))