Flag Odoo vendor bills that need a human before you pay

By General Input

Every weekday morning we check new vendor bills against their purchase orders, then post only the ones with price gaps, duplicates or no PO to Slack.

Integrations

  • Odoo
  • Slack Bot

Type

Agentic Task

Categories

  • Finance
  • Operations

Every weekday at 8am, review the vendor bills that have landed in my Odoo instance since the last run and tell me which ones a human actually needs to look at before we pay them. The goal is exception reporting for accounts payable, not a daily summary of everything.

Start by pulling the new bills. Use Odoo Search & Read Records (search_read) on the account.move model, filtered to vendor bills with a domain on move_type equal to in_invoice, and restricted to bills created since the previous run. Keep track of the timestamp of the last successful run between runs so no bill is reviewed twice and none are skipped. On the very first run, look back over the previous 7 days. Read the fields needed for the checks, including the vendor (partner_id), the vendor reference (ref), the bill name or number, invoice_date, amount_total, currency, the source document (invoice_origin), and the bill lines with their product, quantity and unit price.

For each bill, find the purchase order it references. The invoice_origin field on the bill usually carries the purchase order name. Use Search & Read Records (search_read) on purchase.order to locate that order, then Search & Read Records (search_read) on purchase.order.line to pull its lines with product, product_qty, price_unit and subtotal. Compare the bill against the purchase order line by line: unit price billed versus unit price ordered, quantity billed versus quantity ordered, and the bill total versus the order total. Match lines on product where possible rather than assuming the lines are in the same order.

Detect suspected duplicates. For each bill, use Odoo Count Records (search_count) on account.move to check whether another vendor bill already exists from the same vendor with the same vendor reference, and separately whether one exists from the same vendor with the same amount. Exclude the bill being checked from its own count. A count above zero on either check means a suspected duplicate. Also flag any bill that has no matching purchase order at all, whether the source document is empty or the referenced order cannot be found.

Apply a tolerance so the alert stays worth reading. Only report price or quantity variances that exceed 5 percent of the expected line value or 250 in the bill currency, whichever is larger. Make this tolerance easy to change in one place, since different finance teams set it differently. Suspected duplicates and bills with no purchase order are always reported regardless of size, because a duplicate payment costs the full amount rather than just the difference, and an unmatched bill has nothing to check it against.

Report the exceptions as a single Slack message to our finance channel using Slack Bot Send a Message. Group the exceptions by issue type, with headings for price variances, quantity variances, suspected duplicates, and bills with no purchase order. Under each heading list one line per bill showing the vendor name, the bill amount, the specific variance found stated concretely (for example billed at 42.00 per unit against 38.00 ordered, a 10.5 percent gap on 120 units), and the bill reference or number so someone can find it in Odoo immediately. Use Slack mrkdwn formatting, with single asterisks for bold. Lead with a one-line count of how many bills were reviewed and how many need attention.

Stay completely silent when nothing is anomalous. If every new bill matched its purchase order within tolerance and no duplicates or unmatched bills were found, post nothing at all, so the channel does not get trained to ignore the alert. Never post an all clear message.

Related prompts

Explore more prompts
A brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasonLiveChat coverage board for planning next week's shiftsPhone routing control panel for LiveKit voice agentsLinkedIn Ads budget pacing dashboard for every client accountGive your team Looker numbers without buying more seatsPause marketing emails to escalated customers, then restore them