From 360022820de56d8e1b2a51eed098b8df24d4f768 Mon Sep 17 00:00:00 2001 From: Narayanan Madaswamy Date: Tue, 14 Jul 2026 13:59:00 +0530 Subject: [PATCH] Template mapping and detect issue fixed --- check_matches.py | 16 ++++ debug_match.py | 26 ++++++ docengine/app/api/v1/templates.py | 66 +++++++++++++ docengine/app/services/fingerprint_service.py | 93 ++++++++++++------- frontend/src/app/services/template.service.ts | 8 +- .../src/app/templates/templates.component.ts | 29 ++++-- print_cells.py | 14 +++ print_fp.py | 13 +++ print_fp2.py | 18 ++++ regenerate_fingerprints.py | 21 +++++ 10 files changed, 264 insertions(+), 40 deletions(-) create mode 100644 check_matches.py create mode 100644 debug_match.py create mode 100644 print_cells.py create mode 100644 print_fp.py create mode 100644 print_fp2.py create mode 100644 regenerate_fingerprints.py diff --git a/check_matches.py b/check_matches.py new file mode 100644 index 0000000..d25458a --- /dev/null +++ b/check_matches.py @@ -0,0 +1,16 @@ +import sys +import os +sys.path.append(os.path.join(os.getcwd(), 'docengine')) + +from app.core.database import SessionLocal +from app.models.document import TemplateMatch +from app.models.template import DocumentFormat + +db = SessionLocal() +matches = db.query(TemplateMatch).order_by(TemplateMatch.created_at.desc()).limit(10).all() +print(f"Found {len(matches)} matches.") +for m in matches: + fmt = db.query(DocumentFormat).filter(DocumentFormat.id == m.format_id).first() + fmt_name = fmt.name if fmt else 'Unknown' + print(f"Match: doc_id={m.document_id}, format_id={m.format_id}, name={fmt_name}, score={m.confidence_score}") + print(f"Details: {m.match_details}") diff --git a/debug_match.py b/debug_match.py new file mode 100644 index 0000000..b9391ae --- /dev/null +++ b/debug_match.py @@ -0,0 +1,26 @@ +import sys +import os +sys.path.append(os.path.join(os.getcwd(), 'docengine')) + +from app.core.database import SessionLocal +from app.models.document import Document +from app.services.matching_service import MatchingService + +db = SessionLocal() +doc = db.query(Document).order_by(Document.created_at.desc()).first() +if not doc: + print("No documents found.") + sys.exit(0) + +print(f"Latest document: {doc.id} (status: {doc.status})") + +svc = MatchingService(db) +try: + # Match with min_confidence=0.0 so it returns EVERYTHING + matches = svc.match_document(doc.id, min_confidence=0.0) + print(f"Returned {len(matches)} matches.") + for m in matches: + print(f"Match: format_id={m.format_id}, score={m.confidence_score}") + print(f"Details: {m.match_details}") +except Exception as e: + print(f"Error matching: {e}") diff --git a/docengine/app/api/v1/templates.py b/docengine/app/api/v1/templates.py index d67f4b3..ec3ac4d 100644 --- a/docengine/app/api/v1/templates.py +++ b/docengine/app/api/v1/templates.py @@ -83,6 +83,63 @@ def create_template( } +@router.put( + "/{template_id}", + response_model=dict, + summary="Update Template", + description="Update an existing template name and its fields.", +) +def update_template( + template_id: uuid.UUID, + payload: TemplateCreateRequest, + current_user: CurrentUser, + db: Session = Depends(get_db), +) -> dict: + """Update a template.""" + template_repo = TemplateRepository(db) + template = template_repo.get_by_id(template_id) + if not template: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Template '{template_id}' not found", + ) + + if template.name != payload.template_name: + template.name = payload.template_name + + from app.models.template import DocumentCell + db.query(DocumentCell).filter(DocumentCell.format_id == template_id).delete() + + saved_fields = [] + cell_repo = DocumentCellRepository(db) + for index, field in enumerate(payload.fields): + cell = cell_repo.create_cell( + format_id=template.id, + page_number=1, + row_no=0, + column_no=0, + field_name=field.field_label, + data_type=field.field_type, + x=0.0, + y=0.0, + width=0.0, + height=0.0, + is_dynamic=True + ) + saved_fields.append({ + "field_label": cell.field_name, + "field_type": cell.data_type + }) + + db.commit() + + return { + "pk_template_id": str(template.id), + "template_name": template.name, + "fields": saved_fields + } + + @router.post( "/{template_id}/mappings/save", response_model=SuccessResponse, @@ -109,6 +166,15 @@ def save_mappings( table_repo = TableFormatRepository(db) table_col_repo = TableColumnRepository(db) + # Delete existing field mappings and table formats for this template + from app.models.template import DocumentRegion, TableFormat + db.query(DocumentRegion).filter( + DocumentRegion.format_id == template_id, + DocumentRegion.region_type == "field_mapping" + ).delete() + db.query(TableFormat).filter(TableFormat.format_id == template_id).delete() + db.flush() + cells = cell_repo.get_template_cells(template_id) cell_map = {c.field_name: c for c in cells} table_format = None diff --git a/docengine/app/services/fingerprint_service.py b/docengine/app/services/fingerprint_service.py index 2d43681..b109424 100644 --- a/docengine/app/services/fingerprint_service.py +++ b/docengine/app/services/fingerprint_service.py @@ -145,6 +145,11 @@ class FingerprintService: if not template.table_formats: return None + # Filter out dummy tables created by manual mappings (width=1000, height=1000) + valid_tables = [tf for tf in template.table_formats if tf.width != 1000.0 and tf.height != 1000.0] + if not valid_tables: + return None + return { "items": [ { @@ -156,14 +161,35 @@ class FingerprintService: "rows": tf.rows, "columns": tf.columns, } - for tf in template.table_formats + for tf in valid_tables ] } def _extract_cell_coordinates(self, template: DocumentFormat) -> dict[str, Any] | None: """Extract cell coordinates from template.""" + # For manually mapped templates, prefer the actual mapped regions + field_regions = [r for r in template.regions if r.region_type == "field_mapping"] + if field_regions: + return { + "items": [ + { + "page": r.page_number, + "x": r.x, + "y": r.y, + "width": r.width, + "height": r.height, + } + for r in field_regions + ] + } + + # Otherwise fallback to template cells, but skip if they are all 0,0 (unmapped placeholders) if not template.cells: return None + + has_real_coords = any(c.width > 0 or c.height > 0 for c in template.cells) + if not has_real_coords: + return None return { "items": [ @@ -215,44 +241,49 @@ class FingerprintService: weights.append(3.0) # Logo coordinates similarity - logo_score = self._compare_coordinates( - fingerprint1.logo_coordinates, - fingerprint2_data.get("logo_coordinates"), - ) - scores.append(logo_score) - weights.append(2.0) + if fingerprint1.logo_coordinates and fingerprint1.logo_coordinates.get("items"): + logo_score = self._compare_coordinates( + fingerprint1.logo_coordinates, + fingerprint2_data.get("logo_coordinates"), + ) + scores.append(logo_score) + weights.append(2.0) # Header coordinates similarity - header_score = self._compare_coordinates( - fingerprint1.header_coordinates, - fingerprint2_data.get("header_coordinates"), - ) - scores.append(header_score) - weights.append(2.0) + if fingerprint1.header_coordinates and fingerprint1.header_coordinates.get("items"): + header_score = self._compare_coordinates( + fingerprint1.header_coordinates, + fingerprint2_data.get("header_coordinates"), + ) + scores.append(header_score) + weights.append(2.0) # Footer coordinates similarity - footer_score = self._compare_coordinates( - fingerprint1.footer_coordinates, - fingerprint2_data.get("footer_coordinates"), - ) - scores.append(footer_score) - weights.append(1.5) + if fingerprint1.footer_coordinates and fingerprint1.footer_coordinates.get("items"): + footer_score = self._compare_coordinates( + fingerprint1.footer_coordinates, + fingerprint2_data.get("footer_coordinates"), + ) + scores.append(footer_score) + weights.append(1.5) # Table coordinates similarity - table_score = self._compare_coordinates( - fingerprint1.table_coordinates, - fingerprint2_data.get("table_coordinates"), - ) - scores.append(table_score) - weights.append(2.5) + if fingerprint1.table_coordinates and fingerprint1.table_coordinates.get("items"): + table_score = self._compare_coordinates( + fingerprint1.table_coordinates, + fingerprint2_data.get("table_coordinates"), + ) + scores.append(table_score) + weights.append(2.0) # Cell coordinates similarity - cell_score = self._compare_coordinates( - fingerprint1.cell_coordinates, - fingerprint2_data.get("cell_coordinates"), - ) - scores.append(cell_score) - weights.append(1.5) + if fingerprint1.cell_coordinates and fingerprint1.cell_coordinates.get("items"): + cell_score = self._compare_coordinates( + fingerprint1.cell_coordinates, + fingerprint2_data.get("cell_coordinates"), + ) + scores.append(cell_score) + weights.append(1.5) # Weighted average total_weight = sum(weights) diff --git a/frontend/src/app/services/template.service.ts b/frontend/src/app/services/template.service.ts index c00e63b..6d18ba7 100644 --- a/frontend/src/app/services/template.service.ts +++ b/frontend/src/app/services/template.service.ts @@ -81,8 +81,12 @@ export class TemplateService { ); } - createTemplate(data: { template_name: string, source_document_id?: string, fields: TemplateField[] }): Observable