From 0e80834b4496eb53b2a4b058bb8ea4c302b07189 Mon Sep 17 00:00:00 2001 From: Ettore Dreucci Date: Mon, 30 Nov 2020 01:59:19 +0100 Subject: [PATCH] fattureCCSR: rewrite downloader in python. Signed-off-by: Ettore Dreucci --- downloader.py | 74 +++++++++++++++++++++++++++++++++++++++++++ fatture_ccsr.py | 43 +++++++++++++++++-------- traf2000_converter.py | 1 + 3 files changed, 105 insertions(+), 13 deletions(-) diff --git a/downloader.py b/downloader.py index b8177a2..a3e0584 100644 --- a/downloader.py +++ b/downloader.py @@ -1 +1,75 @@ """ask for an input file (.xlsx) and an output file (.pdf) and downloads and unite every invoice""" + +import shutil +import tempfile +import requests +import requests_ntlm +import openpyxl +import PyPDF2 + +import logger + +def get_invoices_info(input_file_path: str) -> dict: + """extract invoices IDs and URLs from xlsx input file""" + xlsx_file = openpyxl.load_workbook(input_file_path) + sheet = xlsx_file.active + invoices = dict() + + for i in range(1, sheet.max_row+1): + invoice_id = sheet["I"+str(i)].value + if invoice_id is not None and "CCSR" in invoice_id: + invoice_id = invoice_id.replace("/", "-") + invoice_url = sheet["BG"+str(i)].hyperlink.target + invoice = { + "id": invoice_id, + "url": invoice_url, + "path": None, + "good": None, + } + invoices[invoice_id] = invoice + + return invoices + + +def download_invoices(input_file_path: str, output_file_path: str, username: str, password: str): + """download invoices from CCSR""" + invoices = get_invoices_info(input_file_path) + + session = requests.Session() + session.auth = requests_ntlm.HttpNtlmAuth("sr\\"+username, password) + logger.downloader_logger.info("Inizio download fatture dal portale CCSR") + + tmp_dir = tempfile.mkdtemp() + + invoices_count = len(invoices) + processed_count = 0 + + for invoice_id, invoice in invoices.items(): + resp = session.get(invoice["url"]) + processed_count += 1 + if resp.status_code == 200: + with open(tmp_dir+"/"+invoice_id+".pdf", "wb") as output_file: + output_file.write(resp.content) + invoice["path"] = output_file.name + print(invoice["path"]) + try: + PyPDF2.PdfFileReader(open(invoice["path"], "rb")) + except (PyPDF2.utils.PdfReadError, OSError): + logger.downloader_logger.error("%d/%d fattura %s corrotta!", processed_count, invoices_count, invoice_id) + invoice["good"] = False + else: + logger.downloader_logger.info("%d/%d scaricata fattura %s in %s", processed_count, invoices_count, invoice_id, invoice["path"]) + invoice["good"] = True + else: + logger.downloader_logger.error("%d/%d impossibile scaricare fattura %s: %d", processed_count, invoices_count, invoice_id, resp.status_code) + invoice["good"] = False + + merger = PyPDF2.PdfFileMerger() + for invoice in invoices.values(): + if invoice["good"]: + merger.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb"))) + merger.write(output_file_path) + + shutil.rmtree(tmp_dir, ignore_errors=True) + + logger.downloader_logger.info("Download terminato. Il pdf contenente le fatture si trova in %s", output_file_path) diff --git a/fatture_ccsr.py b/fatture_ccsr.py index 2dbd4e0..4619110 100644 --- a/fatture_ccsr.py +++ b/fatture_ccsr.py @@ -3,6 +3,7 @@ import logging import wx +import downloader import traf2000_converter import exc import utils @@ -39,11 +40,9 @@ class LogDialog(wx.Dialog): log_handler.setLevel(logging.INFO) self.logger.addHandler(log_handler) - self.btn = wx.Button(self, wx.ID_OK, "Chiudi") - self.btn.Disable() - - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(log_text, 0, wx.ALL, 2) + main_sizer = wx.BoxSizer(wx.VERTICAL) + log_sizer = wx.BoxSizer(wx.HORIZONTAL) + log_sizer.Add(log_text, 0, wx.ALL, 2) if action == CONVERT_ACTION: self.nc_logger = logger.note_credito_logger @@ -51,9 +50,14 @@ class LogDialog(wx.Dialog): nc_handler = LogHandler(nc_text) self.nc_logger.addHandler(nc_handler) - sizer.Add(nc_text, 0, wx.ALL, 2) + log_sizer.Add(nc_text, 0, wx.ALL, 2) - self.SetSizerAndFit(sizer) + main_sizer.Add(log_sizer, 0, wx.ALL, 2) + self.btn = wx.Button(self, wx.ID_OK, "Chiudi") + self.btn.Disable() + main_sizer.Add(self.btn, 0, wx.ALL|wx.CENTER, 2) + + self.SetSizerAndFit(main_sizer) class LoginDialog(wx.Dialog): """login dialog for basic auth download""" @@ -76,6 +80,7 @@ class LoginDialog(wx.Dialog): pass_sizer.Add(self.password, 0, wx.ALL, 2) login_btn = wx.Button(self, label="Login") + login_btn.SetDefault() login_btn.Bind(wx.EVT_BUTTON, self.on_login) main_sizer = wx.BoxSizer(wx.VERTICAL) @@ -87,7 +92,7 @@ class LoginDialog(wx.Dialog): def on_login(self, _): """check credentials and login""" - if self.username not in ("", None) and self.password.GetValue() not in ("", None): + if self.username.GetValue() not in ("", None) and self.password.GetValue() not in ("", None): self.logged_id = True self.Close() @@ -127,7 +132,8 @@ class FattureCCSRFrame(wx.Frame): self.traf2000_btn.Disable() self.login_dlg = LoginDialog(self, "Inserisci le credenziali di login al portale della CCSR") - self.output_file_dialog = wx.FileDialog(panel, "Scegli dove salvare il file TRAF2000", defaultFile="TRAF2000", style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + self.output_traf2000_dialog = wx.FileDialog(panel, "Scegli dove salvare il file TRAF2000", defaultFile="TRAF2000", style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + self.output_pdf_dialog = wx.FileDialog(panel, "Scegli dove salvare il .pdf con le fatture scaricate", defaultFile="fatture.pdf", style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) main_sizer.Add(input_file_text, 0, wx.ALL|wx.CENTER, 2) main_sizer.Add(input_file_doc, 0, wx.ALL|wx.CENTER, 2) @@ -160,13 +166,24 @@ class FattureCCSRFrame(wx.Frame): """event raised when a button is clicked""" btn_id = event.GetEventObject().GetId() if btn_id == DOWNLOAD_ACTION: + if self.output_pdf_dialog.ShowModal() == wx.ID_OK: + self.output_file_path = self.output_pdf_dialog.GetPath() + else: + #TODO: avviso errore file output + return self.login_dlg.ShowModal() if self.login_dlg.logged_id: - print("Download") + self.log_dialog = LogDialog(self, "Download delle fatture dal portale CCSR", DOWNLOAD_ACTION) + self.log_dialog.Show() + downloader.download_invoices(self.input_file_path, self.output_file_path, self.login_dlg.username.GetValue(), self.login_dlg.password.GetValue()) + self.log_dialog.btn.Enable() elif btn_id == CONVERT_ACTION: - if self.output_file_dialog.ShowModal() == wx.ID_OK: - self.output_file_path = self.output_file_dialog.GetPath() - self.log_dialog = LogDialog(self, "Log", CONVERT_ACTION) + if self.output_traf2000_dialog.ShowModal() == wx.ID_OK: + self.output_file_path = self.output_traf2000_dialog.GetPath() + else: + #TODO: avviso errore file output + return + self.log_dialog = LogDialog(self, "Conversione delle fatture in TRAF2000", CONVERT_ACTION) self.log_dialog.Show() try: traf2000_converter.convert(self.input_file_path, self.output_file_path) diff --git a/traf2000_converter.py b/traf2000_converter.py index a6cf110..41bf661 100755 --- a/traf2000_converter.py +++ b/traf2000_converter.py @@ -281,3 +281,4 @@ def convert(input_file_path: str, out_file_path: str): traf2000_file.write(linea) logger.converter_logger.info("Convertita fattura n. %s", fattura["numFattura"]) + logger.converter_logger.info("Conversione terminata")