Invoice Complexity Classification

This page documents the current state of invoice complexity classification in BINS and the Wasteology platform, and outlines the three viable approaches for implementing easy/medium/hard classification.
As of 2026-04-16, no easy/medium/hard complexity field exists in any table, endpoint, or configuration in the BINS codebase or database schema. This page documents what does exist that can support building it.
What Currently Exists
1. ML Line Item Confidence Scores (Best ML Signal)
Every invoice that flows through the invoice-listener pipeline has its line items classified by an external ML API. The confidence scores from this API are the best existing signal for invoice processing difficulty.
API: https://service-normalization.agreeablesmoke-44fc50ff.centralus.azurecontainerapps.io/predict/service_info/
Per-line-item output stored in docai.raw_invoice_normalized_line_items:
| Column | Description |
|---|---|
md5 | Invoice identifier |
label | Label type (service_desc, size, material, container, is_valid) |
value | Predicted label value |
confidence | Confidence score (0.0–1.0) |
Complexity proxy logic:
-- Invoices with low average confidence = harder to process
SELECT
md5,
COUNT(*) as line_item_count,
AVG(confidence) as avg_confidence,
SUM(CASE WHEN label = 'is_valid' AND value = 'false' THEN 1 ELSE 0 END) as invalid_items,
CASE
WHEN AVG(confidence) >= 0.85 AND invalid_items = 0 THEN 'Easy'
WHEN AVG(confidence) >= 0.60 THEN 'Medium'
ELSE 'Hard'
END as complexity
FROM docai.raw_invoice_normalized_line_items
GROUP BY md5
2. "Needs Coordination" Status (Existing Implicit Rule)
The only existing business rule that implicitly flags invoices as harder to process. Any invoice missing one of these fields at ingest is automatically set to "Needs Coordination":
service_addresscounterparty(matched CieTrade location)vendor_namestateservice_dateinvoice_date
This is a binary flag (missing/not missing), not a 3-tier classification — but it is the existing "complexity" signal in the system.
3. Configurable Rule Engine
The BINS backend has a full rule engine built into the database. Rules fire on invoice create or update, evaluate field conditions, and execute actions — including setting arbitrary fields.
Tables:
| Table | Description |
|---|---|
trashy.invoice_rules | Rule definitions (name, trigger: on_create / on_update) |
trashy.rule_conditions | Conditions (field, operator, value) per rule |
trashy.rule_actions | Actions per rule: set_status, set_team, set_field, call_ai_agent |
Supported condition operators: equals, contains, greater_than, less_than, not_equals, not_contains
Supported action types: set_status, set_team, set_field (arbitrary field), call_ai_agent (stubbed — not yet implemented)
Adding a complexity rule requires:
- One database migration to add a
complexitycolumn totrashy.invoices(VARCHAR(10)— 'Easy'/'Medium'/'Hard') - Insert rows into
invoice_rules,rule_conditions,rule_actions— no code changes needed
Example rule configuration (database records):
Rule: "High Value = Hard"
Trigger: on_create
Condition: invoice_amount > 10000
Action: set_field complexity = 'Hard'
Rule: "Missing Fields = Hard"
Trigger: on_create
Condition: status equals "Needs Coordination"
Action: set_field complexity = 'Hard'
Rule: "Standard Invoice = Easy"
Trigger: on_create
Condition: invoice_amount <= 5000 AND status != "Needs Coordination"
Action: set_field complexity = 'Easy'
4. User-Defined Flags
trashy.flags + trashy.invoice_flags: named, hex-colored tags that users apply to invoices through the BINS UI. Flags are a flexible, general-purpose feature — different departments use them differently (priority, routing, review status, etc.). The 6 production flags (High Priority, Medium Priority, Low Priority, Past Due, Recycling Receipt, Stop Service) serve existing departmental workflows and should not be repurposed for complexity tiers.
To add AI-driven complexity classification via flags, new flags would be created (e.g. "Easy", "Medium", "Hard") — not the existing ones reused. No code change is required to add flags; they are database records.
Check production flags:
SELECT * FROM trashy.flags;
SELECT f.name, COUNT(if.invoice_id) as usage_count
FROM trashy.flags f
LEFT JOIN trashy.invoice_flags if ON f.id = if.flag_id
GROUP BY f.name;
Implementation Options Compared
| Option | Schema Change | Code Change | Effort | Data Source | Best For |
|---|---|---|---|---|---|
Rule engine (set_field complexity) | Add complexity column | None — DB records only | Low | Invoice fields (amount, status, vendor) | Business rules driven by field conditions |
| ML signal (aggregate line item confidence) | Add complexity column | New dbt model or backend query | Medium | docai.raw_invoice_normalized_line_items | Data-driven, objective scoring |
| Manual flags (new flags) | None | None | Minimal | User-entered | Quick start; human judgment — create new Easy/Medium/Hard flags, do not reuse existing ones |
| Hybrid (ML → rule engine override) | Add complexity column | None for rules; new query for ML | Medium | Both | Combines objective + business rule overrides |
Recommended Path
The rule engine approach is most aligned with how BINS was architected. trashy.invoice_rules records fire on invoice create/update and can set arbitrary fields — no code deployment required. Steps:
-
Check production state:
-- Existing flags (for reference — do not reuse for complexity)
SELECT * FROM trashy.flags;
-- Existing rules
SELECT * FROM trashy.invoice_rules;
SELECT * FROM trashy.rule_conditions; -
If no rules exist yet, add the column:
ALTER TABLE trashy.invoices ADD COLUMN complexity VARCHAR(10);
-- Values: 'Easy', 'Medium', 'Hard', NULL (unclassified) -
Insert rule records for agreed-upon complexity criteria. No code deployment required — rules are evaluated at runtime from the DB.
-
Optional: backfill from ML signals by querying
docai.raw_invoice_normalized_line_itemsand computing average confidence per invoice as a seed classification.
Related Pages
- BINS Invoice Ingestion Flow — where line item ML data is generated
- GCP Infrastructure — Cloud Run and Cloud Functions infrastructure