How a finance team runs its month-end close with Windmill
The month-end close can take several days, and it is hard to know where it stands.
Bank statements and invoices are often matched in a spreadsheet, and the team chases the owner of each discrepancy and writes supplier emails by hand. Here, one Windmill tool matches them every night, sends each discrepancy for approval and shows where the close stands.
The tool
This example is an internal tool for a finance team, its accountants and its financial controller, built in one Windmill workspace from four pieces: a data pipeline, a flow, an AI agent and an app. The data: bank transactions (date, amount, label, reference), invoices (supplier, number, amount, due date, cost center) and discrepancies (line, type, owner, status).
Each piece below comes with the prompt to build it in your own workspace. The whole project is on the Windmill Hub, with a recorded run of each piece, ready to add to your workspace: Month-end close on the Hub.
A data pipeline matches transactions and invoices every night
Every night, a schedule runs the pipeline. It imports the bank transactions and the invoices, matches each transaction to an invoice by amount, date and reference, and writes the lines it cannot match to a discrepancies table.
Read more: Data pipelines.
In the folder f/finance, build a data pipeline that runs every night. A first script imports the bank transactions from the bank's CSV export into a bank_transactions table (date, amount, label, reference). A second step matches each transaction to the invoices table by amount, date and reference, and writes the lines it cannot match to a discrepancies table (line, type, owner, status).
A flow sends each discrepancy for approval
For each new discrepancy, a flow asks the owner of the cost center to approve or reject it, in Slack or by email. An approval step pauses the flow until they answer.
When nobody answers within 2 days, a branch sends a reminder, then asks the financial controller.
Read more: Approval steps.
Create a flow discrepancy_approval that runs for each new discrepancy: an approval step asks the cost-center owner to approve or reject it in Slack, with a timeout of 2 days and "Continue on disapproval/timeout" turned on. On a timeout, a branch sends a reminder and asks again; on a second timeout, it asks the financial controller.
An AI agent explains a discrepancy
When an accountant asks for it, an AI agent step reads the discrepancy, the bank line and the related invoices with its tools, which are Windmill scripts. It explains the likely cause (a duplicate invoice, a partial payment, a bank fee), proposes the correcting entry without posting it and drafts the email to the supplier.
Read more: AI agents.
Add an AI agent step that takes one discrepancy, reads the bank line and the related invoices with two script tools (get_bank_line and search_invoices), explains the likely cause in two sentences, proposes the correcting entry without posting it, and drafts a short email to the supplier when one is needed.
An app shows where the close stands
A full-code app shows the close progress, the open discrepancies by owner and the pending approvals, with an Explain button on each line that runs the agent.
Read more: Full-code apps.
Build a full-code app that shows the close progress (transactions matched out of the total), the open discrepancies by owner and the pending approvals, with an Explain button on each discrepancy that runs the agent and shows its explanation and draft email.
A day with the tool
- Overnight, the pipeline goes through 1,284 transactions: 1,251 match on their own, 33 are discrepancies.
- Each owner receives the discrepancies to approve, in Slack or by email.
- An accountant clicks Explain: the agent finds a duplicate invoice and drafts the supplier email.
- The accountant reviews the email, sends it and marks the discrepancy as fixed.
- The controller follows the open discrepancies and the 6 pending approvals in the app.