diff --git a/fatture_ccsr/downloader.py b/fatture_ccsr/downloader.py index 85a1294..efc5d9c 100644 --- a/fatture_ccsr/downloader.py +++ b/fatture_ccsr/downloader.py @@ -1,5 +1,6 @@ """ask for an input file (.xlsx) and an output file (.pdf) and downloads and unite every invoice""" +import os import shutil import tempfile import openpyxl @@ -33,12 +34,15 @@ def get_invoices_info(input_file_path: str) -> tuple: owner_name = '_'.join(sheet["B1"].value.split()[2:]) for i in range(1, sheet.max_row+1): - invoice_id = sheet["I"+str(i)].value + row = str(i) + invoice_id = sheet["I"+row].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_type = sheet["AP"+row].value + invoice_url = sheet["BG"+row].hyperlink.target invoice = { "id": invoice_id, + "type": invoice_type, "url": invoice_url, "path": None, "good": None, @@ -49,7 +53,9 @@ def get_invoices_info(input_file_path: str) -> tuple: def download_invoices(parent): """download invoices from CCSR""" - output_file_path = None + output_all_file_path = None + output_ft_file_path = None + output_nc_file_path = None parent.log_dialog.log_text.AppendText("Download file input\n") wx.Yield() @@ -82,8 +88,9 @@ def download_invoices(parent): invoice["good"] = False else: downloaded_count += 1 - parent.log_dialog.log_text.AppendText("%d/%d scaricata fattura %s in %s\n" % (downloaded_count, invoices_count, invoice_id, invoice["path"])) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("%d/%d scaricata fattura %s in %s\n" % (downloaded_count, invoices_count, invoice_id, invoice["path"])) + wx.Yield() invoice["good"] = True else: parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.RED, font=wx.Font(wx.FontInfo(8).Bold()))) @@ -100,17 +107,34 @@ def download_invoices(parent): parent.output_pdf_dialog.SetFilename("fatture_%s.pdf" % invoices_info[0]) if parent.output_pdf_dialog.ShowModal() == wx.ID_OK: - output_file_path = parent.output_pdf_dialog.GetPath() - merger = PyPDF2.PdfFileMerger() - for invoice in invoices.values(): - if invoice["good"]: - merger.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb"))) - merger.write(output_file_path) + output_all_file_path = parent.output_pdf_dialog.GetPath() + path, ext = os.path.splitext(output_all_file_path) + output_ft_file_path = path+"_ft"+ext + output_nc_file_path = path+"_nc"+ext + merger_ft = PyPDF2.PdfFileMerger() + merger_nc = PyPDF2.PdfFileMerger() + merger_all = PyPDF2.PdfFileMerger() + for invoice_id, invoice in invoices.items(): + if invoice["good"]: + merger_all.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb"))) + if invoice["type"] == "Fattura": + merger_ft.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb"))) + elif invoice["type"] == "Nota di credito": + merger_nc.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb"))) + else: + parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.RED, font=wx.Font(wx.FontInfo(8).Bold()))) + parent.log_dialog.log_text.AppendText("Errore: la fattura %s ha tipo sconosciuto %s\n" % (invoice_id, invoice["type"])) + parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr()) + merger_all.write(output_all_file_path) + merger_ft.write(output_ft_file_path) + merger_nc.write(output_nc_file_path) shutil.rmtree(tmp_dir, ignore_errors=True) parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.BLACK, font=wx.Font(wx.FontInfo(8).Bold()))) - parent.log_dialog.log_text.AppendText("Il pdf contenente le fatture si trova in %s\n" % output_file_path) + parent.log_dialog.log_text.AppendText("Il pdf contenente tutti i documenti si trova in %s\n" % output_all_file_path) + parent.log_dialog.log_text.AppendText("Il pdf contenente tutti le fatture si trova in %s\n" % output_ft_file_path) + parent.log_dialog.log_text.AppendText("Il pdf contenente tutti le note di credito si trova in %s\n" % output_nc_file_path) parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr()) wx.Yield() parent.log_dialog.open_file_btn.Enable() diff --git a/fatture_ccsr/fatture_ccsr.py b/fatture_ccsr/fatture_ccsr.py index 508c50c..356b618 100644 --- a/fatture_ccsr/fatture_ccsr.py +++ b/fatture_ccsr/fatture_ccsr.py @@ -2,6 +2,7 @@ import os import sys +import getopt import subprocess import atexit import wx @@ -20,6 +21,18 @@ CONVERT_ACTION = 20 class FattureCCSRFrame(wx.Frame): """main application frame""" def __init__(self, *args, **kwds): + self.verbose = False + try: + opts, _ = getopt.getopt(sys.argv[1:], "v", ["verbose="]) + for opt, _ in opts: + if opt == '-h': + print("fatture_ccsr -v|--verbose") + elif opt in ('-v', '--verbose'): + self.verbose = True + except getopt.GetoptError: + print("fatture_ccsr -v|--verbose") + sys.exit(2) + atexit.register(self.exit_handler) kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.TAB_TRAVERSAL diff --git a/fatture_ccsr/traf2000_converter.py b/fatture_ccsr/traf2000_converter.py index a638988..dc4b300 100755 --- a/fatture_ccsr/traf2000_converter.py +++ b/fatture_ccsr/traf2000_converter.py @@ -35,8 +35,8 @@ def validate_xml(xml_tree) -> bool: xsd_path = os.path.join(sys._MEIPASS, 'schema.xsd') # pylint: disable=no-member, protected-access else: xsd_path = os.path.join(__location__, 'schema.xsd') - xmlschema_doc = lxml.etree.parse(xsd_path) - xmlschema = lxml.etree.XMLSchema(xmlschema_doc) + xmlschema_doc = lxml.etree.parse(xsd_path) # pylint: disable=c-extension-no-member + xmlschema = lxml.etree.XMLSchema(xmlschema_doc) # pylint: disable=c-extension-no-member return xmlschema.validate(xml_tree) @@ -46,20 +46,20 @@ def import_xml(parent, input_file_path) -> dict: if not input_file_path: return None - xml_tree = lxml.etree.parse(input_file_path) + xml_tree = lxml.etree.parse(input_file_path) # pylint: disable=c-extension-no-member if not validate_xml(xml_tree): parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.RED, font=wx.Font(wx.FontInfo(8).Bold()))) - parent.log_dialog.log_text.AppendText("ERRORE: xml non valido secondo lo schema xsd") + parent.log_dialog.log_text.AppendText("ERRORE: xml non valido secondo lo schema xsd\n") parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr()) wx.Yield() - return None + root = xml_tree.getroot() for invoice in root.iter('{STAT_FATTURATO_CTERZI}Dettagli'): lines = dict() invoice_num = invoice.get('protocollo_fatturatestata') invoice_type = invoice.get('fat_ndc') - total_amount = int(format(round(float(invoice.get('denorm_importototale_fatturatestata')), 2), '.2f').replace('.', '').replace('-', '')) * -1 if '-' in invoice.get('denorm_importototale_fatturatestata') else 1 + # total_amount = int(format(round(float(invoice.get('denorm_importototale_fatturatestata')), 2), '.2f').replace('.', '').replace('-', '')) * -1 if '-' in invoice.get('denorm_importototale_fatturatestata') else 1 total_calculated_amount = 0 ritenuta_acconto = 0 @@ -74,13 +74,21 @@ def import_xml(parent, input_file_path) -> dict: else: lines[desc] = amount total_calculated_amount += amount + try: + ragione_sociale = unidecode.unidecode(invoice.get('cognome_cliente') + ' ' + ' '.join(invoice.get('nome_cliente').split()[0:2])) + except TypeError: + parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.RED, font=wx.Font(wx.FontInfo(8).Bold()))) + parent.log_dialog.log_text.AppendText("ERRORE: il documento %s ha ragione sociale non valida!\n" % invoice_num) + parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr()) + wx.Yield() + continue invoice_elem = { "numFattura": invoice_num, "tipoFattura": invoice_type, "rifFattura": invoice.get('protocollo_fatturatestata1'), "dataFattura": datetime.datetime.fromisoformat(invoice.get('data_fatturatestata')).strftime("%d%m%Y"), - "ragioneSociale": unidecode.unidecode(invoice.get('cognome_cliente') + ' ' + ' '.join(invoice.get('nome_cliente').split()[0:2])), + "ragioneSociale": ragione_sociale, "posDivide": str(len(invoice.get('cognome_cliente')) + 1), "cf": invoice.get('cf_piva_cliente'), "importoTotale": total_calculated_amount, @@ -88,8 +96,9 @@ def import_xml(parent, input_file_path) -> dict: "righe": lines, } invoices[invoice_num] = invoice_elem - parent.log_dialog.log_text.AppendText("Importata fattura n. %s\n" % invoice_num) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("Importata fattura n. %s\n" % invoice_num) + wx.Yield() return invoices @@ -254,8 +263,9 @@ def convert(parent): line.append('S') # TRF-RIF-FATTURA line.append('S' + ' '*2 + 'S' + ' '*2) # TRF-RISERVATO-B + TRF-MASTRO-CF + TRF-MOV-PRIVATO + TRF-SPESE-MEDICHE + TRF-FILLER line.append('\n') - parent.log_dialog.log_text.AppendText("Creato record #0 per fattura n. %s\n" % invoice["numFattura"]) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("Creato record #0 per fattura n. %s\n" % invoice["numFattura"]) + wx.Yield() #RECORD 5 per Tessera Sanitaria line.append('04103' + '3' + '5') # TRF5-DITTA + TRF5-VERSIONE + TRF5-TARC @@ -275,8 +285,9 @@ def convert(parent): line.append((' ' + ' ' + ' ')*49) # TRF-A21CO-TIPO + TRF-A21CO-TIPO-SPESA + TRF-A21CO-FLAG-SPESA line.append(' ' + 'S' + ' '*76) # TRF-SPESE-FUNEBRI + TRF-A21CO-PAGAM + FILLER + FILLER line.append('\n') - parent.log_dialog.log_text.AppendText("Creato record #5 per fattura n. %s\n" % invoice["numFattura"]) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("Creato record #5 per fattura n. %s\n" % invoice["numFattura"]) + wx.Yield() #RECORD 1 per num. doc. originale line.append('04103' + '3' + '1') # TRF1-DITTA + TRF1-VERSIONE + TRF1-TARC @@ -295,14 +306,16 @@ def convert(parent): line.append(' '*8) # TRF-CK-RCHARGE line.append('0'*(15-len(invoice["numFattura"])) + invoice["numFattura"]) # TRF-XNUM-DOC-ORI line.append(' ' + '00' + ' '*1090) # TRF-MEM-ESIGIB-IVA + TRF-COD-IDENTIFICATIVO + TRF-ID-IMPORTAZIONE + TRF-XNUM-DOC-ORI-20 + SPAZIO + FILLER - parent.log_dialog.log_text.AppendText("Creato record #1 per fattura n. %s\n" % invoice["numFattura"]) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("Creato record #1 per fattura n. %s\n" % invoice["numFattura"]) + wx.Yield() line = ''.join(line) + '\n' traf2000_file.write(line) - parent.log_dialog.log_text.AppendText("Convertita fattura n. %s\n" % invoice["numFattura"]) - wx.Yield() + if parent.verbose: + parent.log_dialog.log_text.AppendText("Convertita fattura n. %s\n" % invoice["numFattura"]) + wx.Yield() parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr(wx.BLACK, font=wx.Font(wx.FontInfo(8).Bold()))) parent.log_dialog.log_text.AppendText("Conversione terminata.\nTracciato TRAF2000 salvato in %s\n" % output_file_path)