| __pycache__ | ||
| models | ||
| tests | ||
| views | ||
| __init__.py | ||
| __manifest__.py | ||
| CHANGELOG.md | ||
| README.md | ||
Vendor Bill Editable Totals
Overview
This Odoo 17 module enables accountants to directly edit the tax excluded (price_subtotal) and tax included (price_total) amounts on vendor bill invoice lines. When these fields are modified, the system automatically recalculates the unit price (price_unit) to maintain exact decimal accuracy with the user-inputted amounts.
This is particularly useful when entering vendor bills where the supplier invoice shows total amounts that don't divide evenly, or when you need to match exact amounts without manually calculating unit prices.
Features
- ✅ Direct editing of tax excluded amounts - Modify
price_subtotaldirectly on vendor bill lines - ✅ Direct editing of tax included amounts - Modify
price_totaldirectly on vendor bill lines - ✅ Automatic unit price recalculation - System calculates
price_unitto match your entered totals - ✅ Decimal precision accuracy - Maintains exact amounts within configured decimal precision
- ✅ Multiple tax support - Correctly handles lines with multiple taxes
- ✅ Credit note support - Works with negative values for credit notes and adjustments
- ✅ Edge case handling - Graceful handling of zero quantities, no taxes, and other edge cases
- ✅ Seamless integration - Works with standard Odoo vendor bill workflows
Installation
- Copy the
vendor_bill_editable_totalsfolder to your Odooaddonsdirectory - Update the apps list: Go to Apps → Click Update Apps List
- Search for "Vendor Bill Editable Totals"
- Click Install
Configuration
No configuration is required. The module works out of the box after installation.
The module respects Odoo's existing decimal precision settings:
- Navigate to Settings → Technical → Database Structure → Decimal Accuracy
- The "Product Price" precision setting controls the rounding of calculated unit prices
Usage
Editing Tax Excluded Amount (price_subtotal)
- Navigate to Accounting → Vendors → Bills
- Create a new vendor bill or open an existing draft bill
- Add or select an invoice line
- Click on the Subtotal field (price_subtotal) in the invoice line
- Enter the desired tax excluded amount
- Press Enter or click outside the field
- The Unit Price will automatically recalculate to match your entered amount
Example:
Quantity: 3
You enter Subtotal: 100.00
System calculates Unit Price: 33.33
Recomputed Subtotal: 99.99 (or 100.00 depending on precision)
Editing Tax Included Amount (price_total)
- Navigate to Accounting → Vendors → Bills
- Create a new vendor bill or open an existing draft bill
- Add or select an invoice line with taxes configured
- Click on the Total field (price_total) in the invoice line
- Enter the desired tax included amount
- Press Enter or click outside the field
- The Unit Price will automatically recalculate, accounting for taxes
Example:
Quantity: 5
Tax: 10%
You enter Total: 550.00
System calculates:
- Subtotal: 500.00 (550.00 / 1.10)
- Unit Price: 100.00 (500.00 / 5)
Recomputed Total: 550.00
Use Cases
Use Case 1: Matching Supplier Invoice Totals
Scenario: Your supplier invoice shows a line total of €127.50 for 7 items, but the unit price doesn't divide evenly.
Solution:
- Create vendor bill line with quantity: 7
- Click on the Subtotal field
- Enter: 127.50
- System calculates unit price: 18.21 (rounded)
- The line total will match the supplier invoice exactly
Use Case 2: Entering Tax-Included Amounts
Scenario: Your supplier invoice shows a total of $1,234.56 including 15% tax for 10 items.
Solution:
- Create vendor bill line with quantity: 10 and 15% tax
- Click on the Total field
- Enter: 1234.56
- System calculates:
- Subtotal: 1073.53
- Unit price: 107.35
- The line total including tax will match exactly
Use Case 3: Credit Notes
Scenario: You need to create a credit note for a returned item worth -€50.00.
Solution:
- Create vendor credit note (refund)
- Add line with quantity: 1
- Click on the Subtotal field
- Enter: -50.00
- System calculates unit price: -50.00
- Negative values are handled correctly
Technical Details
How It Works
The module extends the account.move.line model with two @api.onchange methods:
-
_onchange_price_subtotal()- Triggered when price_subtotal is modified- Validates quantity is not zero
- Calculates:
price_unit = price_subtotal / quantity - Applies decimal precision rounding
-
_onchange_price_total()- Triggered when price_total is modified- Validates quantity is not zero
- Calculates tax factor from configured taxes
- Derives:
price_subtotal = price_total / (1 + tax_rate) - Calculates:
price_unit = price_subtotal / quantity - Applies decimal precision rounding
View Modifications
The module inherits the vendor bill form view (account.view_move_form) and makes the following changes:
- Sets
readonly="0"forprice_subtotalfield - Sets
readonly="0"forprice_totalfield - Adds conditional readonly based on:
- Document state (only editable in 'draft' state)
- Document type (only editable for vendor bills and refunds)
Supported Document Types
The editable fields are available for:
- Vendor Bills (
move_type='in_invoice') - Vendor Credit Notes (
move_type='in_refund')
The fields remain readonly for:
- Customer Invoices
- Customer Credit Notes
- Journal Entries
- Posted documents (state != 'draft')
Limitations
- Fields are only editable in draft state (standard Odoo behavior)
- Only works for vendor bills and vendor credit notes
- Requires quantity to be set before editing totals (to avoid division by zero)
- Minor rounding differences may occur due to decimal precision limits
Error Handling
Division by Zero
If you attempt to edit price_subtotal or price_total when quantity is zero, you'll see an error:
Cannot calculate unit price: quantity must be greater than zero
Solution: Set the quantity to a non-zero value before editing the total fields.
Precision Rounding
Due to decimal precision limits, there may be minor differences (typically < 0.01) between your entered amount and the recomputed amount. This is normal and expected behavior.
Example:
You enter: 100.00
Quantity: 3
Calculated unit price: 33.333333...
Rounded unit price: 33.33 (2 decimal places)
Recomputed subtotal: 99.99
Testing
The module includes comprehensive test coverage:
Property-Based Tests
- Price subtotal calculation accuracy
- Quantity preservation during modifications
- Round-trip accuracy for price_subtotal
- Round-trip accuracy for price_total with taxes
- Decimal precision compliance
Unit Tests
- Zero quantity error handling
- Negative values (credit notes)
- No taxes scenario
- Single tax calculation
- Multiple taxes calculation
- View configuration
Integration Tests
- Full workflow: create → modify → save → verify
- Compatibility with standard Odoo validations
To run tests:
# Run all property tests
python customaddons/vendor_bill_editable_totals/tests/run_property_test.py
python customaddons/vendor_bill_editable_totals/tests/run_price_total_test.py
python customaddons/vendor_bill_editable_totals/tests/run_decimal_precision_test.py
# Run unit tests
python customaddons/vendor_bill_editable_totals/tests/run_edge_case_tests.py
python customaddons/vendor_bill_editable_totals/tests/run_view_tests.py
# Run integration tests
python customaddons/vendor_bill_editable_totals/tests/run_integration_tests.py
Compatibility
- Odoo Version: 17.0
- Python Version: 3.10+
- Database: PostgreSQL 12+
- License: LGPL-3
Dependencies
account- Odoo core accounting module
Support
For issues, questions, or contributions, please contact your system administrator or the module maintainer.
Changelog
Version 17.0.1.0.0
- Initial release
- Direct editing of price_subtotal on vendor bill lines
- Direct editing of price_total on vendor bill lines
- Automatic unit price recalculation
- Support for multiple taxes
- Support for credit notes
- Comprehensive test coverage
Credits
Author: Your Company
Contributors:
- Development Team
License
This module is licensed under LGPL-3.
Note: This module follows Odoo development best practices and is designed to integrate seamlessly with existing Odoo workflows. It does not modify core Odoo functionality and can be safely installed and uninstalled without affecting other modules.