發票處理工作流程

Business
8 個節點 · 8 條連接business
ex-invoice-processing.osop.yaml
# Invoice Processing Workflow
# Receive invoices, extract data via OCR, match to POs, route for approval, process payment
osop_version: "2.0"
id: invoice-processing
name: "發票處理工作流程"

nodes:
  - id: receive_invoice
    type: api
    purpose: Accept invoice via email attachment, upload, or EDI and normalize to PDF
    runtime:
      endpoint: /api/v1/invoices/ingest
      method: POST
      url: https://ap-service.internal
    outputs: [invoice_id, source_channel, raw_document_url]
    timeout_sec: 30

  - id: ocr_extract
    type: agent
    purpose: Extract structured data from invoice PDF using document AI
    runtime:
      provider: google
      model: document-ai-invoice-parser
      config:
        output_format: json
        fields: [vendor_name, invoice_number, date, due_date, line_items, subtotal, tax, total, currency, bank_details]
    inputs: [raw_document_url]
    outputs: [extracted_data, confidence_scores, extraction_warnings]
    timeout_sec: 60
    retry_policy:
      max_retries: 2
      backoff_sec: 5
    explain: |
      Uses Google Document AI for structured extraction. Fields with
      confidence below 0.85 are flagged for manual review.

  - id: validate_data
    type: cli
    purpose: Validate extracted fields against business rules and check for duplicates
    runtime:
      command: |
        python validate_invoice.py \
          --invoice-id ${invoice_id} \
          --check-duplicate \
          --check-vendor-exists \
          --check-amounts \
          --check-dates
    inputs: [extracted_data, invoice_id]
    outputs: [validation_passed, validation_errors, duplicate_flag]
    timeout_sec: 30

  - id: match_purchase_order
    type: db
    purpose: Match invoice line items to open purchase orders using fuzzy matching
    runtime:
      engine: postgresql
      connection: postgresql://erp:5432/procurement
    inputs: [extracted_data]
    outputs: [matched_po_ids, match_confidence, unmatched_lines]
    timeout_sec: 15
    explain: |
      Three-way match: invoice amount, PO amount, and goods receipt.
      Tolerance of 2% on amounts. Unmatched lines require manual review.

  - id: route_approval
    type: agent
    purpose: Determine approval routing based on amount thresholds and department policy
    runtime:
      provider: internal
      model: approval-rules-engine
      config:
        thresholds:
          - { max: 1000, approvers: 1, role: "team_lead" }
          - { max: 10000, approvers: 1, role: "department_head" }
          - { max: 100000, approvers: 2, role: "vp_finance" }
    inputs: [extracted_data, matched_po_ids]
    outputs: [approval_route, required_approvers]

  - id: manager_approval
    type: human
    purpose: Designated approver reviews invoice details, PO match, and approves payment
    role: approver
    inputs: [extracted_data, matched_po_ids, match_confidence, unmatched_lines]
    outputs: [approval_decision, rejection_reason]
    approval_gate:
      required_approvers: 1
      timeout_min: 4320
    explain: |
      Approver sees side-by-side view of invoice and matched PO.
      Can approve, reject, or request additional information from vendor.

  - id: process_payment
    type: api
    purpose: Submit approved invoice for payment via ERP payment batch
    runtime:
      endpoint: /api/v1/payments/schedule
      method: POST
      url: https://erp.internal
    inputs: [invoice_id, extracted_data, approval_decision]
    outputs: [payment_id, scheduled_date, payment_method]
    security:
      auth: oauth2
      secret_ref: ERP_SERVICE_ACCOUNT
    timeout_sec: 30

  - id: update_ledger
    type: db
    purpose: Post accounting entries to general ledger and update AP aging
    runtime:
      engine: postgresql
      connection: postgresql://erp:5432/accounting
    inputs: [payment_id, extracted_data]
    outputs: [journal_entry_id, gl_posted]
    timeout_sec: 15

edges:
  - from: receive_invoice
    to: ocr_extract
    mode: sequential

  - from: ocr_extract
    to: validate_data
    mode: sequential

  - from: validate_data
    to: match_purchase_order
    mode: conditional
    condition: "validation_passed == true && duplicate_flag == false"

  - from: match_purchase_order
    to: route_approval
    mode: sequential

  - from: route_approval
    to: manager_approval
    mode: sequential

  - from: manager_approval
    to: process_payment
    mode: conditional
    condition: "approval_decision == 'approved'"

  - from: process_payment
    to: update_ledger
    mode: sequential

  - from: validate_data
    to: receive_invoice
    mode: error
    condition: "duplicate_flag == true"
    label: "Duplicate detected, reject and notify sender"