Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import pdfplumber | |
| def classify_pdf(pdf_path: str) -> str: | |
| """ | |
| Peeks at the first page of the PDF to determine its origin. | |
| Returns 'MARG', 'TALLY', or 'UNKNOWN'. | |
| """ | |
| with pdfplumber.open(pdf_path) as pdf: | |
| if len(pdf.pages) == 0: | |
| return "UNKNOWN" | |
| first_page = pdf.pages[0] | |
| words = first_page.extract_words(keep_blank_chars=False) | |
| if not words: | |
| return "UNKNOWN" | |
| text_stream = " ".join([w["text"].lower() for w in words]) | |
| # --- 1. Check for Explicit Metadata/Branding --- | |
| if "marg erp" in text_stream or "margcompusoft" in text_stream: | |
| return "MARG" | |
| if "tally prime" in text_stream or "tally solutions" in text_stream: | |
| return "TALLY" | |
| # --- 2. Check Structural Vocabulary (Heuristics) --- | |
| marg_score = 0 | |
| tally_score = 0 | |
| # Marg Keywords (Strictly Marg-specific financial headers) | |
| # Removed "batch", "exp", and "hsn" as they are shared with Tally | |
| marg_keywords = ["s.no.", "mrp", "p.rate", "total stock", "op.stock", "cl.stock"] | |
| for kw in marg_keywords: | |
| if kw in text_stream: | |
| marg_score += 1 | |
| # Tally Keywords (Hierarchical accounting) | |
| # Added "godown" which is highly specific to Tally | |
| tally_keywords = ["particulars", "opening balance", "inwards", "outwards", "closing balance", "grand total", | |
| "godown"] | |
| for kw in tally_keywords: | |
| if kw in text_stream: | |
| tally_score += 1 | |
| # Look for Marg's distinct dashed lines | |
| dashed_lines = sum(1 for w in words if "----" in w["text"] or "====" in w["text"]) | |
| if dashed_lines > 3: | |
| marg_score += 2 | |
| # Check for explicit Tally report titles combined with Particulars | |
| if "stock summary" in text_stream and "particulars" in text_stream: | |
| tally_score += 2 | |
| # --- 3. Final Decision --- | |
| if marg_score > tally_score and marg_score >= 1: | |
| return "MARG" | |
| elif tally_score > marg_score and tally_score >= 1: | |
| return "TALLY" | |
| # Check for explicit drawn tables (Vanilla Grids) | |
| if len(first_page.find_tables()) > 0: | |
| return "GENERIC" | |
| return "UNKNOWN" | |
| def classify_dataframe(df: pd.DataFrame) -> str: | |
| """Scans the first 15 rows of a dataframe for Tally/Marg signatures.""" | |
| # Convert the top portion to a single lowercase string for easy keyword matching | |
| top_rows_text = df.head(15).to_string().lower() | |
| if "marg erp" in top_rows_text or "margcompusoft" in top_rows_text: | |
| return "MARG" | |
| if "tally prime" in top_rows_text or "tally solutions" in top_rows_text: | |
| return "TALLY" | |
| # Heuristics | |
| if "particulars" in top_rows_text and "godown" in top_rows_text: | |
| return "TALLY" | |
| if "s.no" in top_rows_text and "mrp" in top_rows_text and "p.rate" in top_rows_text: | |
| return "MARG" | |
| return "GENERIC" |