From 1fd0cb12914f8c1509e64d8d83b94fd6edeea95e Mon Sep 17 00:00:00 2001 From: Christophe Lampin Date: Mon, 22 Jul 2013 16:11:29 +0200 Subject: [PATCH] Add module [amelipro] for the heathcare professional ameli website Signed-off-by: Christophe Lampin --- modules/amelipro/__init__.py | 24 ++++++++ modules/amelipro/backend.py | 93 +++++++++++++++++++++++++++++ modules/amelipro/browser.py | 109 ++++++++++++++++++++++++++++++++++ modules/amelipro/favicon.png | Bin 0 -> 6369 bytes modules/amelipro/pages.py | 111 +++++++++++++++++++++++++++++++++++ modules/amelipro/test.py | 34 +++++++++++ 6 files changed, 371 insertions(+) create mode 100644 modules/amelipro/__init__.py create mode 100755 modules/amelipro/backend.py create mode 100755 modules/amelipro/browser.py create mode 100755 modules/amelipro/favicon.png create mode 100755 modules/amelipro/pages.py create mode 100755 modules/amelipro/test.py diff --git a/modules/amelipro/__init__.py b/modules/amelipro/__init__.py new file mode 100644 index 00000000..48b13b92 --- /dev/null +++ b/modules/amelipro/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Christophe Lampin +# +# 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 AmeliProBackend + + +__all__ = ['AmeliProBackend'] diff --git a/modules/amelipro/backend.py b/modules/amelipro/backend.py new file mode 100755 index 00000000..3f0285f5 --- /dev/null +++ b/modules/amelipro/backend.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Christophe Lampin +# +# 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 . + +import urllib +from weboob.capabilities.bill import ICapBill, SubscriptionNotFound, BillNotFound, Subscription, Bill +from weboob.tools.backend import BaseBackend, BackendConfig +from weboob.tools.value import ValueBackendPassword +from .browser import AmeliProBrowser + +__all__ = ['AmeliProBackend'] + + +class AmeliProBackend(BaseBackend, ICapBill): + NAME = 'amelipro' + DESCRIPTION = u'Ameli website: French Health Insurance for Professionals' + MAINTAINER = u'Christophe Lampin' + EMAIL = 'weboob@lampin.net' + VERSION = '0.g' + LICENSE = 'AGPLv3+' + BROWSER = AmeliProBrowser + CONFIG = BackendConfig(ValueBackendPassword('login', + label='numero de SS', + masked=False), + ValueBackendPassword('password', + label='Password', + masked=True) + ) + BROWSER = AmeliProBrowser + + def create_default_browser(self): + return self.create_browser(self.config['login'].get(), + self.config['password'].get()) + + def iter_subscription(self): + return self.browser.get_subscription_list() + + def get_subscription(self, _id): + if not _id.isdigit(): + raise SubscriptionNotFound() + with self.browser: + subscription = self.browser.get_subscription(_id) + if not subscription: + raise SubscriptionNotFound() + else: + return subscription + + def iter_bills_history(self, subscription): + if not isinstance(subscription, Subscription): + subscription = self.get_subscription(subscription) + with self.browser: + return self.browser.iter_history(subscription) + + def get_details(self, subscription): + if not isinstance(subscription, Subscription): + subscription = self.get_subscription(subscription) + with self.browser: + return self.browser.get_details(subscription) + + def iter_bills(self, subscription): + if not isinstance(subscription, Subscription): + subscription = self.get_subscription(subscription) + with self.browser: + return self.browser.iter_bills() + + def get_bill(self, id): + with self.browser: + bill = self.browser.get_bill(id) + if not bill: + raise BillNotFound() + else: + return bill + + def download_bill(self, bill): + if not isinstance(bill, Bill): + bill = self.get_bill(bill) + with self.browser: + return self.browser.readurl(bill._url,urllib.urlencode(bill._args)) diff --git a/modules/amelipro/browser.py b/modules/amelipro/browser.py new file mode 100755 index 00000000..d65c5998 --- /dev/null +++ b/modules/amelipro/browser.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Christophe Lampin +# +# 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 . + +import urllib +import mechanize +from weboob.tools.browser import BaseBrowser +from weboob.capabilities.bill import Detail +from decimal import * +from .pages import LoginPage, HomePage, AccountPage, HistoryPage, BillsPage + +__all__ = ['AmeliProBrowser'] + +class AmeliProBrowser(BaseBrowser): + PROTOCOL = 'https' + DOMAIN = 'espacepro.ameli.fr' + ENCODING = None + + PAGES = {'.*_pageLabel=vp_login_page.*': LoginPage, + '.*_pageLabel=vp_accueil.*': HomePage, + '.*_pageLabel=vp_coordonnees_infos_perso_page.*': AccountPage, + '.*_pageLabel=vp_recherche_par_date_paiements_page.*': HistoryPage, + '.*_pageLabel=vp_releves_mensuels_page.*': BillsPage, + } + + loginp = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_pageLabel=vp_login_page' + homep = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_pageLabel=vp_accueil_book' + accountp = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_pageLabel=vp_coordonnees_infos_perso_page' + billsp = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_pageLabel=vp_releves_mensuels_page' + searchp = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_pageLabel=vp_recherche_par_date_paiements_page' + historyp = '/PortailPS/appmanager/portailps/professionnelsante?_nfpb=true&_windowLabel=vp_recherche_paiement_tiers_payant_portlet_1&vp_recherche_paiement_tiers_payant_portlet_1_actionOverride=%2Fportlets%2Fpaiements%2Frecherche&_pageLabel=vp_recherche_par_date_paiements_page' + + def home(self): + self.location(self.homep) + + def is_logged(self): + if self.is_on_page(LoginPage): + return False + return True + + def login(self): + assert isinstance(self.username, basestring) + assert isinstance(self.password, basestring) + if not self.is_on_page(LoginPage): + self.location(self.loginp) + self.page.login(self.username, self.password) + if self.is_on_page(LoginPage): + raise BrowserIncorrectPassword() + + def get_subscription_list(self): + if not self.is_on_page(AccountPage): + self.location(self.accountp) + return self.page.get_subscription_list() + + def get_subscription(self, id): + assert isinstance(id, basestring) + return self.get_subscription_list() + + def iter_history(self, subscription): + if not self.is_on_page(HistoryPage): + self.location(self.searchp) + + date_deb = self.page.document.xpath('//input[@name="vp_recherche_paiement_tiers_payant_portlet_1dateDebutRecherche"]')[0].value + date_fin = self.page.document.xpath('//input[@name="vp_recherche_paiement_tiers_payant_portlet_1dateFinRecherche"]')[0].value + + data = {'vp_recherche_paiement_tiers_payant_portlet_1dateDebutRecherche': date_deb, + 'vp_recherche_paiement_tiers_payant_portlet_1dateFinRecherche': date_fin, + 'vp_recherche_paiement_tiers_payant_portlet_1codeOrganisme': 'null', + 'vp_recherche_paiement_tiers_payant_portlet_1actionEvt': 'rechercheParDate', + 'vp_recherche_paiement_tiers_payant_portlet_1codeRegime': '01', + } + + self.location(self.historyp, urllib.urlencode(data)) + return self.page.iter_history() + + def get_details(self, sub): + det = Detail() + det.id = sub.id + det.label = sub.label + det.infos = '' + det.price = Decimal('0.0') + return det + + def iter_bills(self): + if not self.is_on_page(BillsPage): + self.location(self.billsp) + return self.page.iter_bills() + + def get_bill(self, id): + assert isinstance(id, basestring) + for b in self.get_bills(): + if id == b.id: + return b + return None diff --git a/modules/amelipro/favicon.png b/modules/amelipro/favicon.png new file mode 100755 index 0000000000000000000000000000000000000000..a6098aee9b4015f2a953dc0ac2ea552a90cf3d80 GIT binary patch literal 6369 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. + + +from datetime import datetime +from decimal import Decimal +import re +from weboob.tools.browser import BasePage +from weboob.capabilities.bill import Subscription, Detail, Bill + + +__all__ = ['LoginPage', 'HomePage', 'AccountPage', 'HistoryPage', 'BillsPage'] + +# Ugly array to avoid the use of french locale +FRENCH_MONTHS = [u'janvier', u'février', u'mars', u'avril', u'mai', u'juin', u'juillet', u'août', u'septembre', u'octobre', u'novembre', u'décembre'] + +class LoginPage(BasePage): + def login(self, login, password): + self.browser.select_form('connexionCompteForm') + self.browser["vp_connexion_portlet_1numPS"] = login.encode('utf8') + self.browser["vp_connexion_portlet_1password"] = password.encode('utf8') + self.browser.submit() + +class HomePage(BasePage): + + def on_loaded(self): + pass + + +class AccountPage(BasePage): + + def get_subscription_list(self): + ident = self.document.xpath('//div[@id="identification"]')[0] + prof = self.document.xpath('//div[@id="profession"]')[0] + name = ident.xpath('//p/b')[0].text.replace(' ', ' ').strip() + number = ident.xpath('//p')[1].text.replace('Cabinet', '').strip() + label = prof.xpath('//div[@class="zoneTexte"]')[0].text.strip() + sub = Subscription(number) + sub._id = number + sub.label = unicode(name) + ' ' + unicode(label) + sub.subscriber = unicode(name) + return sub + +class HistoryPage(BasePage): + + def iter_history(self): + table = self.document.xpath('//table[contains(concat(" ", @class, " "), " cTableauTriable ")]')[0].xpath('.//tr') + for tr in table: + list_a = tr.xpath('.//a') + if len(list_a) == 0: + continue + date = tr.xpath('.//td')[0].text.strip() + lot = list_a[0].text + factures = tr.xpath('.//div[@class="cAlignGauche"]/a') + factures_lbl = '' + for a in factures: + factures_lbl = factures_lbl + a.text + ' ' + montant = tr.xpath('.//div[@class="cAlignDroite"]')[0].text.strip() + det = Detail() + det.id = lot + det.label = lot + det.infos = factures_lbl + det.datetime = datetime.strptime(date, "%d/%m/%Y").date() + det.price = Decimal(montant.replace(',','.')) + yield det + +class BillsPage(BasePage): + + def iter_bills(self): + table = self.document.xpath('//table[@id="releveCompteMensuel"]')[0].xpath('.//tr') + for tr in table: + list_tds = tr.xpath('.//td') + if len(list_tds) == 0: + continue + + date_str = tr.xpath('.//td[@class="cAlignGauche"]')[0].text + month_str = date_str.split()[0] + date = datetime.strptime(re.sub(month_str,str(FRENCH_MONTHS.index(month_str) + 1),date_str),"%m %Y").date() + amount = tr.xpath('.//td[@class="cAlignDroite"]')[0].text + for format in ('CSV', 'PDF'): + bil = Bill() + bil.id = date.strftime("%Y%m") + format + bil.date = date + bil.label = u''+amount.strip() + bil.format = u''+format + filedate = date.strftime("%m%Y") + bil._url = '/PortailPS/fichier.do' + bil._args = {'FICHIER.type': format.lower() + '.releveCompteMensuel', + 'dateReleve': filedate, + 'FICHIER.titre': '', + } + yield bil + + def get_bill(self,bill): + self.location(bill._url, urllib.urlencode(bill._args)) diff --git a/modules/amelipro/test.py b/modules/amelipro/test.py new file mode 100755 index 00000000..97bcebe2 --- /dev/null +++ b/modules/amelipro/test.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Christophe Lampin +# +# 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 + + +__all__ = ['AmeliProTest'] + + +class AmeliProTest(BackendTest): + BACKEND = 'AmeliPro' + + def test_AmeliPro(self): + for subscription in self.backend.iter_subscription(): + list(self.backend.iter_history(subscription.id)) + for bill in self.backend.iter_bills(subscription.id): + self.backend.download_bill(bill.id)