Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -26,6 +26,7 @@ st.title("Import Fatture AI ✨")
|
|
| 26 |
# Gestionione LOGIN
|
| 27 |
if "logged" not in st.session_state:
|
| 28 |
st.session_state.logged = False
|
|
|
|
| 29 |
if st.session_state.logged == False:
|
| 30 |
login_placeholder = st.empty()
|
| 31 |
with login_placeholder.container():
|
|
@@ -87,7 +88,7 @@ API_KEY_GEMINI = settings_ai.API_KEY_GEMINI
|
|
| 87 |
# Configura il modello Gemini
|
| 88 |
genai.configure(api_key=API_KEY_GEMINI)
|
| 89 |
model = genai.GenerativeModel(
|
| 90 |
-
model_name=
|
| 91 |
generation_config=GENERATION_CONFIG,
|
| 92 |
system_instruction=SYSTEM_INSTRUCTION
|
| 93 |
)
|
|
@@ -291,7 +292,7 @@ def process_document(path_file: str, number_pages_split: int, use_azure: bool =
|
|
| 291 |
if mime_type is None:
|
| 292 |
mime_type = "application/octet-stream"
|
| 293 |
if use_azure:
|
| 294 |
-
number_pages_split =
|
| 295 |
if not path_file.lower().endswith(".pdf"):
|
| 296 |
print("File non PDF: elaborazione come immagine.")
|
| 297 |
documento_finale = process_document_splitted(path_file, chunk_label="(immagine)", use_azure=use_azure)
|
|
@@ -327,14 +328,31 @@ def process_document(path_file: str, number_pages_split: int, use_azure: bool =
|
|
| 327 |
if documento_finale is None:
|
| 328 |
raise RuntimeError("Nessun documento elaborato.")
|
| 329 |
|
| 330 |
-
# Controlli aggiuntivi: Se esiste un AVE non possono esistere altri articoli non ave.
|
| 331 |
if any(articolo.CodiceArticolo.startswith("AVE") for articolo in documento_finale.Articoli):
|
| 332 |
documento_finale.Articoli = [articolo for articolo in documento_finale.Articoli if articolo.CodiceArticolo.startswith("AVE")]
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
return documento_finale
|
| 339 |
|
| 340 |
# Analizza Fattura con AZURE
|
|
@@ -369,11 +387,15 @@ def parse_invoice_to_documento_azure(result) -> Documento:
|
|
| 369 |
if items_field and items_field.value_array:
|
| 370 |
for item in items_field.value_array:
|
| 371 |
product_code_field = item.value_object.get("ProductCode")
|
|
|
|
|
|
|
|
|
|
| 372 |
codice_articolo = product_code_field.value_string if product_code_field and product_code_field.value_string else ""
|
| 373 |
amount_field = item.value_object.get("Amount")
|
| 374 |
totale_non_ivato = amount_field.value_currency.amount if amount_field and amount_field.value_currency else 0.0
|
| 375 |
articolo = Articolo(
|
| 376 |
CodiceArticolo=codice_articolo,
|
|
|
|
| 377 |
TotaleNonIvato=totale_non_ivato,
|
| 378 |
Verificato=None
|
| 379 |
)
|
|
@@ -393,9 +415,11 @@ def main():
|
|
| 393 |
#st.set_page_config(page_title="Import Fatture AI", page_icon="✨")
|
| 394 |
st.sidebar.title("Caricamento File")
|
| 395 |
uploaded_files = st.sidebar.file_uploader("Seleziona uno o più PDF", type=["pdf", "jpg", "jpeg", "png"], accept_multiple_files=True)
|
| 396 |
-
model_ai = st.sidebar.selectbox("Modello", ['Gemini Flash 2.0'
|
|
|
|
|
|
|
| 397 |
use_azure = True if model_ai == 'Azure Intelligence' else False
|
| 398 |
-
number_pages_split = st.sidebar.slider('Split Pagine', 1, 30,
|
| 399 |
if st.sidebar.button("Importa", type="primary", use_container_width=True):
|
| 400 |
if not uploaded_files:
|
| 401 |
st.warning("Nessun file caricato!")
|
|
@@ -419,15 +443,18 @@ def main():
|
|
| 419 |
f"- **Articoli Compatibili**: {len(doc.Articoli)}\n"
|
| 420 |
f"- **Totale Documento**: {format_euro(doc.TotaleImponibile)}\n"
|
| 421 |
)
|
|
|
|
|
|
|
| 422 |
if totale_non_ivato_non_verificato > 0:
|
| 423 |
-
st.error(f"Totale Ave Non Verificato: {format_euro(
|
| 424 |
-
|
| 425 |
st.success(f"Totale Ave Verificato: {format_euro(totale_non_ivato_verificato)}")
|
| 426 |
df = pd.DataFrame([{k: v for k, v in Articolo.model_dump().items() if k != ""} for Articolo in doc.Articoli])
|
| 427 |
if 'Verificato' in df.columns:
|
| 428 |
df['Verificato'] = df['Verificato'].apply(lambda x: "✅" if x == 1 else "❌" if x == 0 else "❓" if x == 2 else x)
|
| 429 |
if totale_non_ivato > 0:
|
| 430 |
-
|
|
|
|
| 431 |
st.json(doc.model_dump(), expanded=False)
|
| 432 |
if totale_non_ivato == 0:
|
| 433 |
st.info(f"Non sono presenti articoli 'AVE'")
|
|
|
|
| 26 |
# Gestionione LOGIN
|
| 27 |
if "logged" not in st.session_state:
|
| 28 |
st.session_state.logged = False
|
| 29 |
+
st.session_state.model = "gemini-2.0-flash"
|
| 30 |
if st.session_state.logged == False:
|
| 31 |
login_placeholder = st.empty()
|
| 32 |
with login_placeholder.container():
|
|
|
|
| 88 |
# Configura il modello Gemini
|
| 89 |
genai.configure(api_key=API_KEY_GEMINI)
|
| 90 |
model = genai.GenerativeModel(
|
| 91 |
+
model_name=st.session_state.model,
|
| 92 |
generation_config=GENERATION_CONFIG,
|
| 93 |
system_instruction=SYSTEM_INSTRUCTION
|
| 94 |
)
|
|
|
|
| 292 |
if mime_type is None:
|
| 293 |
mime_type = "application/octet-stream"
|
| 294 |
if use_azure:
|
| 295 |
+
number_pages_split = 1
|
| 296 |
if not path_file.lower().endswith(".pdf"):
|
| 297 |
print("File non PDF: elaborazione come immagine.")
|
| 298 |
documento_finale = process_document_splitted(path_file, chunk_label="(immagine)", use_azure=use_azure)
|
|
|
|
| 328 |
if documento_finale is None:
|
| 329 |
raise RuntimeError("Nessun documento elaborato.")
|
| 330 |
|
| 331 |
+
# Controlli aggiuntivi: Se esiste un AVE non possono esistere altri articoli non ave.
|
| 332 |
if any(articolo.CodiceArticolo.startswith("AVE") for articolo in documento_finale.Articoli):
|
| 333 |
documento_finale.Articoli = [articolo for articolo in documento_finale.Articoli if articolo.CodiceArticolo.startswith("AVE")]
|
| 334 |
+
# Controllo occorrenze di doppioni
|
| 335 |
+
if path_file.lower().endswith(".pdf"):
|
| 336 |
+
pdf_text = pdf_to_text(path_file)
|
| 337 |
+
pdf_text = pdf_text.replace(" ", "")
|
| 338 |
+
occorrenze = {}
|
| 339 |
+
for articolo in documento_finale.Articoli:
|
| 340 |
+
codice_clean = articolo.CodiceArticolo.replace(" ", "")
|
| 341 |
+
if codice_clean not in occorrenze:
|
| 342 |
+
occorrenze[codice_clean] = pdf_text.count(codice_clean)
|
| 343 |
+
articoli_contati = {}
|
| 344 |
+
for articolo in documento_finale.Articoli:
|
| 345 |
+
codice_clean = articolo.CodiceArticolo.replace(" ", "")
|
| 346 |
+
if codice_clean in pdf_text:
|
| 347 |
+
print(codice_clean)
|
| 348 |
+
print(occorrenze[codice_clean])
|
| 349 |
+
articoli_contati[codice_clean] = articoli_contati.get(codice_clean, 0) + 1
|
| 350 |
+
if articoli_contati[codice_clean] <= occorrenze.get(codice_clean, 0):
|
| 351 |
+
articolo.Verificato = True
|
| 352 |
+
else:
|
| 353 |
+
articolo.Verificato = False
|
| 354 |
+
else:
|
| 355 |
+
articolo.Verificato = False
|
| 356 |
return documento_finale
|
| 357 |
|
| 358 |
# Analizza Fattura con AZURE
|
|
|
|
| 387 |
if items_field and items_field.value_array:
|
| 388 |
for item in items_field.value_array:
|
| 389 |
product_code_field = item.value_object.get("ProductCode")
|
| 390 |
+
description_field = str(item.value_object.get("Description").get("content"))
|
| 391 |
+
if not description_field:
|
| 392 |
+
description_field = ""
|
| 393 |
codice_articolo = product_code_field.value_string if product_code_field and product_code_field.value_string else ""
|
| 394 |
amount_field = item.value_object.get("Amount")
|
| 395 |
totale_non_ivato = amount_field.value_currency.amount if amount_field and amount_field.value_currency else 0.0
|
| 396 |
articolo = Articolo(
|
| 397 |
CodiceArticolo=codice_articolo,
|
| 398 |
+
DescrizioneArticolo=description_field,
|
| 399 |
TotaleNonIvato=totale_non_ivato,
|
| 400 |
Verificato=None
|
| 401 |
)
|
|
|
|
| 415 |
#st.set_page_config(page_title="Import Fatture AI", page_icon="✨")
|
| 416 |
st.sidebar.title("Caricamento File")
|
| 417 |
uploaded_files = st.sidebar.file_uploader("Seleziona uno o più PDF", type=["pdf", "jpg", "jpeg", "png"], accept_multiple_files=True)
|
| 418 |
+
model_ai = st.sidebar.selectbox("Modello", ['Gemini Flash 2.0', 'Gemini 2.5 Pro', 'Azure Intelligence'])
|
| 419 |
+
if model_ai == 'Gemini 2.5 Pro':
|
| 420 |
+
st.session_state.model = "gemini-2.5-pro-exp-03-25"
|
| 421 |
use_azure = True if model_ai == 'Azure Intelligence' else False
|
| 422 |
+
number_pages_split = st.sidebar.slider('Split Pagine', 1, 30, 1, help="Numero suddivisione pagine del PDF. Più il numero è basso e più il modello AI è preciso, più è alto più è veloce")
|
| 423 |
if st.sidebar.button("Importa", type="primary", use_container_width=True):
|
| 424 |
if not uploaded_files:
|
| 425 |
st.warning("Nessun file caricato!")
|
|
|
|
| 443 |
f"- **Articoli Compatibili**: {len(doc.Articoli)}\n"
|
| 444 |
f"- **Totale Documento**: {format_euro(doc.TotaleImponibile)}\n"
|
| 445 |
)
|
| 446 |
+
if totale_non_ivato > doc.TotaleImponibile and doc.TotaleImponibile > 0:
|
| 447 |
+
st.warning("Totale Ave maggiore di Totale Merce")
|
| 448 |
if totale_non_ivato_non_verificato > 0:
|
| 449 |
+
st.error(f"Totale Ave Non Verificato: {format_euro(totale_non_ivato_non_verificato)}")
|
| 450 |
+
if totale_non_ivato > 0:
|
| 451 |
st.success(f"Totale Ave Verificato: {format_euro(totale_non_ivato_verificato)}")
|
| 452 |
df = pd.DataFrame([{k: v for k, v in Articolo.model_dump().items() if k != ""} for Articolo in doc.Articoli])
|
| 453 |
if 'Verificato' in df.columns:
|
| 454 |
df['Verificato'] = df['Verificato'].apply(lambda x: "✅" if x == 1 else "❌" if x == 0 else "❓" if x == 2 else x)
|
| 455 |
if totale_non_ivato > 0:
|
| 456 |
+
df["TotaleNonIvato"] = df["TotaleNonIvato"].apply(format_euro)
|
| 457 |
+
st.dataframe(df, use_container_width=True)
|
| 458 |
st.json(doc.model_dump(), expanded=False)
|
| 459 |
if totale_non_ivato == 0:
|
| 460 |
st.info(f"Non sono presenti articoli 'AVE'")
|