Daily updates from Odoo
Friday, June 26, 2026
206 changes
20 changes
Resolved issues and error corrections
This update prevents the salary configurator from crashing when the company car option is enabled without a car model already selected. It improves reliability for Belgian contract salary setups, especially in databases created without demo data.
Original PR description
## Steps to Reproduce: 1. Install `l10n_be_hr_contract_salary` without demo data. 2. Create a Belgian company and switch to it. 3. Create an employee. 4. Create a contract for the employee. 5. Click Generate Offer and open the Salary Configurator. 6. Enable the 'Company Car (To order)' option. ## Error: `AttributeError: 'NoneType' object has no attribute 'split'` ## Cause: When the salary configurator is used without demo data, no car model is selected. The method assumes that select_wishlist_car_total_depreciated_cost always contains a value and directly calls split() on it, resulting in an error, when the field is None. ## Fix: This commit checks that both the company car option is enabled and a car model has been selected before trying to extract the model ID. sentry-7554712017 Forward-Port-Of: odoo/enterprise#121650 Forward-Port-Of: odoo/enterprise#121138
This change fixes an unstable point-of-sale test that could sometimes look in the wrong order list before an update had fully finished. It improves reliability by making the test wait for the update to complete and by using the correct Paid filter on the ticket screen.
Original PR description
The tour `test_product_level_discount` was failing intermittently because the order status update request was not fully processed before the nextstep executed. As a result, the tour searched for the order in the wrong ticket list. This commit adds a proper wait for the backend request after updating the order status and applies the Paid filter on the ticket screen to ensure the tour searches in the correct order list. Runbot Error: [241140](https://runbot.odoo.com/odoo/runbot.build.error/241140) Forward-Port-Of: odoo/enterprise#109371
This update corrects a Belgian VAT number used in an automated test so it matches the current validation rules. It keeps the test scenario intact while preventing failures caused by stricter third-party validation checks in newer systems.
Original PR description
This commit fixes a Belgian VAT validation check in `test_import_partner_retrieval_bank_account_number` as the provided vat number isn't a valid one. It keeps the spirit of the test by still having vat number mismatch, but with a valid value. The python-stdnum library used for this validation added a stricter check since version 2.2, which is used in Ubuntu Resolute 26.04. References: - https://github.com/arthurdejong/python-stdnum/commit/7ca9b6ce7b1f2b4d1bf164c2af83a8a77bc919d2 runbot-939796 Forward-Port-Of: odoo/odoo#272082
This change prevents the system from creating duplicate draft entries when the scheduled import runs for Belgian SODA files. It restores the previous behavior to avoid repeated imports and reduce confusion in accounting records.
Original PR description
Since this commit: https://github.com/odoo/enterprise/commit/a0c9e9b5c0ed8135d77c343c819c1fa918356794 users are experiencing some duplicate draft move when the cron is running. It's because we don't skip the files when it already exist, we now add a number of imported count. This commit will revert this change to avoid the problem, and we will contact codabox to find a better way to deal with files imported the same month. task-6299508 Forward-Port-Of: odoo/enterprise#121472
The search dialog in bank reconciliation now shows the full reference text instead of cutting it off. The date and balance are also aligned more clearly at the top, making the list easier to scan and compare.
Original PR description
This commit will remove the text-truncate from the reference so that we have it full. Also removing the align item so that the date and balance are on top. no task id Forward-Port-Of: odoo/enterprise#120963
This fix prevents module upgrades from failing for older databases that use the Italian tax reporting package. It removes outdated report entries before the upgrade so the new report formulas can be installed cleanly.
Original PR description
Steps to reproduce: - Create a database with `l10n_it_reports` on a version before PR #264294 - Switch to current `17.0` - Upgrade module `l10n_it` - An error is raised Upgrading a database with `l10n_it_reports` installed raises an error if the database was created before that PR In that PR, we modified the formulas of several report expressions to use subformulas instead of simple aggregations. During upgrade, the ORM attempts to insert the updated expressions while the old ones still exist, violating the UNIQUE constraint on `(report_line_id, label)` in `account.report.expression` Only happens on upgrade, not on a fresh install. A migration script is added to delete the outdated expressions before the upgrade runs Ticket [link](https://www.odoo.com/odoo/project.task/6299385) opw-6299385 Forward-Port-Of: odoo/odoo#271320
This change stops the Point of Sale ticket screen from refunding lines that are already refunds or have been fully refunded. It helps avoid accidental duplicate refunds and keeps refund records accurate.
Original PR description
In the ticket screen, clicking an order line selected it for refund and incremented its quantity without checking whether the line could actually be refunded. As a result, a refund order (whose lines carry a negative quantity) could itself be refunded, and already fully refunded lines could be refunded again. opw-6314527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271109
The Spanish Mod 349 report now keeps invoices that were paid during the selected period. This fixes an issue where paid invoices could be incorrectly left out of the report, helping ensure the filing is complete and accurate.
Original PR description
The mod349 report engine has been refactored to use tax tags (commit : 5f36778288a1b60245acec74677421666448351f). To avoid redundancies, the query used to get the invoice lines to include is designed to remove the amounts that have been reconciled with a credit note during the selected period. However, the current query removes the lines from any invoice that is reconciled with a move created in the period. As a result, invoices that have been paid in the period are also removed from the report. opw-6250491 Forward-Port-Of: odoo/enterprise#119551
When two restaurant orders are merged into one table, previously sent kitchen quantities are now preserved correctly. This prevents already-prepared items from being shown as new and sent to the kitchen again, avoiding duplicate work and confusion.
Original PR description
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was…
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was incorrectly marked as new and had to be sent again. Steps to reproduce: ------------------- * Open table 1, add product A (2 units) and product B, send to kitchen * Open table 2, add product A (3 units) and product C, send to kitchen * On table 2, transfer/merge the order to table 1 > Observation: product A shows 2 units as new and must be sent to the kitchen printer again, although all quantities were already sent. Why the fix: ------------ When merging preparation history for identical lines, handlePreparationHistory overwrote the destination sent quantity with the source one instead of summing both. The kitchen diff then treated the missing quantity as new changes. A unit test will be added in 18.3. opw-6246470 Forward-Port-Of: odoo/odoo#271828 Forward-Port-Of: odoo/odoo#267915
Automatic reconciliation now preserves the original payment reference on matched bank statement lines instead of replacing it with the account name. This keeps labels consistent across reconciliation methods and makes it easier for users to identify transactions correctly.
Original PR description
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent…
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent lines with the account name This creates an inconsistent user experience Using the "Set Account" button directly keeps the statement line payment reference as the journal item label However, clicking the automatically generated reconciliation model button replaces that reference with the account name Before the fix, clicking the automated rule button on a third matching line overrides its label with the account name instead of keeping its unique reference ### Cause: In `_create_reconciliation_rule`, when an automatic model is generated, the dictionary used to create the counterpart line explicitly set `label` to `rule_data['account'].name` When a reconciliation model line has a specific label defined, Odoo uses it to replace the statement line `payment_ref` on the generated counterpart move lines Removing this default value allows the system to fall back on the original payment reference ### Steps to reproduce: - Install `account_accountant` - Go to the Bank Reconciliation widget from the Accounting Dashboard - Create 2 statement lines without partners (e.g., Ref: "Test Ref 1" and "Test Ref 2") - Set the same account on both lines using Set Account - This automatically creates a Reconciliation Rule named after the account - Create a 3rd statement line with a matching reference (e.g., "Test Ref 3") - Click the newly available automatic reconciliation button for this line Before the fix, checking the generated entry label shows the account name instead of "Test Ref 3" To check unfold the details, click on the pencil icon of a line opw-6246833 Forward-Port-Of: odoo/enterprise#119133
This update adjusts how French PDP-related records are recalculated so they no longer depend on unrelated company or partner changes. It helps avoid build errors and prevents unnecessary system work when partner information is updated, improving stability and performance.
Original PR description
- This removes dependency on account move fields to company : Build error 939448 - This removes dependency on account move fields to commercial_partner_id fields (avoid recompute all moves on partner info change) Forward-Port-Of: odoo/odoo#271978 Forward-Port-Of: odoo/odoo#269701
The German SKR03 accounting template now points to the correct default accounts for cash discounts. This helps ensure bookkeeping setup uses the right account codes and reduces the risk of misconfigured accounting entries.
Original PR description
The default cash discout accounts referenced in the
German skr03 template used the wrong account codes.
The template has been updated with the right ones.
task-4915939
opw-4909059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271886
Forward-Port-Of: odoo/odoo#271024The default cash discount accounts in the German SKR03 template were pointing to the wrong account codes. They have been updated so accounting reports and exports use the correct defaults, reducing the risk of posting or reporting errors.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
The holiday attestation calculation now uses the correct wage basis when an employee had a long sick leave. This prevents the annual taxable income from being incorrectly set to zero and ensures the employee’s holiday-related amounts are computed accurately.
Original PR description
Problem ---------------------- When an employee takes a long sick leave (more than 30 days), the basic wage on the payslip is set to 0, leading to the holiday attest annual taxable income to be…
Problem ---------------------- When an employee takes a long sick leave (more than 30 days), the basic wage on the payslip is set to 0, leading to the holiday attest annual taxable income to be calculated as 0 * 12, which is incorrect. Reason ------------------- The calculation for the holiday attest uses the last payslip for the employee, and if the employee had leave type LEAVE214, the last payslip has the basic wage set to zero, so the taxable wage that is used in the annual taxable wage calculation is wrong. The monthly wage should be used as the basic wage in the payslip to get the correct computation. Solution ------------------- The GROSS (taxable income) line that is used is computed as (basic wage - ONSS total + BIK), but the basic wage was 0. This commit checks whether the basic wage is 0 and if the time off type was longterm sick leave, and simulates a payslip using the monthly wage from the contract as basic wage to get the accurate computation for the taxable income. task-6237717 Forward-Port-Of: odoo/enterprise#120180
This change prevents an error that could appear when opening the Accounting tab in Studio for contacts with bank accounts. It makes the bank tag component accept the same read-only behavior as the rest of the interface, so the page loads correctly instead of failing.
Original PR description
When opening Studio → Contacts → Accounting Tab, Owl raises the following error: ```py Odoo Client Error Occured on 114697239-saas-19-2-all.runbot254.odoo.com on 2026-06-19 07:01:00 GMT…
When opening Studio → Contacts → Accounting Tab, Owl raises the following error:
```py
Odoo Client Error
Occured on 114697239-saas-19-2-all.runbot254.odoo.com on 2026-06-19 07:01:00 GMT
UncaughtPromiseError > OwlError
Uncaught Promise > Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
OwlError: Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
Error: Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
at Object.validateProps (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1001:67)
at FieldMany2ManyTagsBanks.slot1 (eval at compile (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1387:421), <anonymous>:16:13)
at callSlot (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:968:25)
at TagsList.template (eval at compile (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1387:421), <anonymous>:22:30)
at Fiber._render (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:797:96)
at Fiber.render (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:796:6)
at ComponentNode.initiateRender (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:867:47)
```
Note: The error only occurs when the contact has at least one bank accounts (bank_ids) in the Accounting tab.
`FieldMany2ManyTagsBanks` inherits from `Many2ManyTagsField`, whose `getTagProps()` [method](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js#L165-L173) intentionally sets `onDelete` to [undefined](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js#L168) when the field is rendered in readonly mode.
However, `BankTag` declares `onDelete` as a required [prop](https://github.com/odoo/odoo/blob/saas-19.2/addons/account/static/src/components/many2many_tags_banks/many2many_tags_banks.js#L18). Since Studio renders the field as readonly, `onDelete` is undefined, causing Owl prop validation to fail.
Make `onDelete` optional in `BankTag` to match the behavior of the parent widget and the underlying `BadgeTag` component, which already defines `onDelete` as [optional](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/core/tags_list/badge_tag.js#L12).
This fixes the Owl error when opening the Accounting tab in Studio.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271019When a database field changes from one index type to another, Odoo now replaces the old index instead of silently keeping the outdated one. This helps keep searches fast and reliable after upgrades, especially for records that rely on specialized search indexes.
Original PR description
Description of the issue/feature this PR addresses: `Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates…
Description of the issue/feature this PR addresses:
`Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates the index when no index of that name already exists. It never inspects the access method of an existing index.
As a consequence, changing a field's `index=` kind on an **already-indexed** column is silently ignored on existing databases. For example `account.move.name` was changed from a plain btree index to `index='trigram'`:
```python
name = fields.Char(
...
index='trigram',
)
```
On a fresh database this creates the expected GIN/trigram index. On any database that already had the btree index, the old btree index keeps its name, so `check_indexes` finds the name present and does nothing. The `(=)ilike` searches the trigram index was meant to accelerate keep falling back to sequential scans, with no error or warning.
Current behavior before PR:
### Steps to reproduce
1. Install a module on an existing DB while a `Char` field is `index=True` (btree).
2. Change the field to `index='trigram'` and upgrade the module.
3. `\d <table>` in psql — the index is still `USING btree`, not `USING gin`.
Desired behavior after PR is merged:
`check_indexes` now also reads each existing index's access method (`pg_am.amname`). When the method no longer matches what the field expects (`gin` for trigram, `btree` otherwise), the stale index is dropped and recreated. The drop is issued inside the **same savepoint** as the recreate, so a failed rebuild (e.g. a lock timeout) rolls the drop back and never leaves the column without an index.
Scope: only the access method is reconciled. A change that alters solely the partial predicate (`btree` -> `btree_not_null`) keeps the same method and is intentionally left untouched.
### Notes
- This extends the existing index-management logic in place and keeps the current "keep unexpected index" behaviour for fields that dropped `index=` entirely; only fields that still want an index, of a different method, are rebuilt.
- Trigram rebuilds still require the `pg_trgm` extension; without it the GIN index is skipped exactly as before (`self.has_trigram` guard).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272198
Forward-Port-Of: odoo/odoo#268505When a partner’s official data is refreshed in the POS flow, the updated legal information is now correctly shown right away. This avoids POS keeping a temporary name after the government lookup has returned the verified partner details.
Original PR description
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh…
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh icon` is visible: click on it. Observation: - the dialog is closed and partner is selected with "temp" name Expected: - with valid government credentials and a valid identification number, the refresh action should also update the partner data on the POS side Cause: - the refresh button triggers the `button_l10n_co_dian_refresh_data` action, which fetches the legal name and email from the government service - although the backend record is correctly updated, the new values are not immediately synchronized with the POS - when the refresh button is clicked, editPartner() first triggers `web_save` using the temporary "temp" name and immediately reads the partner data afterward - the refresh action executes later and updates the contact with the fetched legal information, but the POS is not aware of these subsequent changes Fix: - read the data again if there is any update caused by this action. - this is done by overriding `afterExecuteActionButton` of FormController class opw-6198035 Forward-Port-Of: odoo/enterprise#117527
This update ensures that upgraded databases for the Dominican Republic localization receive the latest chart of accounts, taxes, and tax groups. It prevents missing accounting records after an upgrade, so businesses keep using the correct local accounting setup without manual fixes.
Original PR description
Steps to Reproduce: * Create a database before saas~19.3. * Install to l10n_do and company configured * Upgrade the database to saas~19.3. * Check the Dominican Republic chart of accounts, taxes, and…
Steps to Reproduce:
* Create a database before saas~19.3.
* Install to l10n_do and company configured
* Upgrade the database to saas~19.3.
* Check the Dominican Republic chart of accounts, taxes, and tax groups.
Issue:
* The localization updates introduced in saas~19.3 are not loaded during the upgrade.
* As a result, some Dominican Republic accounts, taxes, and tax groups are missing after the upgrade.
Cause:
* New localization data was introduced for `l10n_do`, but the chart template is not reloaded during the upgrade.
* Consequently, the newly introduced records are never created on upgraded databases.
Related:
https://github.com/odoo/odoo/pull/257233
Fix:
* Reload the Dominican Republic chart template during the upgrade using `account.chart.template.try_loading('do', company)` to ensure all newly
introduced accounts, taxes, and tax groups are created.
opw-6274580
upg-4333738
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix lets users record several finished-product serial numbers or lots in a single barcode session during manufacturing. It prevents the last scan from overwriting earlier ones, so production can be validated correctly and the right lot information is saved.
Original PR description
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and…
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and confirm it. 3. Open the Barcode app, scan the MO, then scan a first serial number SN_X1. 4. Scan a second serial number SN_X2. 5. Validate. Lot-tracked finished product: 1. Create a lot-tracked finished product with a one-component BoM and an existing lot LOT_A. 2. Create a Manufacturing Order and confirm it. 3. Open the Barcode app, scan the MO, then scan the existing lot LOT_A. 4. Scan a different, not-yet-existing lot LOT_B. 5. Validate. Issue ----- Only the last scanned serial is registered on the MO, and validation then fails because the count of producing serials does not match qty_producing for a serial-tracked finished product. updateLine overwrote lot_producing_ids with [args.lot_id] on every scan, so the first serial was dropped when the second one was scanned, and the same branch never staged a freshly typed lot_name, so a brand-new serial typed on a serial-tracked MO was lost before reaching the backend. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L407 Two behaviours of the shared barcode dispatcher make a single accumulating branch insufficient. The final-product line must keep exposing a producing lot, otherwise the base hasUnassignedQty check counts a scanned serial as zero once a quantity is already set, leaving qty_producing stuck below the demand. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1446 But exposing a producing lot makes the dispatcher treat the next serial as a conflicting tracking number, since the base _canOverrideTrackingNumber considers a different lot name non-overridable. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L796-L798 So the scan is diverted to a new line through the override gate instead of updating the header line. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1585 For a lot-tracked finished product the producing lot can be corrected by scanning a different value, but the lot branch only stored a freshly typed value in lot_name and overwrote lot_producing_ids with the single existing lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L404-L407 The header reads its lot from lot_producing_ids whenever that relation is set and only falls back to lot_name when it is empty. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/components/header.js#L45-L58 The save path only promotes lot_name to a producing lot when lot_producing_ids is empty, so scanning an existing lot then a new one neither displayed nor recorded the new lot and the finished product was produced under the old lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L628 Solution -------- Accumulate scanned serials by appending to lot_producing_ids instead of replacing it, and stage a freshly typed lot_name as a new producing lot when the finished product is tracked by serial, so every serial reaches the backend. Keep the final-product line exposing the last producing lot so each scanned serial is still counted as one unit instead of resetting the quantity to zero once several serials are registered. Override _canOverrideTrackingNumber for the final-product line so a serial scan updates the header line rather than being diverted to a new line, which is the only valid path for the finished product since it is a single header line backed by the lot_producing_ids relation. Persist the producing serials with explicit x2many commands, separating already-existing lots from freshly typed ones, so both are written on the MO. Reject a serial that is already registered on the MO so the same number cannot be produced twice in one session. For a lot-tracked finished product, build a producing lot from the scanned value, using the existing lot or a freshly typed lot name, and store it in lot_producing_ids so the new lot is both displayed and persisted through the same x2many commands as the serial case. Leave the produced quantity unchanged when the scanned lot differs from the one already registered, since replacing the lot is a correction and not an extra unit, and keep incrementing it when the same lot is scanned again. opw-6189620 Forward-Port-Of: odoo/enterprise#116890
When a vendor bill is completed from a purchase order, related invoice details can change. This update ensures early payment discount lines are refreshed or removed correctly so the invoice and journal entries stay aligned.
Original PR description
When a vendor bill is imported and auto-completed from a purchase order, then invoice lines, taxes, fiscal position, and payment terms can change. Existing EPD dynamic lines that lose their epd_key are skipped by sync and keep stale tax tags and amounts, causing mismatches between Invoice Lines and Journal Items. This commit makes EPD sync include keyless existing EPD lines so they are rewritten or removed during dynamic recomputation after PO auto-complete. Journal items remain consistent with the final invoice lines, taxes, and early discount configuration. Ticket [link](https://www.odoo.com/odoo/project.task/6047505) opw-6047505 Forward-Port-Of: odoo/odoo#272267 Forward-Port-Of: odoo/odoo#265539
30 changes
Resolved issues and error corrections
The stock forecast report now converts all quantities to the product’s main unit of measure before displaying them. This prevents mixed units from appearing on the same graph and makes the forecast easier to read and interpret.
Original PR description
When a stock move's UoM differs from the product template's UoM, the report aggregation incorrectly shows data for both UoMs of stock move.quantity on the same graph. All moves should be normalized…
When a stock move's UoM differs from the product template's UoM, the report aggregation incorrectly shows data for both UoMs of stock move.quantity on the same graph. All moves should be normalized to the UoM of the product for which we are viewing the forecast. We can do this with: `m.quantity * move_uom.factor / pt_uom.factor AS quantity` If the UoMs of the stock move and the product template are identical, as is the case most of the time, this simply multiplies by one, and the query behaves exactly as it did before. But if the units are distinct, the move UoM is converted into the product template UoM so that the data for stock move quantity is normalized to one shared unit across the entire forecast graph. **E.g.**: m.quantity == 500g m.UoM == g m.UoM.factor == 1 pt.UoM == kg pt.UoM.factor == 1000 500g * 1 / 1000 ==> .5kg **Steps to Reproduce on Runbot**: 1. Create a product which uses kg and g. 2. Confirm and Validate a receipt for this product (10 kg for example). 3. Confirm a second receipt for this product in the same UoM kg. 4. Confirm and Validate a delivery for this product with UoM g (500 g for example). 5. View the forecasted graph for the product, and you will see that the y axis is scaled on grams ~500, and the current / future stock moves in the report are still scaled based on kg. opw-6234066 Forward-Port-Of: odoo/odoo#266811
The salary configurator no longer crashes when a user enables the company car option without a car model being selected. This makes the setup process work correctly for companies installed without demo data.
Original PR description
## Steps to Reproduce: 1. Install `l10n_be_hr_contract_salary` without demo data. 2. Create a Belgian company and switch to it. 3. Create an employee. 4. Create a contract for the employee. 5. Click Generate Offer and open the Salary Configurator. 6. Enable the 'Company Car (To order)' option. ## Error: `AttributeError: 'NoneType' object has no attribute 'split'` ## Cause: When the salary configurator is used without demo data, no car model is selected. The method assumes that select_wishlist_car_total_depreciated_cost always contains a value and directly calls split() on it, resulting in an error, when the field is None. ## Fix: This commit checks that both the company car option is enabled and a car model has been selected before trying to extract the model ID. sentry-7554712017 Forward-Port-Of: odoo/enterprise#121650 Forward-Port-Of: odoo/enterprise#121138
This update corrects a Belgian VAT number used in an automated test so it matches current validation rules. It keeps the same test scenario while preventing failures caused by stricter external validation checks.
Original PR description
This commit fixes a Belgian VAT validation check in `test_import_partner_retrieval_bank_account_number` as the provided vat number isn't a valid one. It keeps the spirit of the test by still having vat number mismatch, but with a valid value. The python-stdnum library used for this validation added a stricter check since version 2.2, which is used in Ubuntu Resolute 26.04. References: - https://github.com/arthurdejong/python-stdnum/commit/7ca9b6ce7b1f2b4d1bf164c2af83a8a77bc919d2 runbot-939796 Forward-Port-Of: odoo/odoo#272082
This update fixes how French PDP-related records are recalculated so they no longer depend on unrelated company or partner details. It prevents unnecessary rebuilds and reduces the risk of errors or slowdowns when company or contact information changes.
Original PR description
- This removes dependency on account move fields to company : Build error 939448 - This removes dependency on account move fields to commercial_partner_id fields (avoid recompute all moves on partner info change) Forward-Port-Of: odoo/odoo#271978 Forward-Port-Of: odoo/odoo#269701
This change prevents the system from creating duplicate draft entries when the scheduled import runs. It restores the previous behavior so repeated files are not processed in a way that creates extra transactions, reducing confusion and cleanup for users.
Original PR description
Since this commit: https://github.com/odoo/enterprise/commit/a0c9e9b5c0ed8135d77c343c819c1fa918356794 users are experiencing some duplicate draft move when the cron is running. It's because we don't skip the files when it already exist, we now add a number of imported count. This commit will revert this change to avoid the problem, and we will contact codabox to find a better way to deal with files imported the same month. task-6299508 Forward-Port-Of: odoo/enterprise#121472
Automatic reconciliation rules now preserve the original payment reference on bank statement lines instead of replacing it with the account name. This makes labels consistent across reconciliation methods and helps users identify entries more easily.
Original PR description
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent…
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent lines with the account name This creates an inconsistent user experience Using the "Set Account" button directly keeps the statement line payment reference as the journal item label However, clicking the automatically generated reconciliation model button replaces that reference with the account name Before the fix, clicking the automated rule button on a third matching line overrides its label with the account name instead of keeping its unique reference ### Cause: In `_create_reconciliation_rule`, when an automatic model is generated, the dictionary used to create the counterpart line explicitly set `label` to `rule_data['account'].name` When a reconciliation model line has a specific label defined, Odoo uses it to replace the statement line `payment_ref` on the generated counterpart move lines Removing this default value allows the system to fall back on the original payment reference ### Steps to reproduce: - Install `account_accountant` - Go to the Bank Reconciliation widget from the Accounting Dashboard - Create 2 statement lines without partners (e.g., Ref: "Test Ref 1" and "Test Ref 2") - Set the same account on both lines using Set Account - This automatically creates a Reconciliation Rule named after the account - Create a 3rd statement line with a matching reference (e.g., "Test Ref 3") - Click the newly available automatic reconciliation button for this line Before the fix, checking the generated entry label shows the account name instead of "Test Ref 3" To check unfold the details, click on the pencil icon of a line opw-6246833 Forward-Port-Of: odoo/enterprise#119133
When a vendor bill is auto-filled from a purchase order, some invoice details can change and previously generated early payment discount lines could stay out of sync. This update makes those lines refresh or disappear as needed, so invoice lines and journal items stay aligned and the bill totals remain correct.
Original PR description
When a vendor bill is imported and auto-completed from a purchase order, then invoice lines, taxes, fiscal position, and payment terms can change. Existing EPD dynamic lines that lose their epd_key are skipped by sync and keep stale tax tags and amounts, causing mismatches between Invoice Lines and Journal Items. This commit makes EPD sync include keyless existing EPD lines so they are rewritten or removed during dynamic recomputation after PO auto-complete. Journal items remain consistent with the final invoice lines, taxes, and early discount configuration. Ticket [link](https://www.odoo.com/odoo/project.task/6047505) opw-6047505 Forward-Port-Of: odoo/odoo#271981 Forward-Port-Of: odoo/odoo#265539
This update fixes a display issue in purchase request for quotation reports, where incoterm details were visible in the screen version but missing from the PDF. With this change, the printed quotation now matches what users see on screen, helping ensure shipping terms are communicated correctly.
Original PR description
Currently, when printing a request for quotation the incoterm informations are not present. Steps to reproduce: ------------------- * Create a new quotation * Add basic required information * Open…
Currently, when printing a request for quotation the incoterm informations are not present. Steps to reproduce: ------------------- * Create a new quotation * Add basic required information * Open tab "Other info" and fill incoterm field(s) * Save (don't confirm) * Print RFQ pdf report > Observation: The incoterm values are not being printed Why the fix: ------------ If we look at the html version of that report we can see those information are present before the logo section. This issue was introduced by the following commit: https://github.com/odoo/odoo/commit/bba2fc505f5d0b4770eacc6877155b1aeda6d772 As we can see the incoterm informations are positioned after the `layout_document_title` https://github.com/odoo/odoo/blob/a7de246efa8241c49196be0e0477abd086bf9e63/addons/purchase_stock/report/purchase_report_templates.xml#L44-L55 After the mentioned commit the `layout_document_title` is defined before the external layout. So when the report is rendered the incoterm bloc is positioned before the external layout as well which explains why it can be seen in the html and not the pdf. This fix changes the xpath to make it corresponds to the same placement as it was prior to the issue. The class `page` was chosen in this case as the `layout_document_title` block was before the page class as well and all the blocks that were in between `layout_document_title` and `page` previously are now also before the external layout. HTML: <img width="1718" height="867" alt="image" src="https://github.com/user-attachments/assets/0b2a04ec-5f0e-4915-8e57-e511a1cd2d8c" /> PDF: <img width="1677" height="870" alt="image" src="https://github.com/user-attachments/assets/06e94ea4-6ce6-48ed-85db-c672137877c2" /> After fix: <img width="1917" height="1002" alt="image" src="https://github.com/user-attachments/assets/158e66a1-83ea-4122-8daa-f90e9aa537d5" /> opw-6211465
This update fixes issues in the Viva payment flow so receipts and preparation prints are generated correctly after payment. It also ensures the Viva payment prompt appears when expected and clears outdated stored answers if a user changes their choice, reducing mistakes during checkout.
Original PR description
[FIX] point_of_sale, pos_viva_com: automatic receipt printing 3 Fixes for the app-to-app integration of Viva 1. Under the normal flow the `OrderPaymentValidation` does the payment validation and post…
[FIX] point_of_sale, pos_viva_com: automatic receipt printing 3 Fixes for the app-to-app integration of Viva 1. Under the normal flow the `OrderPaymentValidation` does the payment validation and post validation operations (such as receipt printing or preparation prints). Then it launches the `FeedbackScreen` with the validation promise on the `waitFor` prop. The `pos_viva_com` app-2-app integration does the payment validation on the backend on the callback endpoint. Then it redirects the user directly on the `FeedbackScreen` skipping the normal validation and post validation operations. This means that receipts and preparation prints do not get processed. This PR adds a check on the `FeedbackScreen` to see whether there is anything set on the `waitFor` prop. If the prop is undefined, we can expect that the screen was mounted outside the normal flow, so we run the post validation operations manually. --- 2. Using the fast payment method with Viva would use `order.addPaymentLine` instead of the overloaded `payment_screen.addNewPaymentLine`. So the integration pop up which is defined in the `payment_screen` would never fire. Now I've added a check on `validateOrder` to detect whether we're about to use a `fastPaymentMethod`, in which case it will apply the same behaviour as the override of the `payment_screen.addNewPaymentLine` --- 3. Added a patch for `reloadData` which will remove the answer for the Viva wallet pop up from local storage in case users change their minds or made a mistake Task-[6251297](https://www.odoo.com/odoo/project/1737/tasks/6251297) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change fixes a test that could miss an update if the messaging connection was not fully ready before the notification was sent. It helps ensure WhatsApp seen indicators load reliably and prevents false test failures.
Original PR description
The "Allow SeenIndicators in WhatsApp Channels" test delivers the seen update over the bus with `_sendone`, but nothing waited for the websocket to subscribe to the channel first. When the notification was sent before the subscription landed it was dropped, the member's seen_message_id was never updated client-side and the seen indicators never rendered, so the assertion timed out. The current user is a member of the channel, so it is subscribed at connection time: wait for the subscription together with `start()` (listener registered first) before opening the channel and sending the notification. https://runbot.odoo.com/odoo/error/242021
This change prevents upgrade failures for Italian accounting databases that include the local tax report. It removes outdated report definitions before the upgrade runs, so customers can move to the latest version without hitting an error during the update process.
Original PR description
Steps to reproduce: - Create a database with `l10n_it_reports` on a version before PR #264294 - Switch to current `17.0` - Upgrade module `l10n_it` - An error is raised Upgrading a database with `l10n_it_reports` installed raises an error if the database was created before that PR In that PR, we modified the formulas of several report expressions to use subformulas instead of simple aggregations. During upgrade, the ORM attempts to insert the updated expressions while the old ones still exist, violating the UNIQUE constraint on `(report_line_id, label)` in `account.report.expression` Only happens on upgrade, not on a fresh install. A migration script is added to delete the outdated expressions before the upgrade runs Ticket [link](https://www.odoo.com/odoo/project.task/6299385) opw-6299385 Forward-Port-Of: odoo/odoo#271320
When two restaurant table orders are combined, products that were already sent to the kitchen now keep their sent quantity correctly. This prevents staff from having to resend items that were already prepared, reducing duplicate kitchen tickets and avoiding unnecessary work.
Original PR description
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was…
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was incorrectly marked as new and had to be sent again. Steps to reproduce: ------------------- * Open table 1, add product A (2 units) and product B, send to kitchen * Open table 2, add product A (3 units) and product C, send to kitchen * On table 2, transfer/merge the order to table 1 > Observation: product A shows 2 units as new and must be sent to the kitchen printer again, although all quantities were already sent. Why the fix: ------------ When merging preparation history for identical lines, handlePreparationHistory overwrote the destination sent quantity with the source one instead of summing both. The kitchen diff then treated the missing quantity as new changes. A unit test will be added in 18.3. opw-6246470 Forward-Port-Of: odoo/odoo#271828 Forward-Port-Of: odoo/odoo#267915
When a product is set to be made on demand but has no Bill of Materials, Odoo will no longer create an empty manufacturing order. This ensures the replenishment flow handles the request correctly and prevents confusing draft orders from appearing.
Original PR description
Steps to reproduce: - unarchive the MTO route - Create a storable product "P1" with the MTO + Manufacture routes but set no Bill of Materials on it - Create a sales order with one unit of P1 and confirm it Problem: An empty draft MO is created even though no Bill of Materials exists. When no BoM is available, manufacturing orders should not be created, only replenishment rules are expected to handle this case. Fix: Added an early `continue` in `_run_manufacture` to skip MO creation when no BoM is found. opw-6174886 Forward-Port-Of: odoo/odoo#263108
This change ensures that when a field’s index type is updated, existing databases also get the new index type instead of silently keeping the old one. This helps searches stay fast and reliable after upgrades, especially for large datasets.
Original PR description
Description of the issue/feature this PR addresses: `Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates…
Description of the issue/feature this PR addresses:
`Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates the index when no index of that name already exists. It never inspects the access method of an existing index.
As a consequence, changing a field's `index=` kind on an **already-indexed** column is silently ignored on existing databases. For example `account.move.name` was changed from a plain btree index to `index='trigram'`:
```python
name = fields.Char(
...
index='trigram',
)
```
On a fresh database this creates the expected GIN/trigram index. On any database that already had the btree index, the old btree index keeps its name, so `check_indexes` finds the name present and does nothing. The `(=)ilike` searches the trigram index was meant to accelerate keep falling back to sequential scans, with no error or warning.
Current behavior before PR:
### Steps to reproduce
1. Install a module on an existing DB while a `Char` field is `index=True` (btree).
2. Change the field to `index='trigram'` and upgrade the module.
3. `\d <table>` in psql — the index is still `USING btree`, not `USING gin`.
Desired behavior after PR is merged:
`check_indexes` now also reads each existing index's access method (`pg_am.amname`). When the method no longer matches what the field expects (`gin` for trigram, `btree` otherwise), the stale index is dropped and recreated. The drop is issued inside the **same savepoint** as the recreate, so a failed rebuild (e.g. a lock timeout) rolls the drop back and never leaves the column without an index.
Scope: only the access method is reconciled. A change that alters solely the partial predicate (`btree` -> `btree_not_null`) keeps the same method and is intentionally left untouched.
### Notes
- This extends the existing index-management logic in place and keeps the current "keep unexpected index" behaviour for fields that dropped `index=` entirely; only fields that still want an index, of a different method, are rebuilt.
- Trigram rebuilds still require the `pg_trgm` extension; without it the GIN index is skipped exactly as before (`self.has_trigram` guard).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272198
Forward-Port-Of: odoo/odoo#268505This fix ensures the holiday attest uses the employee’s normal monthly wage when long sick leave would otherwise make the last payslip show a zero basic wage. As a result, the annual taxable income used for the certificate is calculated correctly and employees are no longer underreported because of extended sickness leave.
Original PR description
Problem ---------------------- When an employee takes a long sick leave (more than 30 days), the basic wage on the payslip is set to 0, leading to the holiday attest annual taxable income to be…
Problem ---------------------- When an employee takes a long sick leave (more than 30 days), the basic wage on the payslip is set to 0, leading to the holiday attest annual taxable income to be calculated as 0 * 12, which is incorrect. Reason ------------------- The calculation for the holiday attest uses the last payslip for the employee, and if the employee had leave type LEAVE214, the last payslip has the basic wage set to zero, so the taxable wage that is used in the annual taxable wage calculation is wrong. The monthly wage should be used as the basic wage in the payslip to get the correct computation. Solution ------------------- The GROSS (taxable income) line that is used is computed as (basic wage - ONSS total + BIK), but the basic wage was 0. This commit checks whether the basic wage is 0 and if the time off type was longterm sick leave, and simulates a payslip using the monthly wage from the contract as basic wage to get the accurate computation for the taxable income. task-6237717
This update prevents subscription products from being saved without a required plan when they are not available as one-time sales. It also makes hybrid subscription products available in pricing rules for one-time pricing, so users can configure prices more easily and accurately.
Original PR description
Before this commit:
1. Users could save a pricelist rule for a pure subscription product without assigning a plan.
2. Hybrid subscription products (where 'Allow One-Time Sale' is True) were filtered out of the pricelist item form when no plan was selected, preventing users from setting a one-time price.
After this commit:
- The `plan_id` field on the product template form is now mandatory if the product is a subscription and does not allow one-time sales.
- The `product_tmpl_id` domain on the pricelist item form is updated to `['|', ('recurring_invoice', '=', bool(plan_id)), ('allow_one_time_sale', '=', True)]`, allowing users to select hybrid products for one-time pricing.
task: 6164232
Forward-Port-Of: odoo/enterprise#115271This fix ensures that when manufacturing products are scanned in the Barcode app, every produced serial number or lot is kept and saved instead of only the last one. It prevents validation errors and makes production tracking accurate when a single manufacturing order produces more than one item.
Original PR description
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and…
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and confirm it. 3. Open the Barcode app, scan the MO, then scan a first serial number SN_X1. 4. Scan a second serial number SN_X2. 5. Validate. Lot-tracked finished product: 1. Create a lot-tracked finished product with a one-component BoM and an existing lot LOT_A. 2. Create a Manufacturing Order and confirm it. 3. Open the Barcode app, scan the MO, then scan the existing lot LOT_A. 4. Scan a different, not-yet-existing lot LOT_B. 5. Validate. Issue ----- Only the last scanned serial is registered on the MO, and validation then fails because the count of producing serials does not match qty_producing for a serial-tracked finished product. updateLine overwrote lot_producing_ids with [args.lot_id] on every scan, so the first serial was dropped when the second one was scanned, and the same branch never staged a freshly typed lot_name, so a brand-new serial typed on a serial-tracked MO was lost before reaching the backend. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L407 Two behaviours of the shared barcode dispatcher make a single accumulating branch insufficient. The final-product line must keep exposing a producing lot, otherwise the base hasUnassignedQty check counts a scanned serial as zero once a quantity is already set, leaving qty_producing stuck below the demand. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1446 But exposing a producing lot makes the dispatcher treat the next serial as a conflicting tracking number, since the base _canOverrideTrackingNumber considers a different lot name non-overridable. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L796-L798 So the scan is diverted to a new line through the override gate instead of updating the header line. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1585 For a lot-tracked finished product the producing lot can be corrected by scanning a different value, but the lot branch only stored a freshly typed value in lot_name and overwrote lot_producing_ids with the single existing lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L404-L407 The header reads its lot from lot_producing_ids whenever that relation is set and only falls back to lot_name when it is empty. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/components/header.js#L45-L58 The save path only promotes lot_name to a producing lot when lot_producing_ids is empty, so scanning an existing lot then a new one neither displayed nor recorded the new lot and the finished product was produced under the old lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L628 Solution -------- Accumulate scanned serials by appending to lot_producing_ids instead of replacing it, and stage a freshly typed lot_name as a new producing lot when the finished product is tracked by serial, so every serial reaches the backend. Keep the final-product line exposing the last producing lot so each scanned serial is still counted as one unit instead of resetting the quantity to zero once several serials are registered. Override _canOverrideTrackingNumber for the final-product line so a serial scan updates the header line rather than being diverted to a new line, which is the only valid path for the finished product since it is a single header line backed by the lot_producing_ids relation. Persist the producing serials with explicit x2many commands, separating already-existing lots from freshly typed ones, so both are written on the MO. Reject a serial that is already registered on the MO so the same number cannot be produced twice in one session. For a lot-tracked finished product, build a producing lot from the scanned value, using the existing lot or a freshly typed lot name, and store it in lot_producing_ids so the new lot is both displayed and persisted through the same x2many commands as the serial case. Leave the produced quantity unchanged when the scanned lot differs from the one already registered, since replacing the lot is a correction and not an extra unit, and keep incrementing it when the same lot is scanned again. opw-6189620 Forward-Port-Of: odoo/enterprise#116890
The German SKR03 template now points to the correct default accounts for cash discounts. This helps ensure accounting entries are set up properly and reduces the risk of using the wrong account codes during configuration.
Original PR description
The default cash discout accounts referenced in the
German skr03 template used the wrong account codes.
The template has been updated with the right ones.
task-4915939
opw-4909059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271886
Forward-Port-Of: odoo/odoo#271024The default cash discount accounts in the German SKR03 template were using incorrect account codes. They have been updated to the right ones so German accounting exports and related reports reflect the proper accounts.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
The mailing theme selector now updates both the title and the preview when switching between favorite templates for different target models. This prevents users from seeing a mismatched preview and helps them choose the right mailing template more confidently.
Original PR description
Overview ------ When having a favorite mailing (template) for target model X, and another one for target model Y, and try to create a new mailing for target model X, the theme selector will first…
Overview ------ When having a favorite mailing (template) for target model X, and another one for target model Y, and try to create a new mailing for target model X, the theme selector will first show the template X with the correct title and preview, however when switching to model Y, the theme selector will show the title of the tempalte Y but the preview is always the one of template X. How to reproduce ------ 1. Create a new mailing for a target model X (e.g. `mailing.contact`) 2. Set a content for that mailing (you can choose from the existing themes) 3. Set that mailing as a favorite (using the favorite star button) 4. Create a new mailing for another target model Y. 5. Redo steps 2. and 3. 6. Create a new mailing, and set the target model to X (You should see the mailing X in the theme selector with the correct title and preview) 7. Change the target model to Y. Expected Behavior ------ Both the title and the preview of the mailing X in the theme selector should change into the title and the preivew of mailing Y. Current Behavior ------ The title of the template is changed into the one of Y however the preview remains the one of mailing X. Cause of The Issue ------ After the first mount of the `FavoritePreivew` component, when the template changes in the props, the body content of the preivew is not updated with the new value. Task-6332946 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272065
This fix stops popup-related snippets from being offered in places where they should not be used, including after snippet refreshes. It also prevents a browser error that could appear when editing websites, improving reliability while keeping the editing experience consistent.
Original PR description
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError:…
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError: Cannot read properties of undefined (reading 'after')`. This can happen in multiple scenarios: - After saving a custom snippet, the snippets are reloaded but `disableUndroppableSnippets` is not called again, although the snippets should be filtered again. - `NewsletterPopupPlugin` registers `.o_newsletter_popup` in the `so_snippet_addition_selector` resource, bypassing the more restrictive `dropzone_selector` of `PopupOptionPlugin`. - Popups are not disabled when the cookie bar is open because we don't take `excludeAncestor` into account in `DisableSnippetsPlugin`. __Fix__ - Trigger an event whenever the snippets are loaded and call `disableUndroppableSnippets` when it is. - Remove the redundant `NewsletterPopupPlugin`. - Filter `dropAreaEls` with `excludeAncestor` in `DisableSnippetsPlugin`. Forward-Port-Of: odoo/odoo#271635 Forward-Port-Of: odoo/odoo#269864
This change stops public holiday work entries from being counted twice when they overlap with worked-time leave. It ensures the holiday is applied first, so payroll work entries stay accurate and employees do not see inflated hours on the same day.
Original PR description
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day.…
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day. Steps to reproduce: - Create an employee with Work Entry Source set to Attendances - Use a flexible working schedule on the employee - Configure a public holiday on a scheduled day with work entry type (Paid time off) - Create a time off type with Count as set to Worked Time - Generate time off for the period so the public holiday entry exists (maybe a day before and a the public holiday and the day after) - Open Payroll > Work Entries (Observe the date of the public holiday will have more than 8h entry) Cause: In `_get_version_work_entries_values()`, calendar leaves are split by `hr_holidays` `time_type` into: - leaves: absences and public holidays - worked_leaves: worked-time time off For attendance-based contracts, both sets were turned into work entries without removing overlap between a public holiday and a worked-time leave on the same period. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L222-L226 For non-flexible calendar: Public holidays and worked-time leaves are both clipped to the static working schedule (e.g. 8h per working day). overlap was kept in both result sets. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L260 For flexible calendar: The one-day intervals are kept as the actual interval (often 00:00-23:59 for a public holiday). The worked-time on that day is schedule-shaped (e.g. 8h). Subtracting intervals on a full-day public holiday left a 16h fragment instead of removing the public holiday entry. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L242-L249 Solution: We need to make regular leaves take priority over worked-time leaves, compute the real regular leave intervals first, then remove those intervals from the worked-time leave intervals before work entries are created: - for fully flexible employees, subtract regular leaves from worked leaves; - for flexible calendars, keep one-day regular leaves as is and subtract them from worked-time leaves - for non-flexible attendance-based calendars, clip regular leaves on the static schedule, then subtract them from worked-time leaves clipped on the same schedule. This means that when a sandwich worked-time leave overlaps a public holiday, the public holiday consumes that period first. The overlapping part is then removed from `real_worked_leaves`, so no second worked-time entry is generated for the same public holiday period. opw-6237163 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269615 Forward-Port-Of: odoo/odoo#268527
This update prevents public holiday time from being counted twice when an employee has worked-time leave overlapping the holiday. It ensures payroll work entries are generated correctly, avoiding inflated hours and cleaner attendance-to-payroll processing.
Original PR description
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day.…
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day. Steps to reproduce: - Create an employee with Work Entry Source set to Attendances - Use a flexible working schedule on the employee - Configure a public holiday on a scheduled day with work entry type (Paid time off) - Create a time off type with Count as set to Worked Time - Generate time off for the period so the public holiday entry exists (maybe a day before and a the public holiday and the day after) - Open Payroll > Work Entries (Observe the date of the public holiday will have more than 8h entry) Cause: In `_get_version_work_entries_values()`, calendar leaves are split by `hr_holidays` `time_type` into: - leaves: absences and public holidays - worked_leaves: worked-time time off For attendance-based contracts, both sets were turned into work entries without removing overlap between a public holiday and a worked-time leave on the same period. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L222-L226 For non-flexible calendar: Public holidays and worked-time leaves are both clipped to the static working schedule (e.g. 8h per working day). overlap was kept in both result sets. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L260 For flexible calendar: The one-day intervals are kept as the actual interval (often 00:00-23:59 for a public holiday). The worked-time on that day is schedule-shaped (e.g. 8h). Subtracting intervals on a full-day public holiday left a 16h fragment instead of removing the public holiday entry. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L242-L249 Solution: We need to make regular leaves take priority over worked-time leaves, compute the real regular leave intervals first, then remove those intervals from the worked-time leave intervals before work entries are created: - for fully flexible employees, subtract regular leaves from worked leaves; - for flexible calendars, keep one-day regular leaves as is and subtract them from worked-time leaves - for non-flexible attendance-based calendars, clip regular leaves on the static schedule, then subtract them from worked-time leaves clipped on the same schedule. This means that when a sandwich worked-time leave overlaps a public holiday, the public holiday consumes that period first. The overlapping part is then removed from `real_worked_leaves`, so no second worked-time entry is generated for the same public holiday period. opw-6237163 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#120300 Forward-Port-Of: odoo/enterprise#119530
The page limit note in the website generator was updated to use more general wording instead of stating a fixed number. This gives the business more flexibility to adjust page limits later without needing another visible wording change.
Original PR description
Page limit note fixed by being more general instead of stating a blatant 200. This gives us more leeway to control the nbr of pages IAP side. Forward-Port-Of: odoo/enterprise#121671
This change corrects the color shown in the Timesheets grid when an employee has a schedule with fractional working hours. It ensures the status color matches the actual expected hours, avoiding misleading orange or red highlights caused by tiny rounding differences.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#121463Attachments added to employee records and leave requests now go into the correct folder instead of the Employees root folder. The fix also ensures documents are created properly for sick leave attachments, so records are no longer missed.
Original PR description
Before this commit, when adding an attachment to a leave or a employee version the mixin was configured to create the document in the root folder of Employees which was not very convenient. In addition, when creating a Sick leave with an attachment, no document was ever created. This commit fix both those bugs. Task-6095811 Forward-Port-Of: odoo/enterprise#120539 Forward-Port-Of: odoo/enterprise#112993
This change prevents PoS session closing from failing when the cash difference gain account has a default tax. It now calculates the tax split correctly up front, so cash counts can be posted and closed without accounting errors.
Original PR description
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session,…
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session, count more cash than expected at closing. 3. Try to close the session. -> Error message shows up "The journal entry reached an invalid state..." ... "The journal entry must always have exactly one journal item involving the bank/cash account" What's happening ---------------- PoS creates a bank statement line with the gain account as counterpart, resulting in 2 lines: cash +10, gain -10. Since the gain account has a default tax, `_sync_tax_lines` adds a tax line of -2.5 on top, which makes the move unbalanced by 2.5. Then `_sync_unbalanced_lines` adds a 4th line to fix it, on the line returned by `_get_automatic_balancing_account`, which is `journal.default_account_id`, i.e. the cash account itself for a cash journal. So we end up with 2 lines on that same cash account, which a bank statement line move doesn't allow -> Error. The fix ------- In `_post_statement_difference`, precompute the base and tax split ourselves and build the statement line's `line_ids` directly (e.g. for +10 and a 25% tax: cash +10, gain -8, tax -2). The move is balanced from creation, so `_sync_tax_lines` and `_sync_unbalanced_lines` don't have to touch it. Note that we force the tax computation to be in 'force_price_include' mode, as the counted cash difference is a gross amount (physical money in the drawer). This way the tax is always extracted from the cash amount, regardless of how the tax is configured (included or excluded in price). Same pattern is already used by `hr_expense` (cf `hr_expense.models.account_move_line._compute_totals`). opw-5972690 Forward-Port-Of: odoo/odoo#271921 Forward-Port-Of: odoo/odoo#257892
This change prevents stock installation from failing in databases that use multiple companies when not all companies have a warehouse yet. It ensures the system can complete the setup first, without stopping on a warehouse-related warning during the module install process.
Original PR description
Steps to reproduce the bug:
- Have a database with sale_management installed and at least two companies (Company 1 and Company 2)
- Confirm sale orders with storable products under each company
- Install the stock module (which triggers sale_stock as a bridge module)
Problem:
The installation raised a RedirectWarning ("Please create a warehouse for company 2") and aborted. During sale_stock installation, _init_column initialises the new `warehouse_id` column on `sale.order` via SQL. Orders belonging to companies that have no warehouse yet (company 2, since `create_missing_warehouse` only creates one for the first company at that point) remain NULL. The stored-field recompute then calls write(), which fires _check_warehouse. That constraint calls _warehouse_redirect_warning() for each company without a warehouse, raising a RedirectWarning that aborts the install.
opw-6302537
Forward-Port-Of: odoo/odoo#270962
Forward-Port-Of: odoo/odoo#270480This update ensures taxes defined for every fiscal position remain available even when no specific mapping exists, including tax unit cases. It also keeps related tax information visible in the interface and prevents tax lines from getting out of sync after fiscal position changes, reducing accounting errors and confusion.
Original PR description
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem…
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem map_tax drops every tax when the FP has no mapping, including the "All" ones that should pass through. action_open_related_taxes only lists the FP's tax_ids, so "All" taxes are invisible from the FP form. The Taxes stat button is hidden whenever the FP has no tax_ids. action_update_fpos_values invokes the field computes directly, so tax and balance lines fall out of sync after an FP change. Fix map_tax: when the FP has no tax_ids, return the input taxes whose fiscal_position_ids is empty (the "All" ones) instead of an empty recordset. action_open_related_taxes: extend the domain to also include taxes bound to no fiscal position. partner_view: drop the invisible="not tax_ids" guard on the Taxes stat button. action_update_fpos_values: route the deferred computes through _check_balanced and _sync_dynamic_lines so tax lines stay in sync after the update. task-id [6231514](https://www.odoo.com/odoo/project/967/tasks/6231514) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268273
This update adjusts an automated tax test so it correctly handles taxes that are not linked to any fiscal position. It makes the test match the intended behavior, ensuring valid taxes are not incorrectly excluded and helping prevent false failures in tax reporting checks.
Original PR description
map_tax on an empty fiscal position now preserves taxes with no fiscal_position_ids. Filter those out in test_tax_unit_auto_fiscal_position so the assertion only checks that taxes bound to a fiscal position are dropped by the unit FP. comunity PR: https://github.com/odoo/odoo/pull/268273 task-id 623151 Forward-Port-Of: odoo/enterprise#121525
17 changes
Resolved issues and error corrections
This update prevents an error when enabling the company car option in the Belgian salary configurator without demo data. It ensures the system only looks up a car model when one has actually been selected, so the offer process continues smoothly.
Original PR description
## Steps to Reproduce: 1. Install `l10n_be_hr_contract_salary` without demo data. 2. Create a Belgian company and switch to it. 3. Create an employee. 4. Create a contract for the employee. 5. Click Generate Offer and open the Salary Configurator. 6. Enable the 'Company Car (To order)' option. ## Error: `AttributeError: 'NoneType' object has no attribute 'split'` ## Cause: When the salary configurator is used without demo data, no car model is selected. The method assumes that select_wishlist_car_total_depreciated_cost always contains a value and directly calls split() on it, resulting in an error, when the field is None. ## Fix: This commit checks that both the company car option is enabled and a car model has been selected before trying to extract the model ID. sentry-7554712017 Forward-Port-Of: odoo/enterprise#121650 Forward-Port-Of: odoo/enterprise#121138
This update adjusts how French PDP-related records are recalculated so they no longer depend on unrelated company or partner changes. It helps prevent build issues and avoids unnecessary updates across invoices when partner information changes.
Original PR description
- This removes dependency on account move fields to company : Build error 939448 - This removes dependency on account move fields to commercial_partner_id fields (avoid recompute all moves on partner info change) Forward-Port-Of: odoo/odoo#271978 Forward-Port-Of: odoo/odoo#269701
This change adjusts an automated test in Point of Sale so it no longer mixes data from different company setups. It helps prevent test failures caused by company-specific settings and keeps the test environment more reliable.
Original PR description
Making the test only depend on one class setup to avoid potential (already present) multicompany issues. In this case the env.user came from one setup class but was incompatible to use during the setup of the second class that was creating records for another company. By making the test only depend on one of the tests we'll avoid this issue. runbot-939375
This update corrects a Belgian VAT number used in an automated test so it passes under newer validation rules. It keeps the test’s original purpose intact by still checking for a VAT mismatch, but with a valid VAT format.
Original PR description
This commit fixes a Belgian VAT validation check in `test_import_partner_retrieval_bank_account_number` as the provided vat number isn't a valid one. It keeps the spirit of the test by still having vat number mismatch, but with a valid value. The python-stdnum library used for this validation added a stricter check since version 2.2, which is used in Ubuntu Resolute 26.04. References: - https://github.com/arthurdejong/python-stdnum/commit/7ca9b6ce7b1f2b4d1bf164c2af83a8a77bc919d2 runbot-939796 Forward-Port-Of: odoo/odoo#272082
This change fixes an issue where automatic reconciliation could replace a bank statement’s original payment reference with the account name. As a result, transaction labels stay consistent and easier to trace when the system applies a reconciliation rule automatically.
Original PR description
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent…
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent lines with the account name This creates an inconsistent user experience Using the "Set Account" button directly keeps the statement line payment reference as the journal item label However, clicking the automatically generated reconciliation model button replaces that reference with the account name Before the fix, clicking the automated rule button on a third matching line overrides its label with the account name instead of keeping its unique reference ### Cause: In `_create_reconciliation_rule`, when an automatic model is generated, the dictionary used to create the counterpart line explicitly set `label` to `rule_data['account'].name` When a reconciliation model line has a specific label defined, Odoo uses it to replace the statement line `payment_ref` on the generated counterpart move lines Removing this default value allows the system to fall back on the original payment reference ### Steps to reproduce: - Install `account_accountant` - Go to the Bank Reconciliation widget from the Accounting Dashboard - Create 2 statement lines without partners (e.g., Ref: "Test Ref 1" and "Test Ref 2") - Set the same account on both lines using Set Account - This automatically creates a Reconciliation Rule named after the account - Create a 3rd statement line with a matching reference (e.g., "Test Ref 3") - Click the newly available automatic reconciliation button for this line Before the fix, checking the generated entry label shows the account name instead of "Test Ref 3" To check unfold the details, click on the pencil icon of a line opw-6246833 Forward-Port-Of: odoo/enterprise#119133
This change prevents upgrade failures for databases using the Italian reporting module. It removes outdated report definitions before the update runs, so existing customers can upgrade smoothly without hitting a duplicate label error.
Original PR description
Steps to reproduce: - Create a database with `l10n_it_reports` on a version before PR #264294 - Switch to current `17.0` - Upgrade module `l10n_it` - An error is raised Upgrading a database with `l10n_it_reports` installed raises an error if the database was created before that PR In that PR, we modified the formulas of several report expressions to use subformulas instead of simple aggregations. During upgrade, the ORM attempts to insert the updated expressions while the old ones still exist, violating the UNIQUE constraint on `(report_line_id, label)` in `account.report.expression` Only happens on upgrade, not on a fresh install. A migration script is added to delete the outdated expressions before the upgrade runs Ticket [link](https://www.odoo.com/odoo/project.task/6299385) opw-6299385 Forward-Port-Of: odoo/odoo#271320
This fix ensures that when multiple serial numbers or lots are scanned during manufacturing, every scanned value is kept and saved correctly instead of being overwritten by the last one. It also prevents validation errors and makes sure the finished product is recorded under the correct serial or lot during one barcode session.
Original PR description
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and…
Steps to reproduce ------------------ Serial-tracked finished product: 1. Create a serial-tracked finished product and an un-tracked component. 2. Create a Manufacturing Order with quantity 2 and confirm it. 3. Open the Barcode app, scan the MO, then scan a first serial number SN_X1. 4. Scan a second serial number SN_X2. 5. Validate. Lot-tracked finished product: 1. Create a lot-tracked finished product with a one-component BoM and an existing lot LOT_A. 2. Create a Manufacturing Order and confirm it. 3. Open the Barcode app, scan the MO, then scan the existing lot LOT_A. 4. Scan a different, not-yet-existing lot LOT_B. 5. Validate. Issue ----- Only the last scanned serial is registered on the MO, and validation then fails because the count of producing serials does not match qty_producing for a serial-tracked finished product. updateLine overwrote lot_producing_ids with [args.lot_id] on every scan, so the first serial was dropped when the second one was scanned, and the same branch never staged a freshly typed lot_name, so a brand-new serial typed on a serial-tracked MO was lost before reaching the backend. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L407 Two behaviours of the shared barcode dispatcher make a single accumulating branch insufficient. The final-product line must keep exposing a producing lot, otherwise the base hasUnassignedQty check counts a scanned serial as zero once a quantity is already set, leaving qty_producing stuck below the demand. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1446 But exposing a producing lot makes the dispatcher treat the next serial as a conflicting tracking number, since the base _canOverrideTrackingNumber considers a different lot name non-overridable. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L796-L798 So the scan is diverted to a new line through the override gate instead of updating the header line. https://github.com/odoo/enterprise/blob/f622064871bf55b93890606d16407c50cf4419a6/stock_barcode/static/src/models/barcode_model.js#L1585 For a lot-tracked finished product the producing lot can be corrected by scanning a different value, but the lot branch only stored a freshly typed value in lot_name and overwrote lot_producing_ids with the single existing lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L404-L407 The header reads its lot from lot_producing_ids whenever that relation is set and only falls back to lot_name when it is empty. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/components/header.js#L45-L58 The save path only promotes lot_name to a producing lot when lot_producing_ids is empty, so scanning an existing lot then a new one neither displayed nor recorded the new lot and the finished product was produced under the old lot. https://github.com/odoo/enterprise/blob/4a2f1da5466740b7758d1962e5241620845d616b/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L628 Solution -------- Accumulate scanned serials by appending to lot_producing_ids instead of replacing it, and stage a freshly typed lot_name as a new producing lot when the finished product is tracked by serial, so every serial reaches the backend. Keep the final-product line exposing the last producing lot so each scanned serial is still counted as one unit instead of resetting the quantity to zero once several serials are registered. Override _canOverrideTrackingNumber for the final-product line so a serial scan updates the header line rather than being diverted to a new line, which is the only valid path for the finished product since it is a single header line backed by the lot_producing_ids relation. Persist the producing serials with explicit x2many commands, separating already-existing lots from freshly typed ones, so both are written on the MO. Reject a serial that is already registered on the MO so the same number cannot be produced twice in one session. For a lot-tracked finished product, build a producing lot from the scanned value, using the existing lot or a freshly typed lot name, and store it in lot_producing_ids so the new lot is both displayed and persisted through the same x2many commands as the serial case. Leave the produced quantity unchanged when the scanned lot differs from the one already registered, since replacing the lot is a correction and not an extra unit, and keep incrementing it when the same lot is scanned again. opw-6189620 Forward-Port-Of: odoo/enterprise#116890
The default account codes used for cash discounts in the German SKR03 setup have been corrected. This helps ensure new company configurations use the proper accounting accounts from the start.
Original PR description
The default cash discout accounts referenced in the
German skr03 template used the wrong account codes.
The template has been updated with the right ones.
task-4915939
opw-4909059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271886
Forward-Port-Of: odoo/odoo#271024The default account settings used for cash discounts in the German SKR03 template were pointing to the wrong account codes. This update replaces them with the correct ones so accounting exports and related postings use the proper accounts.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
This update ensures grouped taxes are correctly included in Philippine generic tax report queries, even when the relevant tag is defined on a child tax. As a result, reported amounts are more accurate and tax lines are less likely to be missed in the report.
Original PR description
When using group taxes, the base invoice lines only store the parent tax in the `account_move_line_account_tax_rel` table. Because of this, if a child tax within the group contains a specific tax report tag, the generic report query would previously fail to pick up those base lines. This commit updates the SQL join conditions in `l10n_ph_generic_report.py` to also match `account_tax.id` against the child taxes of the linked parent tax using the `account_tax_filiation_rel` table. This ensures that base lines are correctly reported under the tags of their respective child taxes. Task-6278098 Forward-Port-Of: odoo/enterprise#121596
This update fixes cases where taxes without a fiscal position were being lost or hidden, especially for tax units and similar setups. It also keeps tax lines and totals in sync after fiscal position changes, reducing the risk of incorrect invoice balances.
Original PR description
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem…
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem map_tax drops every tax when the FP has no mapping, including the "All" ones that should pass through. action_open_related_taxes only lists the FP's tax_ids, so "All" taxes are invisible from the FP form. The Taxes stat button is hidden whenever the FP has no tax_ids. action_update_fpos_values invokes the field computes directly, so tax and balance lines fall out of sync after an FP change. Fix map_tax: when the FP has no tax_ids, return the input taxes whose fiscal_position_ids is empty (the "All" ones) instead of an empty recordset. action_open_related_taxes: extend the domain to also include taxes bound to no fiscal position. partner_view: drop the invisible="not tax_ids" guard on the Taxes stat button. action_update_fpos_values: route the deferred computes through _check_balanced and _sync_dynamic_lines so tax lines stay in sync after the update. task-id [6231514](https://www.odoo.com/odoo/project/967/tasks/6231514) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268273
This update corrects a test in the accounting reports area so it properly handles taxes that are not linked to any fiscal position. It ensures the test only checks that taxes tied to a fiscal position are removed, while unrelated taxes continue to pass through as expected.
Original PR description
map_tax on an empty fiscal position now preserves taxes with no fiscal_position_ids. Filter those out in test_tax_unit_auto_fiscal_position so the assertion only checks that taxes bound to a fiscal position are dropped by the unit FP. comunity PR: https://github.com/odoo/odoo/pull/268273 task-id 623151 Forward-Port-Of: odoo/enterprise#121525
Fixed an issue where the Time Spent cell could show the wrong color in Timesheets when an employee’s working schedule includes fractional hours, such as 8 hours 20 minutes. The update makes the status display reliable so users see the correct green, orange, or red indicator based on actual working time.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#121463We fixed an intermittent issue in chat-related tests where the window title could be missed during loading. This makes automated checks more stable and reduces the chance of false failures in messaging features.
Original PR description
The hoot `:text('X')` pseudo-class matches an element only when its whole inline text equals "X". `.o-mail-ChatWindow:text('slytherins')` therefore matched the chat window only during the brief frame where it showed nothing but its title, before the thread body (start message, composer) was rendered. Catching that frame is a race, so the assertion times out intermittently on runbot.
Assert against the title element itself: add a dedicated `o-mail-ChatWindow-name` class on it and match it with `.o-mail-ChatWindow-name:text('X')`. This is exact and no longer depends on the rest of the window being empty.
https://runbot.odoo.com/odoo/error/939914This change fixes a problem that could prevent PoS sessions from closing when the cash difference gain account has a default tax. Odoo now calculates the tax split correctly at creation time, so the closing entry stays valid and can be posted without error.
Original PR description
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session,…
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session, count more cash than expected at closing. 3. Try to close the session. -> Error message shows up "The journal entry reached an invalid state..." ... "The journal entry must always have exactly one journal item involving the bank/cash account" What's happening ---------------- PoS creates a bank statement line with the gain account as counterpart, resulting in 2 lines: cash +10, gain -10. Since the gain account has a default tax, `_sync_tax_lines` adds a tax line of -2.5 on top, which makes the move unbalanced by 2.5. Then `_sync_unbalanced_lines` adds a 4th line to fix it, on the line returned by `_get_automatic_balancing_account`, which is `journal.default_account_id`, i.e. the cash account itself for a cash journal. So we end up with 2 lines on that same cash account, which a bank statement line move doesn't allow -> Error. The fix ------- In `_post_statement_difference`, precompute the base and tax split ourselves and build the statement line's `line_ids` directly (e.g. for +10 and a 25% tax: cash +10, gain -8, tax -2). The move is balanced from creation, so `_sync_tax_lines` and `_sync_unbalanced_lines` don't have to touch it. Note that we force the tax computation to be in 'force_price_include' mode, as the counted cash difference is a gross amount (physical money in the drawer). This way the tax is always extracted from the cash amount, regardless of how the tax is configured (included or excluded in price). Same pattern is already used by `hr_expense` (cf `hr_expense.models.account_move_line._compute_totals`). opw-5972690 Forward-Port-Of: odoo/odoo#271921 Forward-Port-Of: odoo/odoo#257892
Receipt deadlines will now update correctly when an order line is cancelled or its quantity is set to zero. This prevents outdated cancelled items from keeping an old deadline on the picking, so the expected date shown to users stays accurate.
Original PR description
Steps to reproduce the bug:
- Create a Purchase Order with 2 products and confirm it
- Note the receipt's deadline (= date_planned of both lines)
- Set the quantity of one PO line to 0
- Update the scheduled date (date_planned) of the purchase order
Problem:
the receipt deadline does not update.
The receipt kept the old deadline from the cancelled move. When a PO line qty is set to 0, `_merge_moves` cancels the corresponding stock move via `_action_cancel`. Then `_update_move_date_deadline` correctly skips cancelled moves (filtered by `state not in ('done', 'cancel')`), so the cancelled move retains its original `date_deadline`. However, `_compute_date_deadline` on `stock.picking` used
`move_ids.filtered('date_deadline')`, which not checks move state, so the stale deadline of the cancelled move was included in the min/max computation.
opw-6292600
Forward-Port-Of: odoo/odoo#271890
Forward-Port-Of: odoo/odoo#270985When manufacturing orders are merged, any pending quality checks tied to the cancelled orders are now removed automatically. This keeps the quality view accurate and prevents cancelled orders from still showing unfinished checks or the Quality Checks button.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous fix introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: odoo-dev@db93bd2 This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L2480 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- opw-6260735 Forward-Port-Of: odoo/enterprise#121717 Forward-Port-Of: odoo/enterprise#119525
2 changes
Resolved issues and error corrections
The default cash discount account settings in the German SKR03 template were pointing to the wrong account codes. They have been corrected so German accounting exports and configurations use the proper accounts.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
The Timesheets grid now shows the correct status color for the total time spent, even when work schedules include fractional hours. This prevents rows from being marked orange or red incorrectly due to tiny calculation rounding differences, so users can trust the status indicator again.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#1214636 changes
Resolved issues and error corrections
Refreshing a tax report from the returns screen no longer sends users back to the kanban view or shows an error. The report now keeps track of the correct report context after refresh, so users can continue working without interruption.
Original PR description
Steps to reproduce: 1. Install `account_reports` and set fiscal year beginning date for Tax returns. 2. Open Tax Report from the button on Kanban view of account return. 3. Try to refresh from the…
Steps to reproduce: 1. Install `account_reports` and set fiscal year beginning date for Tax returns. 2. Open Tax Report from the button on Kanban view of account return. 3. Try to refresh from the report page. Without debug mode, it will return to returns kanban view and with debug mode, it will go back and a traceback will appear. Cause: The report from kanban view is opened via a python action method, which returns a `ir.actions.client` of `account_report`. In the controller for report, it tries to fetch the `report_id` from `context` [[1]] set during the python method call. But when we refresh page, this action context is wiped out, so when it tries to get the report options in controller via orm call [[2]], the report_id is lost, and it causes traceback. Solution: This commit tries to get the `report_id` from `action stack` which is prepared based on the url. so it fetches the correct report via ORM call. [1]: https://github.com/odoo/enterprise/blob/saas-18.3/account_reports/static/src/components/account_report/controller.js#L23 [2]: https://github.com/odoo/enterprise/blob/saas-18.3/account_reports/static/src/components/account_report/controller.js#L167 task-6240800
This update corrects a Belgian VAT number used in an automated test so it matches the current validation rules. It keeps the test objective the same while preventing failures caused by a stricter external validation library.
Original PR description
This commit fixes a Belgian VAT validation check in `test_import_partner_retrieval_bank_account_number` as the provided vat number isn't a valid one. It keeps the spirit of the test by still having vat number mismatch, but with a valid value. The python-stdnum library used for this validation added a stricter check since version 2.2, which is used in Ubuntu Resolute 26.04. References: - https://github.com/arthurdejong/python-stdnum/commit/7ca9b6ce7b1f2b4d1bf164c2af83a8a77bc919d2 runbot-939796 Forward-Port-Of: odoo/odoo#272082
This change prevents upgrades of the Italian local accounting package from failing when older databases are updated. It removes outdated report definitions before the upgrade runs, so businesses can move to the newer version without hitting an install error.
Original PR description
Steps to reproduce: - Create a database with `l10n_it_reports` on a version before PR #264294 - Switch to current `17.0` - Upgrade module `l10n_it` - An error is raised Upgrading a database with `l10n_it_reports` installed raises an error if the database was created before that PR In that PR, we modified the formulas of several report expressions to use subformulas instead of simple aggregations. During upgrade, the ORM attempts to insert the updated expressions while the old ones still exist, violating the UNIQUE constraint on `(report_line_id, label)` in `account.report.expression` Only happens on upgrade, not on a fresh install. A migration script is added to delete the outdated expressions before the upgrade runs Ticket [link](https://www.odoo.com/odoo/project.task/6299385) opw-6299385 Forward-Port-Of: odoo/odoo#271320
This change stops private tasks from being selected as the parent of other tasks. It helps preserve task visibility rules and avoids accidental links that could expose private work in project hierarchies.
Original PR description
In this commit, we ensure that private tasks can never be selected as parent tasks. task-5119141 Forward-Port-Of: odoo/odoo#271896 Forward-Port-Of: odoo/odoo#270795
This change gives the desktop test suite more time to complete, reducing occasional failures in nightly builds. It helps keep automated testing reliable as the number of tests grows.
Original PR description
The test_unit_desktop suite sometimes timeouts, especially in nightly builds. There's nothing alarming in those timeouts, that are most certainly due to an increasing number of tests. We thus increase the timeout to 45 minutes (note: in 19, it's 60 minutes). Runbot error~243569 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects the color shown for the Time Spent cell in Timesheets when an employee has a work schedule with fractional hours. It prevents harmless rounding differences from making a normal timesheet look like it has overtime or a shortage.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#1214632 changes
Resolved issues and error corrections
This change corrects the color shown in the Time Spent cell when an employee’s schedule includes fractional hours. It prevents valid timesheets from being flagged with the wrong status because of tiny rounding differences.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#121463The GSTR-1 export now converts SEZ invoices issued in a foreign currency to the company’s currency, INR, for the “Invoice Value” column. This ensures the spreadsheet matches the required reporting currency and avoids incorrect values being submitted in USD or other foreign currencies.
Original PR description
Currently, when generatign GSTR-1 return spreadshee, SEZ invoices issued in a foreign currency are exported with their totals in the foreign currency rather than the company currency (INR) Steps to reproduce: - Create a B2B SEZ invoice in foreign currency - Go to Accounting > Reporting > [India] GST Return periods - Generate the GSTR-1 report for the period Issue: In the resulting spreadsheet, the "Invoice Value" column takes the invoice total in USD rather then INR opw-6292913 Forward-Port-Of: odoo/enterprise#121663 Forward-Port-Of: odoo/enterprise#121157
3 changes
Resolved issues and error corrections
This change stops the planning process from trying to auto-plan or send schedules when no start or end dates have been set. It helps avoid unexpected errors and makes the planning workflow more reliable for users.
Original PR description
Add a guarding condition to the auto-plan or send behavior to avoid doing those operations when no start/end dates are defined --- Task: 6312650
This update fixes a cleanup problem in Studio tests that could leave behind test data in the system. As a result, customer records and user-related processes are less likely to run into unexpected errors during background checks or computed updates.
Original PR description
This bug occurs whenever a computed field or onchange tries to interact with the res.users or res.partner, where it then tries to fetch the res_partner.x_studio_test_tracking and it does not exist.
When a customer’s information is refreshed from the Colombian government service, the updated legal name and email are now also reflected in Point of Sale right away. This avoids showing a temporary name in POS and ensures staff see the correct customer details immediately after the refresh.
Original PR description
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh…
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh icon` is visible: click on it. Observation: - the dialog is closed and partner is selected with "temp" name Expected: - with valid government credentials and a valid identification number, the refresh action should also update the partner data on the POS side Cause: - the refresh button triggers the `button_l10n_co_dian_refresh_data` action, which fetches the legal name and email from the government service - although the backend record is correctly updated, the new values are not immediately synchronized with the POS - when the refresh button is clicked, editPartner() first triggers `web_save` using the temporary "temp" name and immediately reads the partner data afterward - the refresh action executes later and updates the contact with the fetched legal information, but the POS is not aware of these subsequent changes Fix: - read the data again if there is any update caused by this action. - this is done by overriding `afterExecuteActionButton` of FormController class opw-6198035 Forward-Port-Of: odoo/enterprise#117527
10 changes
Resolved issues and error corrections
This update adjusts an automated accounting test so it only expects taxes linked to a fiscal position to be removed by the unit fiscal position. Taxes that are not tied to any fiscal position are now correctly preserved, making the test reflect the intended behavior more accurately.
Original PR description
map_tax on an empty fiscal position now preserves taxes with no fiscal_position_ids. Filter those out in test_tax_unit_auto_fiscal_position so the assertion only checks that taxes bound to a fiscal position are dropped by the unit FP. comunity PR: https://github.com/odoo/odoo/pull/268273 task-id 623151
The Shop Floor view now correctly sorts manufacturing orders with unplanned work orders after those that are already planned. This brings the Shop Floor ordering in line with the rest of Manufacturing, making it easier to focus on the work that is ready to be executed.
Original PR description
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will…
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will update the sorting logic in the MrpDisplay component to more gracefully handle falsy date_start values, sorting them to the end. ## Steps to reproduce (runbot 19) 1. Create 2 MOs with an operation (work order) involving a work center, we'll call them A and B. 2. Open Shop Floor and open the work center that the MOs' work orders belong to, and note they are ordered A, B (this is fine, neither are planned so the precedence falls back to id 3. Go back to MO B and plan it. This should give it precedence in Shop Floor 4. Under the work center in Shop Floor, note that the MOs are still ordered A, B, despite B's work order having a start date and A's work order not having one To further motivate this being unintended, you can go to Manufacturing > Operations > Work Orders, and you'll see MO B's work order sitting at the top of the list. opw-6303323
This fix ensures invoice lines are properly included in tax reports when grouped taxes are used. It now recognizes the relevant child tax tags, so report totals are more accurate and no longer miss lines tied to those taxes.
Original PR description
When using group taxes, the base invoice lines only store the parent tax in the `account_move_line_account_tax_rel` table. Because of this, if a child tax within the group contains a specific tax report tag, the generic report query would previously fail to pick up those base lines. This commit updates the SQL join conditions in `l10n_ph_generic_report.py` to also match `account_tax.id` against the child taxes of the linked parent tax using the `account_tax_filiation_rel` table. This ensures that base lines are correctly reported under the tags of their respective child taxes. Task-6278098
Fixed an issue where partner mapping could be applied automatically on bank statements even when the reconciliation rule was still set to manual. This makes statement handling more consistent and ensures only the right reconciliation rules are suggested to users.
Original PR description
Users may define a reconciliation model for partner mapping by having a matching label and a counterpart item setting only the partner. If the user then opens the transactions or reconciliation menu and creates a statement, partner mapping will occur automatically, even if the model is still set to 'manual'. Steps to reproduce: - Create a reconciliation model with - Label: Contains 'mylabel' - Counterpart Items: set any partner - Open accounting app - From a Bank journal card click 'Transactions' - Create a statement line containing 'mylabel' Issue: Partner will be automatically set according to the reconciliation model, even if it has not been set to 'Automatic'. opw-5480282
This update makes the UNSPSC code 10171500, “Organic fertilizers and plant nutrients,” available again in product accounting. It ensures users can find and use the correct classification code when managing products.
Original PR description
The code 10171500 - Organic fertilizers and plant nutrients wasn't appearing. In the file that has the unspsc product codes this one is set to False. Steps to reproduce: - Activate module product_unspsc. - Go to product > accounting. - Verify that this code is not listed. Ticket [link](https://www.odoo.com/odoo/project.task/4461974) opw-4461974
This update ensures DIAN email templates in the Colombian localization are translated correctly when a new language is installed. It prevents untranslated invoice and credit note emails for users who add languages after the localization is already in place.
Original PR description
### Issue: When installing a new language on a database with `l10n_co_dian`, the DIAN email templates are not translated Languages already installed when `l10n_co_dian` is installed are correctly…
### Issue: When installing a new language on a database with `l10n_co_dian`, the DIAN email templates are not translated Languages already installed when `l10n_co_dian` is installed are correctly translated, as the copy happens at that moment Only languages installed afterwards are affected ### Cause: The DIAN email templates are created dynamically via `_create_dian_mail_templates` as copies of the `account` templates Because they are created at runtime, no translations exist for their XML IDs in the `l10n_co_dian` `.po` files The `TranslationImporter` finds nothing to import for them The fix hooks into `_load_module_terms` to sync translations from the source `account` templates to the DIAN ones whenever a new language is installed `TranslationImporter.save()` is used without `force_overwrite`, so existing translations on `noupdate` records are never replaced This is the standard way to push translations while preserving any manually modified values ### Notes: Languages installed before this fix are not updated Only newly installed languages will get the synced translations ### Steps to reproduce: - Install `l10n_co_dian` - Enable Developer Mode in Settings - Install any language (e.g. `fr_FR`) - Go in Settings > Technical > Email > Email Templates - Search for DIAN and open Invoice or Credit Note Before the fix, the DIAN invoice and credit note templates had untranslated name, description and body_html opw-6269979
This change fixes a test in the salary configuration flow by ensuring the employee’s private address is available when the test runs. It helps keep the test suite reliable and prevents false failures unrelated to the actual salary configuration behavior.
Original PR description
Task-6329628
This update fixes several issues in the website rental flow tests so they run consistently. It ensures payment setup is only prepared when the needed demo data exists, allows rental scenarios that include weekends, and narrows the shop page search so the right product is found reliably.
Original PR description
## [FIX] website_sale_renting_planning: prepare payment if demo is installed Before this commit, the demo `payment.provider` for the tests was being created in `setUpClass` this caused an issue…
## [FIX] website_sale_renting_planning: prepare payment if demo is installed Before this commit, the demo `payment.provider` for the tests was being created in `setUpClass` this caused an issue because `payment_demo` is not a dependency of this module, therefore it may not be installed while these tests are running and cause the tests to error at setup. After this commit, the `payment.provider` creation was moved into the tests after the check for `payment_demo` installation, ensuring that `payment_demo` would exist when a `payment.provider` is prepared. https://runbot.odoo.com/odoo/runbot.build.error/940273 ## [FIX] website_sale_renting_planning: unforbid weekend in tests Before this commit, the company had `renting_forbidden_sat` and `renting_forbidden_sun` enabled which made it not possible to rent products from website if the rental date included a saturday or sunday. This commit fixes that but setting `renting_forbidden_sat` and `renting_forbidden_sun` to False and allowing rental on all days of the week. https://runbot.odoo.com/odoo/runbot.build.error/940312 ## [FIX] website_sale_renting_planning: search for product in shop page Before this commit, the website `/shop` page would display all published products in the db, this could cause the `website_sale_renting_planning_buy_product` tour to fail if the setup product is not in the first page. After this commit, the `/shop` page is now access with a search on the product to ensure there won't be other products in the first page. https://runbot.odoo.com/odoo/runbot.build.error/940275
The default cash discount account codes in the German SKR03 template were incorrect and have been updated. This helps ensure accounting exports and postings use the right accounts, reducing the risk of reporting errors.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
The Timesheets grid now shows the correct status color for a row even when an employee’s work schedule includes fractional hours. This prevents misleading orange or red indicators caused by tiny rounding differences, so users can trust the visual status shown for completed time entries.
Original PR description
## Issue In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color…
## Issue
In the Timesheets app, the color of the *Time Spent* cell at the end of a row indicates the current status of the timesheets based on the expected number of working hours. The selected color (green/orange/red) is sometimes wrong when an employee has a work schedule with fractional hours.
## Steps to reproduce
1. Install *Timesheets* (`timesheet_grid`)
2. For an employee E, edit the *Standard 40 hours/week* schedule:
- Change *Monday Afternoon* "Work to" column from 17:00 to 17:20.
3. In Timesheets > All Timesheets, go back one week and fill the timesheet for the employee E. We need 8 hours everyday but on Monday, where we need 8 hours and 20 minutes.
4. __The background of the *Time Spent* cell is orange, even though there's no overtime anywhere, and the value in the cell is precisely 40:20, which is the expected amount of hours worked.__
## Cause
When comparing the amount of hours worked and the expected amount of hours, small rounding errors occur. At this point of the execution:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L157
We obtain the following values:
```js
> monday = section.cells[1]
> monday.value
8.333333333333336
> workingHours[monday.column.value]
8.333333333333332
> monday.value - workingHours[monday.column.value]
3.552713678800501e-15
```
This small difference differing from 0, the wrong color is selected by `_getSectionTotalCellBgColor`:
https://github.com/odoo/enterprise/blob/19b7f5a6961dbce7367c07fcc55eea1925832634/timesheet_grid/static/src/views/timesheet_grid/timesheet_grid_renderer.js#L160-L172
## Fix
The same issue was fixed elsewhere by https://github.com/odoo/enterprise/commit/3340c0610ae6d7d3087f20da04309512771cc4b7. The same fix is applied here for consistency.
opw-6193181
Forward-Port-Of: odoo/enterprise#1214638 changes
Resolved issues and error corrections
This change fixes a visibility issue in Field Service where customers created under a parent company could not be selected when working from one of its branches. It now correctly recognizes the parent company relationship, so users can choose the expected customer record and continue their work without interruption.
Original PR description
**Steps to Reproduce:** 1. Create a branch under an existing company. 2. Create a contact in company (so the contact is visible only to the company). 3. Switch to the branch of the company. 4. Open Field Service and create a new record. 5. In the *Customer* field, try to select the contact created earlier. **Issue:** The contact created under the company is not selectable in the *Customer* field in Field Service. **Current behaviour:** The same contact is visible in the Contacts app, and also selectable in Sales Order — but not in the Field Service. **Expected behaviour:** The contact created under the company should be selectable as a customer in Field Service when the current user is operating from that branch. **Fix:** Modified the condition of python constrains to check parent company also. **Task-5114444**
This fix makes sure recurring products cannot be added to a sales order without a subscription plan, whether they are added manually or through the product catalog. It prevents inconsistent behavior and avoids orders being saved in an invalid state.
Original PR description
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product >…
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product > Save SO > Observe the User Error 4. Now add the same recurring product through Catalog View Observation: --------------------------------------- No User Error raised stating 'You cannot save a sale order with recurring product and no subscription plan.' Issue: --------------------------------------- When you manually add a line and click 'Save', the constraint (`_constraint_subscription_plan`) is triggered and raised `UserError` https://github.com/odoo/enterprise/blob/434d88960abb5e424fdc1106fc93935d328bff78/sale_subscription/models/sale_order.py#L176-L177 When you add a product via the catalog view, it calls `_update_order_line_info` which directly creates/updates order lines, Which do not trigger the python constraint. https://github.com/odoo/odoo/blob/ef9772bba1515bdaf5410c3af5a3e395f562d513/addons/sale/models/sale_order.py#L1926-L1933 Solution: --------------------------------------- Two private helpers are introduced: * `_is_exempt_from_subscription_plan_check`: single source of truth for all exempt states (draft, cancelled, upsell, and legacy upgrade orders). * `_check_recurring_plan_mismatch`: raises a `UserError` when the order has or will have a recurring product but no subscription plan, reusing the exemption helper so both call sites stay in sync. `_constraint_subscription_plan` is refactored to delegate to these helpers, and `_update_order_line_info` is overridden to call `_check_recurring_plan_mismatch` before the catalog update is applied, ensuring consistent validation across both entry points. opw-6194865 Forward-Port-Of: odoo/enterprise#117879
This change prevents an error that could happen when upgrading databases using the Italian accounting reports. It cleans up outdated report entries before the upgrade runs, so the update completes successfully without duplicate-label conflicts.
Original PR description
Steps to reproduce: - Create a database with `l10n_it_reports` on a version before PR #264294 - Switch to current `17.0` - Upgrade module `l10n_it` - An error is raised Upgrading a database with `l10n_it_reports` installed raises an error if the database was created before that PR In that PR, we modified the formulas of several report expressions to use subformulas instead of simple aggregations. During upgrade, the ORM attempts to insert the updated expressions while the old ones still exist, violating the UNIQUE constraint on `(report_line_id, label)` in `account.report.expression` Only happens on upgrade, not on a fresh install. A migration script is added to delete the outdated expressions before the upgrade runs Ticket [link](https://www.odoo.com/odoo/project.task/6299385) opw-6299385 Forward-Port-Of: odoo/odoo#271320
This update corrects how the Intrastat report handles companies without a country set. It prevents the report query from failing, so users can generate the report reliably in that configuration.
Original PR description
When there is no `country_id` on the company we get `False`. The generated query then fail at: ``` ... CASE WHEN (code.country_id IS NULL OR code.country_id = false) THEN code.code ELSE NULL END AS commodity_code, ... ``` with: ``` ERROR: operator does not exist: integer = boolean LINE 12: ... WHEN (code.country_id IS NULL OR code.country_id = false) T... ``` Forward-Port-Of: odoo/enterprise#121608
This change prevents a contact list from failing to open when users work across multiple companies. It ensures meeting information is calculated only from records the user is allowed to see, so browsing contacts remains smooth and access-safe.
Original PR description
### Steps to reproduce: - Download Calendar and Contacts app - Go to the Setting -> Companies -> Manage companies; make sure there are at least two companies - Go to the Setting -> Users -> Manage…
### Steps to reproduce: - Download Calendar and Contacts app - Go to the Setting -> Companies -> Manage companies; make sure there are at least two companies - Go to the Setting -> Users -> Manage users; make sure the current logged-in user has access to both companies - Create a another user who also have access to both companies - Search for the new user in contacts -> Assign the current company to the contact -> Through the internal link of the company, go to sales and purchase tab -> assign the same company in the company field - Switch the company of the logged in user to the other company - Open the test contact form, use the meeting smart button and create a new meeting - Open the kanban contact view **> Access Error: Uh-oh! Looks like you have stumbled upon some top-secret records.** ### Cause of Issue: When trying to view the search results in kanban view, the `meeting_count` is calculated for each contact. Hence,`_compute_meeting_count()` is called which calls `_compute_meeting()`. https://github.com/odoo/odoo/blob/f39785bcddd1eb5b7fb503d053c9bb66e2a0f15c/addons/calendar/models/res_partner.py#L49-L54 Since the above section tries to access `partner.parent_id` each loop, it reaches a `parent_id` that's not accessible for the current user. ### Fix: Since we need to access `parent_id` to be able to calculate meeting count for the full tree of partners, `sudo()` is used to get all partners, but meetings are computed for ancestors who are in `self_ids` only so that we still remain within scope. Same old logic is used to propagate meetings for every ancestor, but dictionary lookups are used to enhance performance. opw-5874204
This update corrects the email verification banner on public forum profiles so it uses the logged-in account instead of the profile being viewed. As a result, users no longer see another person's private email address in the confirmation message.
Original PR description
**Steps to reproduce:**
- Install website_forum module
- Create a new portal user and log in with it
- Go to the website forum to see that the account requires email verification
- Send the verification email to see the green banner ('an email was sent to XX')
- Add XP (karma) points to this user as admin (User > Smart actions > Karma)
- Switch back to the portal account
- Check any public user profile on the forum (`/profile/user/2?forum_id=2`)
- Green banner now displays the private email of the user you're checking
**Issue:**
On the `email_validation_banner` the user field is used for the validation
data, but it is overridden by `_prepare_user_profile_values` which is
setting the current page user.
**Fix:**
Properly set `user` to `env.user` in the template.
opw-6276809Neutralized databases will now use the test VIES endpoint instead of the live production service when no demo data is present. This reduces the risk of sending checks to the real external service during testing or database neutralization, while leaving any custom endpoint settings unchanged.
Original PR description
Neutralized databases don't always have demo data, so they talk to production VIES endpoint. With this change, the production endpoint is replaced with the test one. If some database has a custom endpoint, nothing is done. @moduon MT-15142 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures that invoices only keep the delivery notes that match the quantity actually invoiced. It prevents extra delivery references from appearing on partial invoices, which avoids inconsistencies in the exported accounting documents.
Original PR description
### Issue: When invoicing partial quantities from a sale order, more DDTs than necessary are linked to the invoice Since `l10n_it_ddt_ids` is computed and not stored, the incorrect links persist…
### Issue: When invoicing partial quantities from a sale order, more DDTs than necessary are linked to the invoice Since `l10n_it_ddt_ids` is computed and not stored, the incorrect links persist until the remaining quantities are invoiced, at which point the extra DDTs are moved to the new invoice This creates inconsistencies in the generated XML, which references DDTs not actually covered by the invoice ### Cause: The quantity allocation loop only checked whether there was remaining `move_qty` to consume, but never checked whether the invoiced quantity (`inv[0]`) had already been fully consumed As a result, once all invoiced quantity was allocated, the loop kept iterating and linking additional DDTs from the sale order ### Steps to reproduce: - Install `l10n_it_stock_ddt` with demo data - Switch to the IT company - Create a Warehouse - Create a Product (Invoicing Policy: Delivered Quantities) - Create and confirm a Sale Order (qty: 5) for that product - Validate 3 partial deliveries of qty 1, creating a backorder each time - Create the invoice, set the quantity to 2 and confirm Before the fix, 3 DDTs were linked instead of 2 opw-6294035
2 changes
Resolved issues and error corrections
This update prevents a failure when installing the Repair app in certain database setups. It ensures the module can be installed cleanly without depending on data that may not be available during automated setup, improving reliability for runbot and test environments.
Original PR description
Runbot builds on version 17.0 and 18.0 fail due to the lines below. These lines reference `move.sale_line_id` as the previous dependencies did not add `sale_line_id` to the `stock.move` model when using --skip-auto-install. https://github.com/odoo/odoo/blob/51824f462402d3d141bda2717402d1fdcf2e118b/addons/repair/models/stock_move.py#L97-L100 To reproduced the issue: 1. New blank database 2. ./odoo-bin -d [database-name] -i repair --skip-auto-install 3. See error in console Looking ahead to verison 18.1+ we see the dependencies change here: https://github.com/odoo/odoo/commit/f7dbdec11b74f8c7d969763d8c5cf09542a47f86 **Affects 17.0 and 18.0** Ticket [link](https://www.odoo.com/odoo/project/27948/tasks/6306099) This can also close this very, very old PR https://github.com/odoo/odoo/pull/189584
This change fixes an issue where creating a repair order could fail if the Sales Stock module had been removed after installing Repairs. By declaring the missing dependency explicitly, the Repair app now keeps the required functionality available and avoids unexpected errors for users.
Original PR description
Before this commit: =============== When we install repair and then manually uninstall the `sale_stock` and creating a repair order will throw trackback. Steps to produce: ============== 1. Install the repair module 2. uninstall the sale_stock module (it is not a direct dependency module it is a transitive dependency module) 3. Then try to create a new repair order with a product we get the following traceback After this commit: ============== Add `sale_stock` in dependency of repair instead of only stock Reference feedback task : https://www.odoo.com/odoo/project.task/4378246 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr