Odoo 19 Perpetual FIFO: Invoicing Before Stock Moves · Calibre Consulting

Perpetual FIFO in Odoo 19 when invoices run ahead of stock.

What Odoo 19 posts when a vendor bill precedes the receipt or an invoice precedes delivery, and how to keep COGS and the stock account right.

This guide explains which journal entries Odoo 19 posts under perpetual inventory valuation with FIFO costing when a vendor bill arrives before the goods, or a customer is invoiced before the goods ship, and how to keep the stock account in line. The short answer: a vendor bill posted early needs no fix, because the bill books the stock account and the receipt later supplies the matching stock value. A customer invoice posted early is the case to watch. Its cost of goods sold is worked out once, when the invoice is posted, from whatever cost Odoo holds at that moment, and nothing recalculates it when the delivery is validated.

It is written for accountants and owners setting up Odoo 19.

Before you start

What Odoo 19 posts at each step

Take 10 units bought at 12.00 each and later sold. With FIFO and perpetual valuation:

Odoo 19 no longer uses separate stock input and output (interim) accounts. Moves to or from a location with its own valuation account, such as inventory loss, still post at the time of the move.

When the vendor bill comes first

To bill goods from a purchase order before they arrive, the product's Control Policy on the Purchase tab must be On ordered quantities. On received quantities, the default for goods, a bill created from the order has nothing to bill until the receipt is done.

Until the receipt, the Stock Account is 120.00 higher than the Stock report. In Enterprise, Accounting > Review > Purchases > Billed Not Received lists the purchase lines billed beyond what has been received. If a stock closing is generated in that window, it credits the Stock Account and debits the Stock Variation account by 120.00. Each closing posts the gap between stock value and the account balance at its date, so the next closing after the receipt moves it back. Validating the receipt is all that is needed.

When the customer invoice comes first

If the goods have not shipped, Odoo prices the invoice's COGS from stock on hand, oldest units first. Any quantity beyond what is on hand is priced at the unit cost of the newest receipt counted, and with nothing on hand at all Odoo uses the product's Cost. When that cost is zero, for example a new product never received, Odoo adds no COGS lines at all rather than lines at zero.

The delivery posts nothing and the invoice is not revisited. The Stock report drops by the delivered value while the Stock Account still holds it, so the Inventory Valuation report proposes a credit to the Stock Account and a debit to Stock Variation. If Stock Variation is a current asset account, the cost waits on the balance sheet; if it is an expense account, the cost reaches profit and loss, but on that account rather than as COGS on the invoice. Scheduled Daily or Monthly closings do not run for a company whose default valuation is Perpetual, so this entry exists only when someone generates it.

How to handle pre-sold stock

Option 1: take the advance as a down payment.

  1. Open the Sales app, open the confirmed order and click Create Invoice.
  2. Set Create Invoice to Down payment (percentage) or Down payment (fixed amount), enter the amount and click Create Draft. Post the invoice. Its line carries the order's taxes but no product, so no COGS is posted.
  3. After the delivery, click Create Invoice again and choose Regular invoice. The final invoice deducts the down payment and posts COGS from the delivered units' FIFO cost.

Setting the product's Invoicing Policy to Delivered quantities stops a regular invoice from being raised for goods not yet shipped.

Option 2: reset the early invoice and post it again. After the delivery, open the invoice from Accounting > Customers > Invoices, click Reset to Draft, then Confirm. Resetting deletes the COGS lines and confirming rebuilds them from the delivery's cost. If a closing had already moved that cost to Stock Variation, the next closing moves it back. Reset to Draft is not offered on journals that lock posted entries with a hash, lock dates can block it, and Odoo detaches the invoice's stored PDF, so test the cycle on a duplicate database first, especially for paid invoices.

Option 3: rely on the closing. Leave the invoice and post the closing from Accounting > Review > Inventory Valuation with Generate Entry, using an expense account as Stock Variation if the cost should reach profit and loss.

Check that it worked

  1. Open the final or reposted invoice and the Journal Items tab. Two product lines should debit the expense account and credit the Stock Account for the delivered quantity at its FIFO cost.
  2. In the Inventory app, open Reporting > Stock and compare the Total Value sum with the Stock Account balance.
  3. In Enterprise, open Accounting > Review > Inventory Valuation and click Generate Entry. The message "Everything is correctly closed" means the two already agree.

A note on Odoo 20

Odoo 20 reorganizes how COGS lines are built, so the entries above were verified for Odoo 19 only. Check them again on an Odoo 20 database before relying on them there.

Steps verified on Odoo 19. Menus and labels can differ on other versions.

Common questions

What journal entry does Odoo 19 post when a vendor bill is posted before the receipt?

With perpetual valuation, the bill line for a stock-tracked product is booked to the category's Stock Account, against the vendor's payable. The receipt itself posts no entry and is valued from the posted bill.

Why is there no COGS line on a customer invoice in Odoo 19?

COGS is calculated when the invoice is posted. If the goods have not shipped, nothing is on hand and the product's Cost is zero, Odoo skips the COGS lines entirely.

Does Odoo 19 update COGS on an invoice after the delivery is validated?

No. The delivery posts no journal entry and the posted invoice is not revisited. Resetting the invoice to draft and confirming it again rebuilds the COGS lines from the delivery's cost.

Does Odoo 19 still use stock interim accounts?

No. Odoo 19 removed the stock input and output accounts. Differences between stock value and the Stock Account are handled by the stock closing, which posts them against the Stock Variation account.

How do I invoice customers in advance in Odoo without losing COGS?

Use a down payment invoice for the advance. It carries the order's taxes but no product, and the regular invoice issued after delivery posts COGS from the delivered units' cost while deducting the down payment.

Talk to the team.

If you are setting this up, or Odoo is not behaving the way this guide describes, book a 30-minute call. We will look at your configuration and tell you what it needs. Calgary studio, in-house team, no offshore handoffs.

Book the call →