GuideMarch 13, 2026

Timesheet Billing in Odoo 19:
Track Hours, Automate Invoicing & Boost Profitability

INTRODUCTION

You Delivered 200 Hours Last Month. You Billed for 140.

Every professional services firm has the same leak: hours worked but never invoiced. A developer logs time against a project but forgets to assign the right task. A consultant tracks hours in a spreadsheet that never syncs with accounting. A project manager approves timesheets on Friday but the invoice doesn't go out until someone manually creates it the following Wednesday. By then, three line items are missing because they were logged under the wrong project.

The gap between "hours delivered" and "hours billed" is pure revenue loss. For a 50-person consultancy billing at $150/hour, a 15% leakage rate means $2.7 million in annual unbilled work. The problem isn't that people forget to bill — it's that the path from timesheet entry to invoice line requires too many manual steps, each one an opportunity for data to fall through the cracks.

Odoo 19's Timesheet module closes this gap by creating a direct pipeline from time entry to invoice line. When configured correctly, an employee logs time on a project task, a manager approves the timesheet, and Odoo automatically generates the invoice with the correct billing rate, service description, and quantity. No spreadsheets, no copy-paste, no missing hours. This guide walks through the complete setup — from service product configuration through automated invoicing and profitability analysis.

01

Configuring Service Products for Timesheet Billing in Odoo 19

Everything starts with the service product. In Odoo 19, a service product with the invoicing policy set to "Based on Timesheets" tells the system: "don't invoice a fixed quantity — invoice whatever hours are logged against this sale order line." This is the foundation of time-and-materials billing.

Step 1: Create the Service Product

Navigate to Sales → Products → Products and create a new product. The critical fields:

Product Configuration — Service with Timesheet Billing
Product Name:       Senior Developer — Consulting
Product Type:       Service
Invoicing Policy:   Based on Timesheets
                    (Sales → General Information → Invoicing Policy)

Service Tracking:   Task in Existing Project
                    ── OR ──
                    Project & Task (creates both automatically)

Sales Price:        $175.00 / hour
Unit of Measure:    Hours
Cost:               $85.00 / hour   (internal cost for profitability)

# The "Service Tracking" field controls what happens when
# this product is added to a Sale Order:
#
# "Task in Existing Project"
#   → Creates a task in a project you select on the SO line
#   → Best for: ongoing retainers, T&M contracts
#
# "Project & Task"
#   → Creates a NEW project + task per SO
#   → Best for: one-off engagements, fixed-scope projects
#
# "Task in Sales Order's Project"
#   → Groups all SO lines into one auto-created project
#   → Best for: multi-service proposals (dev + QA + PM)

Step 2: Set Up Multiple Service Tiers

Most firms bill different rates for different roles. Create one service product per billing tier:

Service ProductSale PriceInternal CostMarginService Tracking
Junior Developer$100/hr$45/hr55%Task in Existing Project
Senior Developer$175/hr$85/hr51%Task in Existing Project
Technical Architect$225/hr$120/hr47%Task in Existing Project
Project Manager$150/hr$75/hr50%Task in Existing Project
Why Internal Cost Matters

The Cost field on the service product is what Odoo uses to calculate project profitability. Set it to the fully loaded cost of that role — salary, benefits, overhead. If you leave it at zero, the profitability report will show 100% margin on every project, which is useless for decision-making.

02

Setting Up Projects and Tasks for Timesheet Tracking in Odoo 19

With service products configured, the next step is connecting projects, tasks, and sale order lines so that every timesheet entry knows which invoice line it belongs to.

Step 1: Enable Timesheets on the Project

Navigate to Project → Configuration → Settings and ensure Timesheets is enabled. Then open your project and verify:

Project Settings — Timesheet Configuration
Project:            Acme Corp — ERP Implementation
Allow Timesheets:   [x] Enabled
                    (Project → Settings tab)

Timesheet Timer:    [x] Enabled
                    (allows start/stop timer on tasks)

