jayanth-2005's picture
Update app.py
b6de961 verified
Raw History Blame Contribute Delete
4.27 kB
import gradio as gr
import pdfplumber
import pandas as pd
import re
def extract_invoices(file):
text = ""
with pdfplumber.open(file.name) as pdf:
for page in pdf.pages:
t = page.extract_text()
if t:
text += t + "\n"
# ---------------- INVOICE NUMBER ---------------- #
invoice_pattern = r'(?:Invoice\s*No|Invoice\s*Number|InvoiceNo|Inv\.?\s*No|Invoice\s*#|Bill\s*No|Bill\s*Number|Bill\s*of\s*Supply\s*No|Bill\s*of\s*Supply\s*Number)\s*[:#\-]?\s*([A-Za-z0-9\-\/]+)'
invoice_matches = list(re.finditer(invoice_pattern, text, re.IGNORECASE))
rows = []
processed_invoices = set()
# ---------------- GSTIN PATTERN ---------------- #
gstin_pattern = r'\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z\d]Z[A-Z\d]\b'
for i, match in enumerate(invoice_matches):
invoice_number = match.group(1)
if not re.search(r'\d', invoice_number) or len(invoice_number) < 4:
continue
if invoice_number in processed_invoices:
continue
processed_invoices.add(invoice_number)
start = match.start()
if i + 1 < len(invoice_matches):
end = invoice_matches[i + 1].start()
else:
end = len(text)
block = text[start:end]
# ---------------- DATE EXTRACTION ---------------- #
date_pattern = r'(?:\d{1,2}[\/\-.]\d{1,2}[\/\-.]\d{2,4}|\d{4}[\/\-.]\d{1,2}[\/\-.]\d{1,2}|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s+\d{1,2},?\s*\d{2,4}|\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s*\d{2,4})'
date_match = re.search(
r'(Invoice\s*Date|Bill\s*Date|Date\s*of\s*Invoice)\s*[:\-]?\s*\n?\s*(' + date_pattern + ')',
block,
re.IGNORECASE
)
if date_match:
invoice_date = date_match.group(2)
else:
fallback_date = re.search(date_pattern, block, re.IGNORECASE)
invoice_date = fallback_date.group(0) if fallback_date else ""
# ---------------- GSTIN EXTRACTION (BEFORE + AFTER) ---------------- #
# Look BEFORE invoice (important fix)
pre_start = max(0, start - 500)
pre_block = text[pre_start:start]
# Combine both
search_area = pre_block + block
# Try keyword-based extraction
gstin_match = re.search(
r'(GSTIN|GST\s*No|Supplier\s*GSTIN|Vendor\s*GSTIN)\s*[:\-]?\s*(' + gstin_pattern + ')',
search_area,
re.IGNORECASE
)
if gstin_match:
gstin = gstin_match.group(2)
else:
# fallback: get all GSTINs
gstin_list = re.findall(gstin_pattern, search_area, re.IGNORECASE)
if len(gstin_list) > 0:
gstin = gstin_list[0] # usually seller GSTIN
else:
gstin = ""
# ---------------- FLOAT DETECTION ---------------- #
float_pattern = r'(?:\d{1,3}(?:,\d{3})+|\d{1,2}(?:,\d{2})+(?:,\d{3}))\.\d{2}|\d+\.\d{2}'
float_numbers = re.findall(float_pattern, block)
float_numbers = [float(x.replace(",", "")) for x in float_numbers]
total_amount = max(float_numbers) if float_numbers else ""
# ---------------- ROW ---------------- #
row = {
"Invoice Number": invoice_number,
"Invoice Date": invoice_date,
"GSTIN": gstin,
"Narration": "Invoice processed",
"Debit Account": "Expense",
"Credit Account": "Vendor",
"Total Amount": total_amount
}
rows.append(row)
df = pd.DataFrame(rows)
excel_file = "invoice_output.xlsx"
df.to_excel(excel_file, index=False)
return df, excel_file
# ---------------- GRADIO UI ---------------- #
with gr.Blocks() as demo:
gr.Markdown("# Multiple Invoice PDF → Excel Extractor")
file_input = gr.File(label="Upload Invoice PDF")
extract_btn = gr.Button("Extract Invoices")
output_table = gr.Dataframe(label="Extracted Invoice Data")
download_file = gr.File(label="Download Excel")
extract_btn.click(
extract_invoices,
inputs=file_input,
outputs=[output_table, download_file]
)
demo.launch()