Added ragione sociale check. Added verbose mode. Now saving all, ft and nc in different files

Signed-off-by: Ettore Dreucci <ettore.dreucci@gmail.com>
This commit is contained in:
2021-09-26 17:52:41 +02:00
parent ae88f33f02
commit 7fa8d5120a
3 changed files with 79 additions and 29 deletions

View File

@@ -1,5 +1,6 @@
"""ask for an input file (.xlsx) and an output file (.pdf) and downloads and unite every invoice""" """ask for an input file (.xlsx) and an output file (.pdf) and downloads and unite every invoice"""
import os
import shutil import shutil
import tempfile import tempfile
import openpyxl import openpyxl
@@ -33,12 +34,15 @@ def get_invoices_info(input_file_path: str) -> tuple:
owner_name = '_'.join(sheet["B1"].value.split()[2:]) owner_name = '_'.join(sheet["B1"].value.split()[2:])
for i in range(1, sheet.max_row+1): 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: if invoice_id is not None and "CCSR" in invoice_id:
invoice_id = invoice_id.replace("/", "-") 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 = { invoice = {
"id": invoice_id, "id": invoice_id,
"type": invoice_type,
"url": invoice_url, "url": invoice_url,
"path": None, "path": None,
"good": None, "good": None,
@@ -49,7 +53,9 @@ def get_invoices_info(input_file_path: str) -> tuple:
def download_invoices(parent): def download_invoices(parent):
"""download invoices from CCSR""" """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") parent.log_dialog.log_text.AppendText("Download file input\n")
wx.Yield() wx.Yield()
@@ -82,6 +88,7 @@ def download_invoices(parent):
invoice["good"] = False invoice["good"] = False
else: else:
downloaded_count += 1 downloaded_count += 1
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"])) parent.log_dialog.log_text.AppendText("%d/%d scaricata fattura %s in %s\n" % (downloaded_count, invoices_count, invoice_id, invoice["path"]))
wx.Yield() wx.Yield()
invoice["good"] = True invoice["good"] = True
@@ -100,17 +107,34 @@ def download_invoices(parent):
parent.output_pdf_dialog.SetFilename("fatture_%s.pdf" % invoices_info[0]) parent.output_pdf_dialog.SetFilename("fatture_%s.pdf" % invoices_info[0])
if parent.output_pdf_dialog.ShowModal() == wx.ID_OK: if parent.output_pdf_dialog.ShowModal() == wx.ID_OK:
output_file_path = parent.output_pdf_dialog.GetPath() output_all_file_path = parent.output_pdf_dialog.GetPath()
merger = PyPDF2.PdfFileMerger() path, ext = os.path.splitext(output_all_file_path)
for invoice in invoices.values(): output_ft_file_path = path+"_ft"+ext
if invoice["good"]: output_nc_file_path = path+"_nc"+ext
merger.append(PyPDF2.PdfFileReader(open(invoice["path"], "rb")))
merger.write(output_file_path)
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) 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.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()) parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr())
wx.Yield() wx.Yield()
parent.log_dialog.open_file_btn.Enable() parent.log_dialog.open_file_btn.Enable()

View File

@@ -2,6 +2,7 @@
import os import os
import sys import sys
import getopt
import subprocess import subprocess
import atexit import atexit
import wx import wx
@@ -20,6 +21,18 @@ CONVERT_ACTION = 20
class FattureCCSRFrame(wx.Frame): class FattureCCSRFrame(wx.Frame):
"""main application frame""" """main application frame"""
def __init__(self, *args, **kwds): 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) atexit.register(self.exit_handler)
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.TAB_TRAVERSAL kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.TAB_TRAVERSAL

View File

@@ -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 xsd_path = os.path.join(sys._MEIPASS, 'schema.xsd') # pylint: disable=no-member, protected-access
else: else:
xsd_path = os.path.join(__location__, 'schema.xsd') xsd_path = os.path.join(__location__, 'schema.xsd')
xmlschema_doc = lxml.etree.parse(xsd_path) xmlschema_doc = lxml.etree.parse(xsd_path) # pylint: disable=c-extension-no-member
xmlschema = lxml.etree.XMLSchema(xmlschema_doc) xmlschema = lxml.etree.XMLSchema(xmlschema_doc) # pylint: disable=c-extension-no-member
return xmlschema.validate(xml_tree) return xmlschema.validate(xml_tree)
@@ -46,20 +46,20 @@ def import_xml(parent, input_file_path) -> dict:
if not input_file_path: if not input_file_path:
return None 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): 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.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()) parent.log_dialog.log_text.SetDefaultStyle(wx.TextAttr())
wx.Yield() wx.Yield()
return None
root = xml_tree.getroot() root = xml_tree.getroot()
for invoice in root.iter('{STAT_FATTURATO_CTERZI}Dettagli'): for invoice in root.iter('{STAT_FATTURATO_CTERZI}Dettagli'):
lines = dict() lines = dict()
invoice_num = invoice.get('protocollo_fatturatestata') invoice_num = invoice.get('protocollo_fatturatestata')
invoice_type = invoice.get('fat_ndc') 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 total_calculated_amount = 0
ritenuta_acconto = 0 ritenuta_acconto = 0
@@ -74,13 +74,21 @@ def import_xml(parent, input_file_path) -> dict:
else: else:
lines[desc] = amount lines[desc] = amount
total_calculated_amount += 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 = { invoice_elem = {
"numFattura": invoice_num, "numFattura": invoice_num,
"tipoFattura": invoice_type, "tipoFattura": invoice_type,
"rifFattura": invoice.get('protocollo_fatturatestata1'), "rifFattura": invoice.get('protocollo_fatturatestata1'),
"dataFattura": datetime.datetime.fromisoformat(invoice.get('data_fatturatestata')).strftime("%d%m%Y"), "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), "posDivide": str(len(invoice.get('cognome_cliente')) + 1),
"cf": invoice.get('cf_piva_cliente'), "cf": invoice.get('cf_piva_cliente'),
"importoTotale": total_calculated_amount, "importoTotale": total_calculated_amount,
@@ -88,6 +96,7 @@ def import_xml(parent, input_file_path) -> dict:
"righe": lines, "righe": lines,
} }
invoices[invoice_num] = invoice_elem invoices[invoice_num] = invoice_elem
if parent.verbose:
parent.log_dialog.log_text.AppendText("Importata fattura n. %s\n" % invoice_num) parent.log_dialog.log_text.AppendText("Importata fattura n. %s\n" % invoice_num)
wx.Yield() wx.Yield()
return invoices return invoices
@@ -254,6 +263,7 @@ def convert(parent):
line.append('S') # TRF-RIF-FATTURA 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('S' + ' '*2 + 'S' + ' '*2) # TRF-RISERVATO-B + TRF-MASTRO-CF + TRF-MOV-PRIVATO + TRF-SPESE-MEDICHE + TRF-FILLER
line.append('\n') line.append('\n')
if parent.verbose:
parent.log_dialog.log_text.AppendText("Creato record #0 per fattura n. %s\n" % invoice["numFattura"]) parent.log_dialog.log_text.AppendText("Creato record #0 per fattura n. %s\n" % invoice["numFattura"])
wx.Yield() wx.Yield()
@@ -275,6 +285,7 @@ def convert(parent):
line.append((' ' + ' ' + ' ')*49) # TRF-A21CO-TIPO + TRF-A21CO-TIPO-SPESA + TRF-A21CO-FLAG-SPESA 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(' ' + 'S' + ' '*76) # TRF-SPESE-FUNEBRI + TRF-A21CO-PAGAM + FILLER + FILLER
line.append('\n') line.append('\n')
if parent.verbose:
parent.log_dialog.log_text.AppendText("Creato record #5 per fattura n. %s\n" % invoice["numFattura"]) parent.log_dialog.log_text.AppendText("Creato record #5 per fattura n. %s\n" % invoice["numFattura"])
wx.Yield() wx.Yield()
@@ -295,12 +306,14 @@ def convert(parent):
line.append(' '*8) # TRF-CK-RCHARGE line.append(' '*8) # TRF-CK-RCHARGE
line.append('0'*(15-len(invoice["numFattura"])) + invoice["numFattura"]) # TRF-XNUM-DOC-ORI 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 line.append(' ' + '00' + ' '*1090) # TRF-MEM-ESIGIB-IVA + TRF-COD-IDENTIFICATIVO + TRF-ID-IMPORTAZIONE + TRF-XNUM-DOC-ORI-20 + SPAZIO + FILLER
if parent.verbose:
parent.log_dialog.log_text.AppendText("Creato record #1 per fattura n. %s\n" % invoice["numFattura"]) parent.log_dialog.log_text.AppendText("Creato record #1 per fattura n. %s\n" % invoice["numFattura"])
wx.Yield() wx.Yield()
line = ''.join(line) + '\n' line = ''.join(line) + '\n'
traf2000_file.write(line) traf2000_file.write(line)
if parent.verbose:
parent.log_dialog.log_text.AppendText("Convertita fattura n. %s\n" % invoice["numFattura"]) parent.log_dialog.log_text.AppendText("Convertita fattura n. %s\n" % invoice["numFattura"])
wx.Yield() wx.Yield()