Bill from:          Sale Order Item
                    → Each timesheet line bills to the SO line
                       that created its task

# ── Key Relationship Chain ──
#
# Sale Order Line (product: "Senior Developer")
#   └── creates Task ("Backend Development")
#         └── Employee logs Timesheet (2.5 hours)
#               └── Timesheet auto-links to SO Line
#                     └── Invoice pulls hours from SO Line
#
# This chain is AUTOMATIC when Service Tracking
# is set correctly on the product.

Step 2: Create the Sale Order

Create a sale order for the client. Add one line per service tier. When you confirm the order, Odoo automatically creates the linked tasks:

Sale Order — Acme Corp ERP Implementation
# Sale Order: S00042
# Customer: Acme Corp
# ─────────────────────────────────────────────────
# Line | Product              | Qty | Unit Price | Subtotal
# ─────────────────────────────────────────────────
#  1   | Senior Developer     | 160 |   $175.00  | $28,000.00
#  2   | Technical Architect  |  40 |   $225.00  |  $9,000.00
#  3   | Project Manager      |  80 |   $150.00  | $12,000.00
# ─────────────────────────────────────────────────
# Total (estimated):                   $49,000.00
#
# NOTE: The "Qty" here is the ESTIMATED hours.
# With "Based on Timesheets" invoicing policy,
# Odoo invoices ACTUAL hours logged — not this estimate.
# The estimate appears on the quote for client approval.
#
# After confirming this SO:
# → Task "Senior Developer" created in Acme Corp project
# → Task "Technical Architect" created in Acme Corp project
# → Task "Project Manager" created in Acme Corp project

Step 3: Log Timesheets Against Tasks

Employees log time directly on tasks via Project → Tasks → [Task] → Timesheets tab, or through the dedicated Timesheets app which provides a weekly grid view.

Timesheet Entry — Weekly Grid View
# Timesheets → My Timesheets (Grid View)
# Employee: Jane Smith (Senior Developer)
# Week of March 9, 2026
# ──────────────────────────────────────────────────────
# Project / Task          | Mon | Tue | Wed | Thu | Fri | Total
# ──────────────────────────────────────────────────────
# Acme / Backend Dev      | 6.0 | 7.5 | 8.0 | 5.5 | 4.0 | 31.0
# Acme / Code Review      | 1.0 | 0.5 |  -  | 1.5 | 1.0 |  4.0
# Internal / Team Meeting | 1.0 |  -  |  -  | 1.0 |  -  |  2.0
# ──────────────────────────────────────────────────────
# Weekly Total:                                         | 37.0
#
# Only "Acme" tasks are billable — they link to SO lines.
# "Internal / Team Meeting" has no SO link → non-billable.
#
# The timer feature:
# → Click "Start" on a task to begin tracking
# → Click "Stop" to log the elapsed time
# → Odoo rounds to the nearest encoding UoM increment
Timer Rounding Configuration

By default, the timesheet timer logs time to the exact minute. For billing purposes, most firms round to 15-minute increments. Configure this under Timesheets → Configuration → Settings → Minimum Duration. Set it to 15 minutes. Odoo will round up any entry shorter than 15 minutes to 0.25 hours. This prevents 2-minute entries from cluttering your invoices.

03

Configuring Employee Billing Rates and Rate Overrides in Odoo 19

Not every hour is billed at the same rate. Odoo 19 supports three layers of billing rate logic, each overriding the previous one. Understanding this hierarchy is critical for accurate invoicing.

PriorityRate SourceWhere It's SetUse Case
1 (Lowest)Service Product PriceProduct form → Sales PriceDefault rate for all employees on this service
2Pricelist RuleSales → PricelistsClient-specific negotiated rates
3 (Highest)Sale Order Line OverrideSO line → Unit PriceOne-off rate adjustments per engagement

Client-Specific Rates via Pricelists

For clients with negotiated rates, create a pricelist that adjusts the billing rate per service product:

