Skip to main content

BINS Invoice Ingestion Flow

BINS (formerly Trashy) is the Wasteology invoice management application. It receives structured invoice data automatically from the invoice-listener pipeline, which uses Google Document AI to extract fields from PDF invoices arriving via email or OneDrive.

GAPI was the legacy SharePoint-based invoice system. The migration to BINS is complete — all users are on BINS. Migration tooling is no longer maintained.


The Two Invoice Systems

SystemTechnologyStatus
GAPI (legacy)SharePoint listPhased out — migration complete
BINS (active)FastAPI + React + Cloud SQL PostgreSQLActive — all users migrated

End-to-End Flow

PDF Invoice Arrives
(email: invoices@wasteologygroup.com OR OneDrive folder)


invoice-listener: Listener Jobs (GCP Cloud Run Jobs)
Every 10 min (email) / 1 hr (OneDrive)
Publishes blob path to Pub/Sub topic


invoice-listener: HTTP Handlers (GCP Cloud Run Services)
Receives Pub/Sub push message


orchestrator_function.py
├── Download PDF from Azure Blob Storage (pdfinvoices container)
├── Compute MD5 hash — deduplicate against GCS
├── Upload PDF to GCS: {GCS_PDF_BUCKET}/{md5}.pdf
├── Log to Azure SQL: docai.raw_invoices (md5, source, name)
├── Call Google Document AI → entity extraction
├── Save DocAI JSON to GCS: {GCS_RESPONSES_BUCKET}/{md5}
├── Run Service Normalization ML API on each line item
│ → Azure SQL: docai.raw_invoice_normalized_line_items
└── Fan out to 2 parallel queues:

├─ Work orders queue → downstream work order system
│ Passes MD5 + raw OCR text

└─ BINS/Trashy queue → trashy_function.py
POST /invoices/ingest → BINS FastAPI backend

├── Creates trashy.invoices row (Cloud SQL PostgreSQL)
└── Creates trashy.InvoiceProcessingStatus row
(4-stage pipeline audit log)

Document AI Extracted Fields

Google Document AI extracts these fields from the PDF. The orchestrator maps them to a structured dict that is passed to all downstream queues:

FieldBINS ColumnNotes
Vendor namevendor_name
Invoice numberinvoice_number
Invoice totalinvoice_amount
Amount dueamount_due
Invoice dateinvoice_date
Service dateservice_date
Due datedue_date
Service addressservice_address
Matched CieTrade locationlocationResolved via Azure address service
Assigned billing repassigned_toAssigned in BINS via Azure address service
State / regionstateResolved via Azure address service
Account numberaccount_number
Purchase orderpurchase_order
Retail pricing notesretail_pricing_notes

Line Item ML Classification

Each line item description is sent to the Service Normalization API during ingestion:

Endpoint: https://service-normalization.agreeablesmoke-44fc50ff.centralus.azurecontainerapps.io/predict/service_info/

Input: {"raw_text": "<line item description>"}

Output per line item:

LabelDescription
service_desc_label + _probaService description category + confidence
size_label + _probaContainer/equipment size + confidence
material_label + _probaMaterial type + confidence
container_label + _probaContainer type + confidence
is_valid + _probaWhether the line item is valid/parseable + confidence

Results stored in docai.raw_invoice_normalized_line_items on Azure SQL Server.

Pathfinder project

This classifier was built as part of the Pathfinder initiative. Confidence scores are stored in docai.raw_invoice_normalized_line_items but are not actively used in the current BINS UI or any automated workflow. The data is available as a potential signal for future complexity classification.

Complexity signal

The is_valid_proba and _proba scores per line item are the best existing ML signal for invoice complexity. Invoices with many low-confidence or invalid line items are harder to process. See Invoice Complexity Classification for how to use this.


Data Written Per Invoice

SystemTable / LocationWhat
Azure SQL Serverdocai.raw_invoicesMD5, source, filename (dedup audit)
Azure SQL Serverdocai.raw_invoice_normalized_line_itemsML labels + confidence per line item
GCS{GCS_PDF_BUCKET}/{md5}.pdfRaw PDF copy
GCS{GCS_RESPONSES_BUCKET}/{md5}Document AI JSON response
Cloud SQL PostgreSQLtrashy.invoicesFull structured invoice record
Cloud SQL PostgreSQLtrashy.InvoiceProcessingStatus4-stage pipeline audit log

Pipeline Stage Audit (trashy.InvoiceProcessingStatus)

Every uploaded invoice gets a row tracking its progress through 4 independent pipeline stages:

ColumnPossible ValuesWhat It Tracks
status_storagePENDING / SUCCESS / FAILEDPDF uploaded to GCS
status_doc_aiPENDING / SUCCESS / FAILEDDocument AI OCR completed
status_database_insertPENDING / SUCCESS / FAILED / DUPLICATEInvoice row written to BINS DB
status_webservice_callPENDING / SUCCESS / FAILEDAddress + assignment webservice call
last_error_messagetextError detail for last failed stage
retry_countintegerNumber of manual retries
created_attimestampWhen ingestion was first attempted
updated_attimestampLast state change

Admin view: GET /admin/processing-status?status=FAILED


BINS Backend Reporting Endpoints

MethodEndpointDescription
POST/invoices/queryPaginated filtered invoice list
POST/invoices/exportXLSX export — sync (≤1K rows) or async via GCS (>1K rows)
GET/admin/processing-statusAll pipeline status records; filter with ?status=FAILED
GET/admin/processing-status/{md5}Single invoice pipeline status
POST/admin/processing-status/{md5}/retryReset failed stage back to PENDING
GET/status/pipelineGCP Cloud Function + Scheduler health (admin only)
No aggregate stats today

There is no /api/stats, /api/counts, or GROUP-BY-status endpoint in the BINS backend. Aggregate reporting requires either exporting data or querying the trashy.invoices table directly.


GCP Infrastructure

All invoice-listener components run on GCP project academic-torch-405913:

Resource TypeNameSchedule / Trigger
Cloud Run Jobwasteologyinvoice-email-queued-listenerEvery 10 min
Cloud Run Jobwasteologyinvoice-onedrive-listener-queuedEvery 1 hour
Cloud Run Jobwasteologyinvoice-error-email-processorEvery 1 hour
Cloud Run Servicewasteololgy-email-handlersPub/Sub push
Cloud Run Servicewasteololgy-onedrive-handlersPub/Sub push
Cloud Run Servicewasteologyinvoice-mailgun-handlerPub/Sub push
Cloud Functiondb_inserterPub/Sub trigger
Cloud Functiondoc_ai_processorPub/Sub trigger
Cloud Functionwebservice_callerPub/Sub trigger
Active services

The active Cloud Run Services are the email, OneDrive, and trashy handlers, plus the recently added mailgun handler. Some Cloud Functions listed above may be inactive — confirm with the BINS team before modifying them.

See GCP Infrastructure for full networking, VPC, and Terraform details.