Replaces Enterprise's account_invoice_extract with a Fusion-native pipeline: Stage 1 (text extraction): Tesseract OCRs the bill attachment via pytesseract + pdf2image. Pluggable OCRProvider adapter pattern allows future Mindee / Google Document AI / Ollama-vision backends. Stage 2 (field parsing): The fusion_accounting_ai LLMProvider reads the raw OCR text and returns structured invoice fields (vendor, invoice number, dates, amounts, line items) as JSON. Draft invoice fields are auto-populated for empty-only fields (never overwriting user-entered data). Vendor matching by name against res.partner with supplier_rank > 0. Adds: - account.move.ocr_state (selection: not_requested/pending/processing/ done/failed/manual) - account.move.ocr_raw_text, ocr_extracted_data (Json), ocr_backend, ocr_confidence - fusion.ocr.log (audit trail per OCR run) - res.company.fusion_ocr_enabled / fusion_ocr_default_backend / auto_run - /fusion/ocr/request_for_invoice JSON-RPC endpoint Backend availability detected at runtime via OCRProvider.is_available() classmethods. Tesseract 5.3.4 + pytesseract 0.3.13 + pdf2image 1.17.0 are installed in the container. Tests: 13 (TesseractAdapter availability + image OCR; flow tests for draft autofill, no-attachment guard, customer-invoice guard, ref-not- overwritten; field parser empty/clean-json/markdown-fence/bad-JSON/ provider-exception). All pass on westin-v19 OrbStack VM. Made-with: Cursor
46 lines
2.1 KiB
XML
46 lines
2.1 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<record id="view_move_form_inherit_fusion_ocr" model="ir.ui.view">
|
|
<field name="name">account.move.form.inherit.fusion_ocr</field>
|
|
<field name="model">account.move</field>
|
|
<field name="inherit_id" ref="account.view_move_form"/>
|
|
<field name="arch" type="xml">
|
|
|
|
<xpath expr="//header" position="inside">
|
|
<button name="action_request_ocr"
|
|
type="object"
|
|
string="Request OCR"
|
|
class="oe_highlight"
|
|
invisible="move_type not in ('in_invoice', 'in_refund') or ocr_state in ('processing', 'done')"/>
|
|
<button name="action_request_ocr"
|
|
type="object"
|
|
string="Re-run OCR"
|
|
invisible="move_type not in ('in_invoice', 'in_refund') or ocr_state not in ('done', 'failed', 'manual')"/>
|
|
</xpath>
|
|
|
|
<xpath expr="//sheet" position="inside">
|
|
<group string="Fusion OCR"
|
|
invisible="move_type not in ('in_invoice', 'in_refund') or ocr_state == 'not_requested'">
|
|
<group>
|
|
<field name="ocr_state" widget="badge"
|
|
decoration-success="ocr_state == 'done'"
|
|
decoration-info="ocr_state == 'processing'"
|
|
decoration-warning="ocr_state == 'manual'"
|
|
decoration-danger="ocr_state == 'failed'"/>
|
|
<field name="ocr_backend" readonly="1"/>
|
|
<field name="ocr_confidence" readonly="1" widget="percentage"/>
|
|
</group>
|
|
<group>
|
|
<field name="ocr_extracted_data" readonly="1" widget="text"/>
|
|
</group>
|
|
<field name="ocr_raw_text" readonly="1" nolabel="1"
|
|
placeholder="Raw OCR text..."/>
|
|
</group>
|
|
</xpath>
|
|
|
|
</field>
|
|
</record>
|
|
|
|
</odoo>
|