Pricelist Configuration — Acme Corp Discounted Rates
# Sales → Configuration → Pricelists → Create
#
# Pricelist:  Acme Corp — Contract Rates
# Currency:   USD
#
# ── Price Rules ──────────────────────────────────────
# Apply On         | Computation     | Value
# ─────────────────────────────────────────────────────
# Senior Developer | Discount        | 10%   → $157.50/hr
# Tech Architect   | Fixed Price     | $200  → $200.00/hr
# Project Manager  | Discount        | 5%    → $142.50/hr
#
# Assign to customer:
# Contacts → Acme Corp → Sales & Purchases tab
#   → Pricelist: "Acme Corp — Contract Rates"
#
# Now every SO for Acme Corp auto-applies these rates.
# The SO line shows the discounted price by default.
# Salespeople can still override on the line if needed.

Employee Cost Rates for Profitability

The billing rate goes on the invoice. The cost rate is what Odoo uses to calculate margin. Set employee-specific costs under Timesheets → Configuration → Settings → Employee Costs:

Employee Timesheet Cost Configuration
# HR → Employees → Jane Smith → Settings tab
#
# Timesheet Cost:  $90.00 / hour
#
# This overrides the product's "Cost" field for this
# specific employee. Useful when:
# → Senior devs on the same "Senior Developer" product
#    have different salaries
# → Contractors vs. employees have different loaded costs
#
# Cost hierarchy (highest priority wins):
# 1. Employee-level Timesheet Cost
# 2. Product-level Cost field
# 3. Zero (if nothing is set — margin = 100%, which is wrong)
#
# ── Historical Cost Rates ──
# Odoo 19 supports date-based cost rates:
# From        | Cost
# 2026-01-01  | $85.00/hr
# 2026-07-01  | $92.00/hr   (after raise)
#
# Timesheets logged before July use $85;
# timesheets logged after use $92.
# Profitability reports reflect the correct cost per period.
04

Timesheet Approval Workflows: Manager Review Before Invoicing

Invoicing unapproved timesheets is a recipe for client disputes. Odoo 19 provides a built-in approval workflow that gates timesheet entries before they become billable. Enable it under Timesheets → Configuration → Settings → Timesheet Approval.

Timesheet Approval — Configuration and Workflow
# ── Enable Approval ──
# Timesheets → Configuration → Settings
#   [x] Timesheet Approval
#   Approval: By Manager
#
# ── Approval Workflow States ──
#
#   Draft  →  Submitted  →  Approved  →  Invoiced
#     |           |              |             |
#  Employee    Employee       Manager       System
#  logs time   clicks        reviews &     (auto on
#              "Submit"      approves      invoice
#                                          creation)
#
# ── What Each State Means for Billing ──
#
# Draft:     Editable by employee. NOT billable.
# Submitted: Locked for employee. Visible to manager.
# Approved:  Locked for everyone. Ready for invoicing.
#            Only approved timesheets appear in the
#            "Create Invoice" wizard.
# Invoiced:  Linked to an invoice line. Fully locked.
#
# ── Manager Approval View ──
# Timesheets → Managers → Timesheets to Approve
# → Filter by employee, project, date range
# → Bulk approve with "Approve" action
# → Reject with note (sends back to Draft)
Approval Deadline Automation

Set up a scheduled action (Settings → Technical → Automation → Scheduled Actions) that sends reminder emails to managers every Monday for any timesheets submitted but not yet approved from the previous week. Without this nudge, approval backlogs build up and invoicing gets delayed by weeks. The scheduled action filters account.analytic.line records where validated = False and date <= last_friday.

Locking Timesheets by Period

To prevent retroactive edits after invoicing, configure the timesheet lock date:

Timesheet Lock Date — Prevent Retroactive Edits
# Timesheets → Configuration → Settings
#
# Lock Timesheets:  [x] Enabled
# Lock Date:        End of previous month (auto-rolling)
#
# Effect:
# → Employees cannot add/edit timesheets before the lock date
# → Managers cannot approve timesheets before the lock date
# → Only users with "Timesheets Administrator" role can
#    override the lock
#
# Example (today is March 13, 2026):
# Lock date = February 28, 2026
# → No one can log time for January or February
# → March timesheets are open for editing
#
# Best practice: Set the lock date AFTER invoicing the period.
# Workflow:
# 1. March 1: Lock February timesheets
# 2. March 3: Manager approves all February timesheets
# 3. March 5: Accountant creates February invoices
# 4. March 5: Lock date auto-advances to Feb 28
05

Automating Invoice Creation from Approved Timesheets in Odoo 19

This is where the entire pipeline pays off. Approved timesheets are linked to sale order lines. Odoo calculates the billable quantity by summing approved hours per SO line, then generates invoice lines with the correct rate, description, and quantity.

Method 1: Manual Invoice Creation (Per Sale Order)

Creating an Invoice from a Sale Order with Timesheets
# Sales → Orders → S00042 (Acme Corp ERP Implementation)
# Click "Create Invoice" button
#
# ── Invoice Creation Wizard ──
#
# Create Invoice:  [x] Timesheets (Approved)
#                  → Only invoices approved timesheet hours
#
# Invoice Period:  March 1, 2026 – March 31, 2026
#                  → Filters timesheets by date range
#
# ── Preview: What will be invoiced ──
#
# SO Line              | Ordered | Delivered | Invoiced | To Invoice
# ─────────────────────────────────────────────────────────────────
# Senior Developer     |  160 hr |   62.5 hr |    0 hr  |  62.5 hr
# Technical Architect  |   40 hr |   12.0 hr |    0 hr  |  12.0 hr
# Project Manager      |   80 hr |   22.0 hr |    0 hr  |  22.0 hr
#
# "Delivered" = sum of APPROVED timesheet hours for the period.
# "To Invoice" = Delivered − Already Invoiced.
#
# ── Resulting Invoice ──
#
# INV/2026/0089 — Acme Corp
# Line | Description          | Qty    | Price   | Subtotal
# ────────────────────────────────────────────────────────
#  1   | Senior Developer     | 62.50  | $175.00 | $10,937.50
#  2   | Technical Architect  | 12.00  | $225.00 |  $2,700.00
#  3   | Project Manager      | 22.00  | $150.00 |  $3,300.00
# ────────────────────────────────────────────────────────
# Total:                                          $16,937.50

Method 2: Batch Invoicing (All Clients at Once)

For firms with many active projects, creating invoices one-by-one is tedious. Use the batch invoicing flow:

Batch Invoice Creation — All Timesheet-Based Orders
# Sales → To Invoice → Orders to Invoice
#
# This view shows ALL sale orders with uninvoiced
# delivered quantities (including timesheet hours).
#
# Filter: "Invoicing Policy = Timesheets"
# Group by: Customer
#
# Select all → Action → Create Invoices
#
# ── Batch Wizard Options ──
#
# Create Invoice:     [x] Timesheets (Approved)
# Invoicing Date:     2026-03-31
# Group by Partner:   [x]  (one invoice per customer,
#                           even if they have multiple SOs)
#
# Result:
# → 12 invoices created for 12 clients
# → Each invoice has one line per SO line with hours
# → All linked to the correct journal and payment terms
#
# Pro tip: Schedule this as a monthly cron job via
# Settings → Technical → Scheduled Actions:
#
# Model:    sale.advance.payment.inv
# Method:   create_invoices
# Interval: 1 month
# Execute:  First business day of each month

Method 3: Milestone + Timesheet Hybrid

Some contracts bill a fixed fee for milestones plus T&M for additional work. Odoo 19 handles this with mixed invoicing policies on the same sale order:

Mixed Billing — Fixed Milestones + Timesheet Overflow
# Sale Order: S00043 — Acme Corp Phase 2
#
# Line | Product             | Policy       | Qty  | Price
# ──────────────────────────────────────────────────────────
#  1   | Discovery Phase     | Milestones   |  1   | $8,000
#  2   | Development Phase   | Milestones   |  1   | $25,000
#  3   | Additional Dev Work | Timesheets   | 40   | $175/hr
#  4   | Project Management  | Timesheets   | 20   | $150/hr
#
# Lines 1-2: Invoice when milestone is marked "Reached"
#            on the linked project task.
# Lines 3-4: Invoice actual hours logged.
#
# This gives the client budget predictability on the core
# scope while allowing flexible billing for change requests.
Invoice Description Detail Level

