Commit d72ac45a authored by Florent Fourcot's avatar Florent Fourcot Committed by hydrargyrum
Browse files

boostrap payfit module

Payfit is a website for payroll and HR processes.
This module currently only support payroll documents listing and
download
parent d9735d3f
# -*- coding: utf-8 -*-
# Copyright(C) 2021 Florent Fourcot
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see <http://www.gnu.org/licenses/>.
from .module import PayFitModule
__all__ = ['PayFitModule']
# -*- coding: utf-8 -*-
# Copyright(C) 2021 Florent Fourcot
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see <http://www.gnu.org/licenses/>.
from woob.browser import LoginBrowser, need_login, URL
from woob.browser.exceptions import ClientError
from woob.browser.profiles import Firefox
from woob.exceptions import BrowserIncorrectPassword
from woob.capabilities.base import find_object
from woob.capabilities.bill import DocumentNotFound
from .pages import LoginPage, AccountListPage, UserInfoPage, DocumentsPage, CategoryPage
class PayFitBrowser(LoginBrowser):
BASEURL = 'https://api.payfit.com/'
PROFILE = Firefox()
login = URL('/auth/signin', LoginPage)
account_list = URL('/hr/individuals/accounts/list', AccountListPage) # GET
user_info = URL('/hr/user/info', UserInfoPage) # POST
set_account = URL('/auth/updateCurrentAccount')
document_list = URL('/files/files', DocumentsPage)
category_info = URL('/files/category', CategoryPage)
download = URL(r'/files/file/(?P<id>\w+)\?attachment=1')
def do_login(self):
data = {"email": self.username,
"password": self.password,
"remember": False}
try:
self.login.go(json=data)
except ClientError:
raise BrowserIncorrectPassword()
@need_login
def iter_documents(self, subscription):
employee_id, company_id = subscription.id.split("-")
self.set_account.go(params={"companyId": company_id, "employeeId": employee_id})
self.category_info.go(params={"name": "payslip", "country": subscription._country})
payslip_id = self.page.get_id()
self.document_list.go(json={"employeeIds": [employee_id],
"companyIds": [company_id],
"categoryIds": [payslip_id]})
yield from self.page.iter_documents()
@need_login
def iter_subscription(self):
self.account_list.go()
for company, employee in self.page.iter_accounts():
self.set_account.go(params={"companyId": company["id"], "employeeId": employee["id"]})
self.user_info.go(data={})
yield from self.page.get_subscription(company, employee)
@need_login
def get_document(self, id):
return find_object(self.iter_documents(None), id=id,
error=DocumentNotFound)
# -*- coding: utf-8 -*-
# Copyright(C) 2021 Florent Fourcot
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see <http://www.gnu.org/licenses/>.
import hashlib
import hmac
from woob.tools.backend import Module, BackendConfig
from woob.capabilities.base import find_object
from woob.capabilities.bill import CapDocument, SubscriptionNotFound,\
Document, DocumentNotFound
from woob.tools.value import Value, ValueBackendPassword
from .browser import PayFitBrowser
__all__ = ['PayFitModule']
class PayFitModule(Module, CapDocument):
NAME = 'payfit'
DESCRIPTION = 'payfit website'
MAINTAINER = 'Florent Fourcot'
EMAIL = 'woob@flo.fourcot.fr'
LICENSE = 'LGPLv3+'
VERSION = '3.1'
BROWSER = PayFitBrowser
CONFIG = BackendConfig(Value('login', label='Email address', required=True),
ValueBackendPassword('password', label='Password'))
def create_default_browser(self):
mac = hmac.new(self.config['password'].get().encode(), msg=b'', digestmod=hashlib.sha256)
return self.create_browser(self.config['login'].get(), mac.hexdigest())
def get_document(self, _id):
_, sub_id = _id.split("-", maxsplit=1)
return find_object(self.iter_documents(sub_id), id=_id,
error=DocumentNotFound)
def get_subscription(self, _id):
return find_object(self.browser.iter_subscription(), id=_id,
error=SubscriptionNotFound)
def iter_documents(self, subscription):
if isinstance(subscription, str):
subscription = self.get_subscription(subscription)
return self.browser.iter_documents(subscription)
def iter_subscription(self):
return self.browser.iter_subscription()
def download_document(self, doc):
if not isinstance(doc, Document):
doc = self.get_document(doc)
return self.browser.open(doc.url).content
# -*- coding: utf-8 -*-
# Copyright(C) 2021 Florent Fourcot
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this woob module. If not, see <http://www.gnu.org/licenses/>.
from woob.browser.pages import LoggedPage, JsonPage
from woob.browser.elements import ItemElement, DictElement, method
from woob.browser.filters.json import Dict
from woob.capabilities.bill import Subscription, Document
from woob.browser.filters.standard import Date, BrowserURL, Format
class LoginPage(JsonPage):
pass
class UserInfoPage(LoggedPage, JsonPage):
def get_subscription(self, company, employee):
subscription = Subscription()
subscription.id = f"{employee['id']}-{company['id']}"
subscription.label = f"{self.get('jobName')} - {self.get('companyName')}"
subscription.subscriber = self.get('fullName')
subscription._country = self.get('companyCountry')
yield subscription
class AccountListPage(LoggedPage, JsonPage):
def iter_accounts(self):
for account in self.doc:
employee = account["accountInfo"]
company = account["companyInfo"]
if "employeeId" not in account["account"]:
continue
employee["id"] = account["account"]["employeeId"]
company["id"] = account["account"]["companyId"]
yield company, employee
class DocumentsPage(LoggedPage, JsonPage):
@method
class iter_documents(DictElement):
class item(ItemElement):
klass = Document
obj_date = Date(Dict('createdAt'))
obj_format = Dict('type')
obj_label = Dict('name')
obj_id = Format("%s-%s-%s", Dict('id'), Dict('employeeId'), Dict('companyId'))
obj_url = BrowserURL('download', id=Dict('id'))
class CategoryPage(LoggedPage, JsonPage):
def get_id(self):
return self.get('id')
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment