From 4dddc09b3019f9b2ef36fa82e31b76bab79436fb Mon Sep 17 00:00:00 2001 From: Camila Vives Date: Tue, 3 Mar 2026 14:56:48 +0000 Subject: [PATCH] [ADD] account_invoice_move_currency: re-add module X-original-commit: ef35f5a8e6ceac173803d843cb3cec0a897273e8 --- account_invoice_move_currency/README.md | 135 ++++++++++++++++++ account_invoice_move_currency/__init__.py | 2 + account_invoice_move_currency/__manifest__.py | 17 +++ .../models/__init__.py | 1 + .../models/account_move.py | 36 +++++ .../views/account_move_views.xml | 18 +++ .../views/report_invoice.xml | 9 ++ .../wizards/__init__.py | 1 + .../wizards/account_change_currency.py | 30 ++++ .../wizards/account_change_currency_views.xml | 13 ++ 10 files changed, 262 insertions(+) create mode 100644 account_invoice_move_currency/README.md create mode 100644 account_invoice_move_currency/__init__.py create mode 100644 account_invoice_move_currency/__manifest__.py create mode 100644 account_invoice_move_currency/models/__init__.py create mode 100644 account_invoice_move_currency/models/account_move.py create mode 100644 account_invoice_move_currency/views/account_move_views.xml create mode 100644 account_invoice_move_currency/views/report_invoice.xml create mode 100644 account_invoice_move_currency/wizards/__init__.py create mode 100644 account_invoice_move_currency/wizards/account_change_currency.py create mode 100644 account_invoice_move_currency/wizards/account_change_currency_views.xml diff --git a/account_invoice_move_currency/README.md b/account_invoice_move_currency/README.md new file mode 100644 index 00000000..037fa339 --- /dev/null +++ b/account_invoice_move_currency/README.md @@ -0,0 +1,135 @@ +# Account Invoice Move Currency + +This module extends Odoo's accounting functionality to enable dual-currency tracking on invoices. It allows storing invoice values in a secondary currency alongside the primary invoice currency, providing better visibility for businesses operating in multi-currency environments. + +## Features + +- **Secondary Currency Tracking**: Add a secondary currency to invoices to track values in an additional currency +- **Custom Exchange Rates**: Define specific exchange rates for the secondary currency independently from the primary currency +- **Real-time Rate Calculation**: Automatically calculate exchange rates based on company currency and selected secondary currency +- **Currency Change Integration**: Optionally save the original currency as secondary when changing invoice currency +- **Multi-currency Validation**: Prevent conflicts between primary and secondary currencies with built-in validation rules +- **Reporting Support**: Display secondary currency values on invoice reports + +## Configuration + +### Prerequisites + +- Ensure currency rates are configured under Accounting > Configuration > Currencies + +### Installation + +1. Install the module from the Apps menu +2. The module will automatically extend invoice forms with secondary currency fields + +## Usage + +### Adding a Secondary Currency to an Invoice + +1. Navigate to Accounting > Customers > Invoices (or Vendors > Bills) +2. Open a draft invoice +3. In the invoice form, locate the **Secondary Currency** field (visible only with multi-currency enabled) +4. Select a secondary currency from the dropdown +5. The **Account Move Secondary Currency Rate** will be automatically calculated +6. You can manually adjust the rate if needed +7. Save the invoice + +### Important Constraints + +- **Same Currency Restriction**: The secondary currency cannot be the same as the invoice currency +- **Company Currency Requirement**: Secondary currency can only be used when the invoice currency matches the company currency +- If these conditions are not met, the system will display a validation error + +### Changing Invoice Currency + +When using the "Change Currency" wizard: + +1. Open a draft invoice +2. Use the currency change wizard (available from `account_ux` module) +3. Select the new currency +4. Check the **Save in secondary currency?** option if you want to preserve the original currency as the secondary currency +5. When changing to the company currency, this option allows tracking the original currency values +6. Confirm the change + +### Example Use Case + +**Scenario**: A company operates in USD but wants to track invoice values in EUR for reporting purposes. + +1. Create an invoice with currency = USD (company currency) +2. Set Secondary Currency = EUR +3. The system calculates the EUR rate automatically (or enter manually) +4. The invoice values are now tracked in both USD (primary) and EUR (secondary) +5. The secondary currency information is available for reporting and analysis + +## Technical Details + +### Dependencies + +- `account_ux`: Provides extended accounting functionality and the currency change wizard + +### Models Extended + +#### account.move + +**New Fields:** +- `move_currency_id`: Many2one field to store the secondary currency +- `move_inverse_currency_rate`: Float field (16,4 digits) to store the exchange rate + +**Methods:** +- `change_move_currency()`: Onchange method that calculates the exchange rate when secondary currency is selected +- `check_move_currency()`: Constraint method that validates currency selection rules + +#### account.change.currency (TransientModel) + +**New Fields:** +- `save_secondary_currency`: Boolean field to enable saving original currency as secondary +- `same_currency`: Computed field to determine if target currency matches company currency +- `currency_company_id`: Related field for company currency + +**Methods:** +- `_compute_same_currency()`: Computes whether the target currency is the company currency +- `change_currency()`: Extended to handle secondary currency preservation logic + +### Views + +- **Invoice Form View**: Adds secondary currency fields to the invoice header (visible only for invoices/bills in multi-currency setups) +- **Change Currency Wizard**: Adds checkbox to save original currency as secondary +- **Invoice Report**: Shows secondary currency information on printed invoices + +### Security + +No additional security groups or access rights are required beyond standard Odoo accounting permissions. + +## Known Issues / Limitations + +- Secondary currency is only available when the invoice currency is the same as the company currency +- The secondary currency and invoice currency cannot be the same +- Exchange rate modifications are only allowed in draft state + +## Bug Tracker + +Bugs are tracked on [GitHub Issues](https://github.com/ingadhoc/account-invoicing/issues). In case of trouble, please check there if your issue has already been reported. + +## Credits + +### Authors + +* ADHOC SA + +### Contributors + +* ADHOC SA + +### Maintainers + +This module is maintained by ADHOC SA. + +To learn more about ADHOC SA, visit [www.adhoc.com.ar](http://www.adhoc.com.ar). + +## License + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with this program. If not, see . diff --git a/account_invoice_move_currency/__init__.py b/account_invoice_move_currency/__init__.py new file mode 100644 index 00000000..aee8895e --- /dev/null +++ b/account_invoice_move_currency/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/account_invoice_move_currency/__manifest__.py b/account_invoice_move_currency/__manifest__.py new file mode 100644 index 00000000..6783f7da --- /dev/null +++ b/account_invoice_move_currency/__manifest__.py @@ -0,0 +1,17 @@ +{ + "name": "Account Invoice Move Currency", + "version": "19.0.1.0.0", + "author": "ADHOC SA", + "category": "Accounting & Finance", + "depends": ["account_ux"], + "data": [ + "views/account_move_views.xml", + "views/report_invoice.xml", + "wizards/account_change_currency_views.xml", + ], + "website": "www.adhoc.com.ar", + "license": "AGPL-3", + "installable": True, + "auto_install": False, + "application": False, +} diff --git a/account_invoice_move_currency/models/__init__.py b/account_invoice_move_currency/models/__init__.py new file mode 100644 index 00000000..9c0a4213 --- /dev/null +++ b/account_invoice_move_currency/models/__init__.py @@ -0,0 +1 @@ +from . import account_move diff --git a/account_invoice_move_currency/models/account_move.py b/account_invoice_move_currency/models/account_move.py new file mode 100644 index 00000000..dfcffbea --- /dev/null +++ b/account_invoice_move_currency/models/account_move.py @@ -0,0 +1,36 @@ +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class AccountMove(models.Model): + _inherit = "account.move" + + move_currency_id = fields.Many2one( + "res.currency", + "Secondary Currency", + readonly=True, + help="If you set a currency here, then this invoice values will be also stored in the related Account Move Secondary Currency", + ) + + move_inverse_currency_rate = fields.Float( + digits=(16, 4), string="Account Move Secondary Currency Rate", readonly=True + ) + + @api.onchange("move_currency_id") + def change_move_currency(self): + if not self.move_currency_id: + self.move_inverse_currency_rate = False + else: + self.move_inverse_currency_rate = self.move_currency_id._convert( + 1.0, self.company_id.currency_id, self.company_id, self.invoice_date or fields.Date.context_today(self) + ) + + @api.constrains("move_currency_id", "currency_id") + def check_move_currency(self): + for rec in self.filtered("move_currency_id"): + if rec.move_currency_id == rec.currency_id: + raise UserError(_("Secondary currency can not be the same as Invoice Currency")) + if rec.currency_id != rec.company_id.currency_id: + raise UserError( + _("Can not use Secondary currency if invoice is in a Currency different from Company Currency") + ) diff --git a/account_invoice_move_currency/views/account_move_views.xml b/account_invoice_move_currency/views/account_move_views.xml new file mode 100644 index 00000000..ae69f408 --- /dev/null +++ b/account_invoice_move_currency/views/account_move_views.xml @@ -0,0 +1,18 @@ + + + + account.move.view + + account.move + + +
+
+
+
+
diff --git a/account_invoice_move_currency/views/report_invoice.xml b/account_invoice_move_currency/views/report_invoice.xml new file mode 100644 index 00000000..517007d0 --- /dev/null +++ b/account_invoice_move_currency/views/report_invoice.xml @@ -0,0 +1,9 @@ + + + diff --git a/account_invoice_move_currency/wizards/__init__.py b/account_invoice_move_currency/wizards/__init__.py new file mode 100644 index 00000000..ed00f157 --- /dev/null +++ b/account_invoice_move_currency/wizards/__init__.py @@ -0,0 +1 @@ +from . import account_change_currency diff --git a/account_invoice_move_currency/wizards/account_change_currency.py b/account_invoice_move_currency/wizards/account_change_currency.py new file mode 100644 index 00000000..316ee477 --- /dev/null +++ b/account_invoice_move_currency/wizards/account_change_currency.py @@ -0,0 +1,30 @@ +from odoo import api, fields, models + + +class AccountChangeCurrency(models.TransientModel): + _inherit = "account.change.currency" + + save_secondary_currency = fields.Boolean("Save in secondary currency?") + same_currency = fields.Boolean(compute="_compute_same_currency") + currency_company_id = fields.Many2one("res.currency", related="move_id.company_id.currency_id", store=True) + + @api.depends("currency_company_id", "currency_to_id") + def _compute_same_currency(self): + for rec in self: + if rec.currency_company_id == rec.currency_to_id: + rec.same_currency = True + else: + rec.same_currency = False + + def change_currency(self): + # We set it false because if you change the currency to + # the same as the secondary currency they can not be the same + if self.move_id.move_currency_id == self.currency_to_id: + self.move_id.move_currency_id = False + self.move_id.move_inverse_currency_rate = False + currency_from_id = self.currency_from_id + res = super().change_currency() + if self.save_secondary_currency and self.same_currency: + self.move_id.move_currency_id = currency_from_id.id + self.move_id.move_inverse_currency_rate = self.conversion_rate + return res diff --git a/account_invoice_move_currency/wizards/account_change_currency_views.xml b/account_invoice_move_currency/wizards/account_change_currency_views.xml new file mode 100644 index 00000000..f5617cce --- /dev/null +++ b/account_invoice_move_currency/wizards/account_change_currency_views.xml @@ -0,0 +1,13 @@ + + + + Change Currency inherit + account.change.currency + + + + + + + +