By default, the invoice line shows the product name and the total hours. Clients often want to see daily or task-level breakdowns. Enable this under Timesheets → Configuration → Settings → Invoice Details. Set it to "Group by Task" or "Group by Timesheet Entry" to append a detailed breakdown below each invoice line. This prevents "what did we pay for?" calls from clients.

06

Project Profitability Analysis: Tracking Margins in Real Time

Billing hours is only half the story. The real question is: are you making money on this project? Odoo 19's profitability analysis compares revenue (invoiced amounts) against costs (employee timesheet costs, expenses, and purchases) at the project level.

Accessing the Profitability Report

Project Profitability — Dashboard Overview
# Project → Acme Corp ERP Implementation → Profitability button
#
# ── Profitability Summary ──────────────────────────────
#
# Revenue
#   Timesheet Invoiced:          $16,937.50
#   Milestone Invoiced:                $0.00
#   Other Revenue:                     $0.00
#   Total Revenue:               $16,937.50
#
# Costs
#   Timesheet Costs:             ($8,127.50)
#     → Jane Smith:    62.5 hr x $90.00 = ($5,625.00)
#     → Mark Lee:      12.0 hr x $110.00 = ($1,320.00)
#     → Sarah Chen:    22.0 hr x $80.00 = ($1,760.00)
#     → Unassigned:    0 hr              = $0.00
#   Expense Costs:                     $0.00
#   Purchase Costs:                    $0.00
#   Total Costs:                 ($8,127.50)
#
# ── Margin ─────────────────────────────────────────────
#   Profit:                       $8,810.00
#   Margin:                           52.0%
#
# ── Budget Tracking ───────────────────────────────────
#   Estimated Revenue:           $49,000.00
#   Invoiced to Date:            $16,937.50  (34.6%)
#   Remaining Budget:            $32,062.50
#   Hours Consumed:              96.5 / 280  (34.5%)
#
# The consumed percentage (34.5%) roughly matches the
# invoiced percentage (34.6%). Project is on track.

Key Profitability Metrics to Monitor

MetricFormulaHealthy RangeRed Flag
Gross Margin(Revenue - Timesheet Costs) / Revenue45%–65%< 30% — underbilling or overstaffing
Budget Burn RateHours Consumed / Estimated HoursShould match % completion> 80% consumed, < 50% complete
Billable RatioBillable Hours / Total Hours Logged75%–85%< 60% — too much non-billable work
Realization RateInvoiced Hours / Available Hours70%–80%< 55% — scope creep or poor tracking

Analytic Accounts for Cross-Project Reporting

For multi-project profitability views, Odoo 19's analytic accounting lets you tag timesheets, expenses, and invoices with analytic plans. Navigate to Accounting → Configuration → Analytic Plans to set up dimensions like Department, Client, or Service Line. The resulting pivot reports let you answer questions like "What's the margin on all Senior Developer hours across all clients this quarter?"

07

4 Timesheet Billing Mistakes That Cost Consultancies Real Revenue

1

Timesheets Logged Against Tasks Not Linked to a Sale Order

An employee creates a new task manually (instead of letting the SO create it) and logs 20 hours against it. The timesheet exists, the hours are real, but there's no SO line to bill against. These hours never appear in the "Create Invoice" wizard. They're invisible to the billing team. We've seen firms discover $50,000+ in unbilled hours during audits because tasks were created outside the SO workflow.

Our Fix

Set a record rule that restricts task creation to managers only on billable projects. All billable tasks should be auto-created from SO lines. Add a scheduled action that reports weekly on any timesheet entries where so_line = False on billable projects — these are your revenue leaks.

2

Invoicing Before Timesheet Approval (Billing Disputed Hours)

Without the approval workflow enabled, all timesheet entries are immediately billable — including the 8-hour entry someone accidentally logged on the wrong project, or the 3 hours a junior developer spent on work that was already done. The invoice goes out, the client disputes it, and the credit note process begins. Each dispute costs 30+ minutes of back-and-forth and damages client trust.

Our Fix

Always enable timesheet approval. Always set the "Create Invoice" wizard to filter on approved timesheets only. Train managers to review timesheets weekly, not monthly. A Friday afternoon 10-minute review prevents a Tuesday morning 2-hour client dispute.

3

Zero-Cost Employees Inflate Profitability Reports

If you don't set the Timesheet Cost on employees or the Cost on service products, Odoo calculates project cost as $0. Your profitability report shows 100% margin on every project. Management makes staffing decisions based on fictional margins. The firm bills $500,000/year with a "100% margin" but actually operates at 15% because nobody accounted for the $425,000 in loaded labor costs.

Our Fix

Make timesheet cost setup part of the employee onboarding checklist. Use a server action that flags any timesheet entry where the associated employee has a cost of $0 — send an alert to HR to update the employee record. Quarterly, run a profitability report filtered by "cost = 0" to catch any gaps.

4

Forgetting to Handle Hours That Exceed the SO Estimate

You estimated 160 hours on the SO line, but the developer logged 185 hours. Odoo will happily invoice all 185 hours — it doesn't cap at the estimate. The client gets an invoice for 25 hours more than they agreed to. If you catch it before sending, you write off the overage. If the client catches it, you have an uncomfortable conversation about scope.

Our Fix

Enable SO line budget alerts. Odoo 19 shows a progress bar on the SO line comparing delivered vs. ordered quantity. Set up an automated action on sale.order.line that sends an email when delivered hours reach 80% of the estimate. This gives project managers time to request a change order or reallocate hours before overage occurs.

BUSINESS ROI

What Automated Timesheet Billing Saves Your Firm

The ROI of timesheet billing automation isn't theoretical — it's measurable in the first billing cycle:

15%Revenue Recovery

Firms consistently find 10-20% of billable hours were going uninvoiced due to manual processes. Automated SO-to-invoice linking eliminates the most common leakage points.

4 hrsSaved Per Billing Cycle

No more cross-referencing spreadsheets with projects. Batch invoicing turns a full-day process into a 30-minute review-and-click workflow.

60%Fewer Invoice Disputes

Manager-approved timesheets with task-level detail on invoices eliminate the "what were these hours for?" question that triggers 80% of billing disputes.

For a 30-person consultancy billing $3M annually, recovering 15% of leaked hours adds $450,000 to the top line — without hiring a single new person. The profitability dashboard then tells you which clients, services, and employees contribute most to margin, enabling data-driven decisions about where to invest and which engagements to renegotiate.

SEO NOTES

Optimization Metadata

Meta Desc

Complete guide to Odoo 19 timesheet billing. Configure service products, set billing rates, enable approval workflows, automate invoice creation, and track project profitability.

H2 Keywords

1. "Configuring Service Products for Timesheet Billing in Odoo 19"
2. "Automating Invoice Creation from Approved Timesheets in Odoo 19"
3. "4 Timesheet Billing Mistakes That Cost Consultancies Real Revenue"

Stop Leaving Revenue on the Timesheet

Every hour your team works but doesn't bill is money left on the table. Every invoice sent without manager approval is a dispute waiting to happen. Every project without cost tracking is a profitability black box. Odoo 19's timesheet billing pipeline — from time entry through approval to automated invoicing — closes all three gaps in a single, integrated workflow.

If you're running a services business on Odoo and your billing process still involves spreadsheets or manual invoice creation, we can help. We configure the full timesheet-to-invoice pipeline, set up approval workflows, build profitability dashboards, and train your team on the weekly billing rhythm. Most implementations take less than two weeks.

Book a Free Billing Workflow Assessment