Daily updates from Odoo
Friday, June 12, 2026
346 changes
17 changes
Enhancements to existing features
This update automatically refreshes KYC status information for French PDP users by receiving notifications from IAP. Previously, users had to manually update this status. This change streamlines the process and ensures accurate, real-time data.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596 Forward-Port-Of: odoo/odoo#268528
Resolved issues and error corrections
This update fixes a previous issue where sales employees transitioning to non-commission roles incorrectly accrued commission losses for public holidays and sick time. Now, employees in non-sales positions will no longer be impacted by these incorrect commission calculations, ensuring accurate payroll processing. This improves the reliability of the HR payroll module.
Original PR description
If a salesman moves to another job that doesn't pay commission, he shouldn't have loss on commissions for public holidays and sick time off. Forward-Port-Of: odoo/enterprise#120386
This update resolves a technical issue that caused tracebacks in Point of Sale (PoS) when testing LNA with IoT printer configurations. The fix ensures the IP field is properly defined, preventing errors and improving PoS stability. This addresses a known problem impacting printer connectivity.
Original PR description
When testing LNA using the LNA button in the navbar, if the printer configured is of type IoT, the IP field is undefined, and the PoS displays a traceback. We added a guard to return `false` when the IP is not defined. see odoo/enterprise#120273
This update ensures the LNA button in the POS interface correctly tests functionality for IoT Boxes. Previously, the button wasn't properly verifying LNA status, now a status action is sent when LNA is enabled, ensuring accurate IoT Box operation.
Original PR description
The LNA button in the POS navbar wasn't testing LNA for IoT Boxes. We now send a status action for IoT Boxes with LNA enabled. Forward-Port-Of: odoo/enterprise#119998
This update fixes an issue where barcode scanning incorrectly displayed and managed sale order quantities. The root cause was a flaw in how the system selected delivery lines, leading to inaccurate fulfillment. The fix ensures correct quantity updates when using barcode lots, preventing backorders and ensuring accurate order fulfillment.
Original PR description
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities. ## Steps to replicate: - Install Sales and Barcode (no demo data). - Enable Lots & Serial…
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities.
## Steps to replicate:
- Install Sales and Barcode (no demo data).
- Enable Lots & Serial Numbers in settings.
- Create Test Product with Tracking by Lots.
- Go to Inventory > Products>Lots & Serial Numbers and create 3 lots for the product.
- Update each lot’s on-hand quantity to 10 from the product page.
- Create and confirm a Sales Order for the product (lines: qty 3 and 2 units).
- Open the delivery in the Barcode app:
- Scan lot 2 > increase qty to 3 using +1 button
- Scan lot 3 > increase qty to 2 using +1 button
- Validate and go to the sale order.
## Observed Behavior:
The sale order delivered quantities are flipped and a backorder is created even though the quantity for the product is satisfied.
## Root cause:
The issue occurs because when a sales order is confirmed, the system defaults to
using lot 1 on the delivery receipt. When a user scans lot 2, the `_processBarcode` function is triggered, which calls `_findLine` at [1] to select the appropriate line on the receipt.
As the loop in `_findLine` iterates through `pageLines` with values like:
```
[{display_name: "Test product", quantity: 3, lot_id: { name: 'lot1' }},
{display_name: "Test product", quantity: 2, lot_id: { name: 'lot1' }}]
```
During the first iteration, `foundLine` is set at [2] for the line with quantity 3 . Since the subsequent if condition is not satisfied, the loop hits the continue block at [3].
On the next iteration, the line with quantity 2 causes `foundLine` to be overwritten at [2], and the continue block is executed again at [3].
This results in the line with quantity 2 being selected as the line to update at the end of the function.
When the user manually increases the quantity to 3, the line that originally required quantity 2 is updated and fulfilled.
Later, when lot 3 is scanned, the line that required quantity 3 is selected for update, and manually increasing the quantity to 2 before validating the order leads to a backorder and causes the delivered quantities to be flipped.
[1]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1335-L1337 [2]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1690-L1699 [3]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1727-L1729
## Solution:
Avoid grouping lines from different moves unless using batch transfers. This ensures that backorders are not created when the barcode lines are fulfilled.
opw-5423943
Forward-Port-Of: odoo/enterprise#120098
Forward-Port-Of: odoo/enterprise#109032This update corrects a bug where timesheets were incorrectly added to invoices after a partial refund was issued. The fix ensures that timesheets associated with fully invoiced orders are no longer re-added during invoice generation, preventing duplicate invoicing and maintaining accurate financial records. This improves the reliability of the invoicing process.
Original PR description
### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create 2 lines for the services product in the SO, invoicing policy = based on timesheets - Create 2 timesheets for both SO items - Invoice the SO - Create a credit note for line 1 => only line 2 is invoiced and line 1 is now released - Back to the SO > create invoice again > Line 2 is added to the invoice again. ### Cause of Issue: When generating the new invoice, `_recompute_qty_to_invoice` identifies timesheets linked to refunded invoices. Because the original invoice was partially refunded, all timesheets attached to that invoice match the domain used to locate timesheets—even the timesheets for line 2, which wasn't refunded. ### Fix: Ensures that lines that have already been completely invoiced are safely ignored and not inadvertently re-added to subsequent invoices. opw-6217684 Forward-Port-Of: odoo/odoo#268972 Forward-Port-Of: odoo/odoo#265840
This update resolves an error that occurred when downloading the asset template in the Fixed Assets section. Previously, the system incorrectly checked for an account code, causing a technical error. Now, the system uses the asset account's display name, ensuring a smooth download process regardless of the account code's presence.
Original PR description
Currently, an error occurs when downloading the asset template. **Steps to Reproduce:** - Install the `account_asset` module without demo data. - Go to `Accounting` > `Configuration` > `Accounting` >…
Currently, an error occurs when downloading the asset template. **Steps to Reproduce:** - Install the `account_asset` module without demo data. - Go to `Accounting` > `Configuration` > `Accounting` > `Chart of Accounts`. - Open the `Fixed Assets` account, set a `Depreciation` value, and remove the `account code`. - Go to `Accounting` > `Accounting` > `Assets & Liabilities` > `Assets`. - Click `With our template` on the screen. `TypeError: startswith first arg must be str or a tuple of str, not bool` After this [recent commit], account codes became optional and can be removed. As a result, when the code is removed from the Fixed Assets account and when donloading the asset template, the system checks whether the account name starts with the account code [1]. Since the account code is `False`, it raises an error. This commit ensures that the check is only performed when the account code exists; otherwise, the account name is used directly for the asset account. [recent commit]: https://github.com/odoo/odoo/commit/c3313b336b9f1305c363097745926f2bdf61e277 [1]- https://github.com/odoo/enterprise/blob/421fce171dc158faa3b13406b6cea5c1c907ee49/account_asset/controller/asset_template_controller.py#L46-L49 sentry-7487406857
This update now limits the employees assigned to work orders based on the workcenter's configuration. Previously, all employees could be assigned, but now only employees specifically authorized for that workcenter are selectable. This improves accuracy and control over work order assignments.
Original PR description
Add domain on `employee_assigned_ids` to restrict selectable employees based on the workcenter configuration. If `all_employees_allowed` is True, no filter is applied. Otherwise, only employees listed in `allowed_employees` are selectable. opw-6208602 Forward-Port-Of: odoo/enterprise#117876
This update fixes an issue where currency differences were incorrectly aggregated in hierarchical financial reports. Previously, the system was combining figures from different currencies, leading to inaccurate totals. This change ensures that reports accurately reflect the value of transactions in their original currency, improving reporting reliability.
Original PR description
opw-6015098 Forward-Port-Of: odoo/enterprise#119311 Forward-Port-Of: odoo/enterprise#114827
This update prevents the 'Project: Task Rating Request' email template from disappearing when project stages are set to inactive. Previously, disabling ratings on the last stage would remove the template option, causing a frustrating user experience. This fix ensures the template remains available for selection, streamlining the rating process.
Original PR description
Currently, when the `rating_active` feature is disabled on the last project stage using it, the default 'Project: Task Rating Request' email template is automatically archived. This creates a UX issue where the template disappears from the "Rating Email Template" dropdown on the stage form, preventing users from selecting it. This commit resolves the issue by: - Setting `active="True"` by default on the XML template record. - Removing the background archiving logic from the `write` method of `project.task.type`. - Appending a check to `test_send_rating_review` to ensure the template remains active even when all stages in the database have ratings disabled. Task-6102227 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264394
This update resolves an issue where canceling a Global Invoice on a Mexican POS order prevented the creation of a new Global Invoice for the same order. The fix ensures that the refund process correctly updates CFDI documents, allowing users to generate new invoices after a refund is processed. This improves the functionality of the Mexican POS integration.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120349 Forward-Port-Of: odoo/enterprise#117211
This update resolves an issue where the `google_address_autocomplete` widget remained editable even when set to read-only mode. The fix ensures the widget correctly displays the field's value when in read-only mode, improving usability and data consistency.
Original PR description
**Issue:** The `google_address_autocomplete` widget remained editable even when the view or field was set to `readonly`. **Solution:** Modified the `AddressAutoCompleteTemplate` to conditionally render the component. If `props.readonly` is true, the template now renders a `<span>` with the field value. Task~5182770 Forward-Port-Of: odoo/odoo#268109 Forward-Port-Of: odoo/odoo#260952
This update ensures Polish company invoices sent to KSeF (a Polish tax system) correctly include a required field ('PrefiksPodatnika') in the FA(3) XML format. This is necessary for legal compliance with Polish tax regulations for common EU transactions like intra-Community sales and triangular sales, ensuring accurate reporting to the tax authorities.
Original PR description
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed…
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed in the buyer's EU country) or Triangular Sale. 3. Send the invoice to KSeF and download the generated FA(3) XML. Issue The Podmiot1 (seller) block in the rendered FA(3) XML omits the PrefiksPodatnika element, see https://github.com/odoo/odoo/blob/89219a843545d8bb0cad6ea806a1167cee6289da/addons/l10n_pl_edi/data/fa3_template.xml#L34-L42. According to the official Ministry of Finance documentation (https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf, page 11), this conditional field must carry the value "PL" when the invoice documents: - the intra-Community supply of goods, - the provision of services referred to in Article 100 sec. 1 item 1 of the Act for EU VAT taxpayers, - the supply carried out under a simplified triangular transaction by the second taxpayer (Article 135 sec. 1 item 4 (b) and (c)). The XSD marks the element as optional (minOccurs="0", fixed="PL") so KSeF accepts the XML, but the seller's tax reporting is still legally non-compliant for the three cases above, and the field is missing from the KSeF PDF viewer rendering. opw-6213178 Forward-Port-Of: odoo/odoo#264659
This update resolves an issue where the builder sidebar incorrectly displayed "Block" for website snippets. The fix ensures that snippet titles are accurately shown in the builder, improving usability and allowing users to easily manage their page content. This was caused by a change in the plugin's setup process.
Original PR description
\* = website ### Issue: When a page is created either through the configurator or from an existing page template, block-level snippets do not display the correct title in the builder sidebar.…
\* = website
### Issue:
When a page is created either through the configurator or from an
existing page template, block-level snippets do not display the correct
title in the builder sidebar. Instead, "Block" is shown for all
snippets.
### Steps to Reproduce:
- **Configurator:**
1. Install the website module or create a new website from Settings.
2. Complete all configurator steps. Do not use "Skip and start from
scratch".
- **Page template:**
1. Open the website and click the "New" button in the systray.
2. Click on "Page" and choose any template other than a blank page.
### Observed behavior:
The builder sidebar shows "Block" in the option container for all
snippets instead of their actual names.
### Reason:
Previously, just before the builder was opened, the `data-name`
attribute was injected through `_computeSnippetTemplates()` for any
snippet that did not already have it. This behavior was lost after the
plugin refactoring.
### Fix:
As before, we now inject the `data-name` attribute during builder setup
for snippets that do not already have it.
task-[6087348](https://www.odoo.com/odoo/all-tasks/6087348)
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269287
Forward-Port-Of: odoo/odoo#259893This update ensures accurate calculation of variable double holiday pay for employees in Belgium. Previously, the system wasn't properly prorating holiday pay based on legal leave entitlements, leading to potential payment discrepancies. This fix corrects this issue, ensuring compliance and accurate payroll processing.
Original PR description
If you have a double holiday attest, we need to prorate the amount based on legal leave rights. The proration with regards to the previous work time rate wasn't done. Forward-Port-Of: odoo/enterprise#120403
This update fixes an issue where images in email marketing templates were stretched and distorted when paired with long text. By removing specific styling, images now maintain their natural aspect ratio and fit correctly alongside the text, ensuring a professional and consistent email design. This improves the overall visual quality of marketing campaigns.
Original PR description
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the…
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the image is tall, the row grows to fit the text and the image is stretched to that height (and cropped through object-fit: cover). The longer the text, the more the image is distorted. Drop h-100 from the image and align-self-stretch from its column in the s_media_list snippet and in the mass_mailing_themes templates that reuse it. With no forced height the image keeps its natural aspect ratio and the row height follows its content, so the image is laid out next to the text instead of being stretched to match it. Steps to reproduce: 1. Open Email Marketing and create a new mailing. 2. Select the Blogging template for the mail body. 3. In a media item, replace the text next to an image with a very long paragraph. => The image is stretched and cropped to match the height of the text. Ticket [link](https://www.odoo.com/odoo/project.task/5117571) opw-5117571 Forward-Port-Of: odoo/odoo#268675 Forward-Port-Of: odoo/odoo#238138
Code cleanup and technical improvements
This update improves the generation of France's fiscal reports by introducing reusable functions and streamlining existing code. Comprehensive test cases have been added to ensure accurate data extraction and XML report formatting for these critical financial documents.
Original PR description
-Created a utils file for france fiscal reports that has the common functions, and refactored some parts of the code in the report handlers. -Created test cases for adding and removing lines from a report, extracting the data, and exporting the report as xml for the france localization fiscal report. task-6138193
19 changes
Enhancements to existing features
This update automatically refreshes KYC status information for French PDP users by receiving notifications from IAP. Previously, users had to manually update this status. This change streamlines the process and ensures accurate, real-time data.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596 Forward-Port-Of: odoo/odoo#268528
Resolved issues and error corrections
This update resolves a crash issue that occurred when users autofilled formulas in the spreadsheet edition. The fix ensures simple `=PIVOT(...)` formulas remain unchanged during autofill, preventing unexpected crashes and maintaining consistent behavior. This improves stability and reliability for users working with pivot tables.
Original PR description
Current behavior before PR: - Autofill on formulas like `=PIVOT(1)` could crash after the refactor in e34c0a3, the new logic tried to process all pivot formulas. - However, simple `=PIVOT(...)` cases do not require any change in formula during autofill. Desired behavior after PR is merged: - Add an early return for pivot formulas that are not `PIVOT.VALUE` or `PIVOT.HEADER`, avoiding unnecessary processing. - Ensure `=PIVOT(...)` formulas remain unchanged during autofill, preventing crashes and keeping behavior consistent. Task: [6158888](https://www.odoo.com/odoo/project/2328/tasks/6158888)
This update resolves an issue where errors occurred during the download of ETA invoices due to incorrect JSON decoding. A previous change introduced a new error type that wasn't being caught, and this fix adds a necessary catch block to ensure smooth invoice processing. This ensures invoices are correctly downloaded and processed.
Original PR description
When we download the ETA invoice PDF, a JSONDecoderError can happen when calling the json() method on the request. This error is properly caught by Odoo : https://github.com/odoo/odoo/blob/7a9a340e0dbac470c4bea3f8ce8a32e55f3e82e6/addons/l10n_eg_edi_eta/models/account_edi_format.py#L58-L60 However, the following commit introduced a monkeypatch to handle errors when the simplejson library is installed : 2435fe76eec1fc4320ef71726fc7f16ece653a32 If we meet the conditions, the original error is replaced by a json.JSONDecodeError which is not caught during the previous process. We propose to add this error to the catch block. This modification was inspired by the commit d483dac144a9caf84c44b9d8d394ea327ca87cfe. opw-6266862 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268309
This update resolves an issue where the builder sidebar incorrectly displayed "Block" for website snippets. The fix re-injects a key attribute ('data-name') during builder setup, ensuring snippets are correctly identified and displayed with their actual names. This improves the user experience when creating and editing website pages.
Original PR description
\* = website ### Issue: When a page is created either through the configurator or from an existing page template, block-level snippets do not display the correct title in the builder sidebar.…
\* = website
### Issue:
When a page is created either through the configurator or from an
existing page template, block-level snippets do not display the correct
title in the builder sidebar. Instead, "Block" is shown for all
snippets.
### Steps to Reproduce:
- **Configurator:**
1. Install the website module or create a new website from Settings.
2. Complete all configurator steps. Do not use "Skip and start from
scratch".
- **Page template:**
1. Open the website and click the "New" button in the systray.
2. Click on "Page" and choose any template other than a blank page.
### Observed behavior:
The builder sidebar shows "Block" in the option container for all
snippets instead of their actual names.
### Reason:
Previously, just before the builder was opened, the `data-name`
attribute was injected through `_computeSnippetTemplates()` for any
snippet that did not already have it. This behavior was lost after the
plugin refactoring.
### Fix:
As before, we now inject the `data-name` attribute during builder setup
for snippets that do not already have it.
task-[6087348](https://www.odoo.com/odoo/all-tasks/6087348)
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269287
Forward-Port-Of: odoo/odoo#259893This update resolves an error that occurred when users removed the date field in the Accrued Expense Entry wizard. The fix adds a check to ensure the date field has a valid value before performing comparisons, preventing a type error. This ensures the Accrued Expense Entry feature functions correctly.
Original PR description
Currently, error occurs when user removes date on Accrued Expense Entry wizard. Steps to replicate: - Install `purchase` and `accountant` with demo. - Open any Purchase Order > Click on cog menu >…
Currently, error occurs when user removes date on Accrued Expense Entry wizard.
Steps to replicate:
- Install `purchase` and `accountant` with demo.
- Open any Purchase Order > Click on cog menu > Accrued Expense Entry.
- Remove value from `date` and click else where.
Error:
```
File '/home/odoo/odoo19/community/addons/account/wizard/accrued_orders.py', line 67, in _compute_reversal_date
if not record.reversal_date or record.reversal_date <= record.date:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<=' not supported between instances of 'datetime.date' and 'bool'
```
Cause:
- As the user removed value from `date`, [here] `record.date` is received as False.
- As a result the comparison `record.reversal_date <= record.date` causes this error to occur.
Solution:
- Added a conditional check for `date` before the date comparison.
[here]: https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/account/wizard/accrued_orders.py#L67
No ID
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269418
Forward-Port-Of: odoo/odoo#262568This update fixes a previous issue where sales employees transitioning to non-commission roles incorrectly accrued commission losses for public holidays and sick time. The change ensures that these employees are no longer penalized for time off when their compensation structure has changed, improving payroll accuracy.
Original PR description
If a salesman moves to another job that doesn't pay commission, he shouldn't have loss on commissions for public holidays and sick time off. Forward-Port-Of: odoo/enterprise#120386
This update ensures that holiday pay is accurately calculated when employees take double holidays, aligning with legal requirements. Previously, the system didn't properly prorate holiday pay based on the employee's previous work rate. This change improves payroll accuracy and compliance.
Original PR description
If you have a double holiday attest, we need to prorate the amount based on legal leave rights. The proration with regards to the previous work time rate wasn't done.
This update corrects a bug that prevented new online account connections for Canadian banks (which don't use IBANs). Previously, a misleading error would appear if a journal was incorrectly linked. Now, the system skips the journal check when an account number is missing, ensuring proper connection creation and avoiding this frustrating error.
Original PR description
…unt number When a provider returns an account without `account_number` (typical for Canadian banks, which do not use IBANs), the existing-journal search ran with `bank_account_number = False`.…
…unt number When a provider returns an account without `account_number` (typical for Canadian banks, which do not use IBANs), the existing-journal search ran with `bank_account_number = False`. Because `bank_account_number` is a related field on `bank_account_id.account_number`, that search matched every bank journal in the user's allowed companies whose `bank_account_id` was unset. If any of those journals was tied to a connected online link, the new sync was blocked with the misleading error "There's already a synchronized journal linked to this IBAN", even though no IBAN was involved. Skip the search entirely when `account_number` is falsy: without an identifier there is nothing meaningful to dedup against, and the downstream code already handles `existing_journals` being empty by creating a fresh journal. Note: when the provider omits `account_number`, a delete-and-recreate of the connection will now create a fresh journal rather than coincidentally reusing an unlinked empty-`bank_account_number` journal. That reuse path already failed (with a spurious "IBAN already connected" error) as soon as the user had more than one such journal, so the prior behavior was not reliable. The supported recovery path remains the reconnect button on the existing journal, which uses the `active_id` branch and is unchanged. opw-6253563
This update resolves an issue where duplicating a Time Off type with a Payroll Code resulted in an error due to a uniqueness constraint. The fix automatically appends a suffix to the code field during duplication, allowing users to create multiple time off types with the same code.
Original PR description
Steps to reproduce: ------------------------------------------ 1. Install Time Off module 2. Create a new Time Off type with Payroll Code (e.g, TEST) 3. Duplicate the Time Off type Observation:…
Steps to reproduce: ------------------------------------------ 1. Install Time Off module 2. Create a new Time Off type with Payroll Code (e.g, TEST) 3. Duplicate the Time Off type Observation: ------------------------------------------ User Error raised: ``` Cannot insert 'Test (copy)': Work entry type 'Test' of code 'TEST', with no country assigned, already exists. ``` Issue: ------------------------------------------ When you duplicate a Time off type, Odoo's default `copy()` method doesn't modify the code field. The `_check_code_unicity` constraint enforces that each combination of `code` and `country_id` must be unique. Since your duplicated record has the same `code`, the same `country_id` and a different `name`. The constraint correctly raises an error. Solution: ------------------------------------------ Override the `copy()` method to automatically append a suffix to the code field when duplicating, similar to how the name field gets '(copy)' appended. opw-6225931
This update corrects a bug where timesheets were incorrectly added to invoices after a partial refund on a sales order. The fix ensures that timesheets associated with fully invoiced orders are no longer considered when generating new invoices, preventing duplicate invoicing and maintaining accurate financial records. This improves the reliability of our invoicing process.
Original PR description
### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create 2 lines for the services product in the SO, invoicing policy = based on timesheets - Create 2 timesheets for both SO items - Invoice the SO - Create a credit note for line 1 => only line 2 is invoiced and line 1 is now released - Back to the SO > create invoice again > Line 2 is added to the invoice again. ### Cause of Issue: When generating the new invoice, `_recompute_qty_to_invoice` identifies timesheets linked to refunded invoices. Because the original invoice was partially refunded, all timesheets attached to that invoice match the domain used to locate timesheets—even the timesheets for line 2, which wasn't refunded. ### Fix: Ensures that lines that have already been completely invoiced are safely ignored and not inadvertently re-added to subsequent invoices. opw-6217684 Forward-Port-Of: odoo/odoo#268972 Forward-Port-Of: odoo/odoo#265840
This update fixes an issue where users couldn't save a 'Company Name' entered in their account settings. The fix ensures that when a new company name is added, a new company record is automatically created, aligning with the latest portal updates. This improves the user experience and data accuracy.
Original PR description
### Steps to reproduce: - Download "Website" app - In the portal's "/my/account" address form, enter a "Company Name" - Click "Save" to submit the form - Reload the page and check if the company name…
### Steps to reproduce: - Download "Website" app - In the portal's "/my/account" address form, enter a "Company Name" - Click "Save" to submit the form - Reload the page and check if the company name was saved > Company name isn't updated ### Cause of Issue: `_create_or_update_address()` method was passing the 'parent_name' field directly through the main `partner_sudo.write(address_values)` call. https://github.com/odoo/odoo/blob/391cec39b6048ad4f49015fd67888895dc176ee5/addons/portal/controllers/portal.py#L564-L571 Since `parent_name` is a readonly related field (related to `parent_id.name`), the write operation would fail silently to update it, creating orphaned changelog entries instead of properly updating the parent company entity. ### Fix: Since the update of contact forms in v19.1, we can't just edit the "Company Employer" field without assigning an actual partner (existing or create new). The solution here was to add a case to account for when the portal user is an individual adding a "Company Name" for the first time. opw-6115158 Forward-Port-Of: odoo/odoo#264356
This update prevents the 'Project: Task Rating Request' email template from disappearing when project stages are set to inactive. Previously, disabling ratings on the last stage caused the template to be archived, leading to a broken user experience. This fix ensures the template remains available in the dropdown for selection.
Original PR description
Currently, when the `rating_active` feature is disabled on the last project stage using it, the default 'Project: Task Rating Request' email template is automatically archived. This creates a UX issue where the template disappears from the "Rating Email Template" dropdown on the stage form, preventing users from selecting it. This commit resolves the issue by: - Setting `active="True"` by default on the XML template record. - Removing the background archiving logic from the `write` method of `project.task.type`. - Appending a check to `test_send_rating_review` to ensure the template remains active even when all stages in the database have ratings disabled. Task-6102227 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264394
This update resolves an issue where canceling a Global Invoice on a Mexican POS order prevented the creation of a new Global Invoice for the same order after a partial refund. The fix ensures that the refund process correctly updates CFDI documents, allowing for seamless invoice management and avoiding errors.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120349 Forward-Port-Of: odoo/enterprise#117211
This update ensures Polish company invoices sent to KSeF (a Polish tax system) include a required field ('PrefiksPodatnika') as mandated by the Ministry of Finance. This corrects a previous omission that resulted in non-compliant tax reporting for common EU transactions like intra-Community sales. The fix ensures accurate data transmission to KSeF, maintaining legal compliance.
Original PR description
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed…
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed in the buyer's EU country) or Triangular Sale. 3. Send the invoice to KSeF and download the generated FA(3) XML. Issue The Podmiot1 (seller) block in the rendered FA(3) XML omits the PrefiksPodatnika element, see https://github.com/odoo/odoo/blob/89219a843545d8bb0cad6ea806a1167cee6289da/addons/l10n_pl_edi/data/fa3_template.xml#L34-L42. According to the official Ministry of Finance documentation (https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf, page 11), this conditional field must carry the value "PL" when the invoice documents: - the intra-Community supply of goods, - the provision of services referred to in Article 100 sec. 1 item 1 of the Act for EU VAT taxpayers, - the supply carried out under a simplified triangular transaction by the second taxpayer (Article 135 sec. 1 item 4 (b) and (c)). The XSD marks the element as optional (minOccurs="0", fixed="PL") so KSeF accepts the XML, but the seller's tax reporting is still legally non-compliant for the three cases above, and the field is missing from the KSeF PDF viewer rendering. opw-6213178 Forward-Port-Of: odoo/odoo#264659
This change resolves an issue preventing users from selecting contacts with VATs as feedback recipients within appraisals. The previous system incorrectly classified VAT-enabled contacts as 'companies,' limiting recipient options. Removing a restrictive domain allows for full contact selection, streamlining the feedback process.
Original PR description
Issue: ---------------------------------------- We cannot add a contact with a VAT as a feedback recipient. Steps to reproduce: ---------------------------------------- - Have a contact with a VAT - Go to a confirmed appraisal and select 'Ask Feedback' - We cannot add the contact as recipient. Cause: ---------------------------------------- There is a domain on the field to only accept non company contacts. The idea of the domain was to restrict the field to persons only. But since f2965048f60fe6c815b3e50fa714c97a93dfb5d3 the field `is_company` is computed based on the VAT presence. So a contact with a VAT specified is considered a company. Solution: ---------------------------------------- Remove the domain. We allow to select all contacts, the users will have to do the sort. opw-6280689
This update resolves an error that occurred when generating payslips for employees with contracts exceeding 35 years. The fix adjusts a key calculation parameter to accommodate seniority beyond the previous limit, ensuring accurate payroll processing for all employees according to Mexican labor law. This change improves payroll accuracy and compliance.
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-6090590
Forward-Port-Of: odoo/enterprise#113536This update fixes an issue where images in email marketing templates were stretched and distorted when paired with long text. By removing specific styling, images now maintain their natural aspect ratio and fit appropriately alongside the text, ensuring a cleaner and more professional email design. This improves the overall visual quality of marketing communications.
Original PR description
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the…
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the image is tall, the row grows to fit the text and the image is stretched to that height (and cropped through object-fit: cover). The longer the text, the more the image is distorted. Drop h-100 from the image and align-self-stretch from its column in the s_media_list snippet and in the mass_mailing_themes templates that reuse it. With no forced height the image keeps its natural aspect ratio and the row height follows its content, so the image is laid out next to the text instead of being stretched to match it. Steps to reproduce: 1. Open Email Marketing and create a new mailing. 2. Select the Blogging template for the mail body. 3. In a media item, replace the text next to an image with a very long paragraph. => The image is stretched and cropped to match the height of the text. Ticket [link](https://www.odoo.com/odoo/project.task/5117571) opw-5117571 Forward-Port-Of: odoo/odoo#268675 Forward-Port-Of: odoo/odoo#238138
This update enhances the accuracy of partner searches within Odoo by using exact name matches instead of partial matches. This prevents incorrect partner identification and ensures more reliable data retrieval, particularly important for UBL import processes that now utilize bank account details for partner identification.
Original PR description
Before this commit: * Partner was searched using contains on the name, which could match unrelated partners with similar names (e.g. 'Global Tech' matching 'Global Technologies Ltd'). After this commit: - Partner retrieval now uses an exact name match to avoid incorrect matches caused by partial name search. - The search limit is set to 1 to ensure a consistent result when multiple partners are found. Technical: - Replaced `ilike` with `=ilike` in the name search domain. task-5485563 Forward-Port-Of: odoo/odoo#269355 Forward-Port-Of: odoo/odoo#250309
This update prevents the Timesheet Assistant from incorrectly matching events to projects or tasks with disabled timesheets. The change improves data accuracy and ensures the assistant only considers active projects and tasks for time tracking, streamlining the timesheet process.
Original PR description
Currently, the Timesheet Assistant (ActivityWatch) can match events to projects or tasks that have timesheets disabled, either via Custom Rules or Historical Memory.
This commit resolves the issue across the entire pipeline:
- Backend: Updated `resolve_assistant_models_targets` to efficiently filter out records where `allow_timesheets` is False using a search domain.
- Frontend: Updated the `loadData` JS pipeline to intercept and wipe any project/task IDs rejected by the backend, ensuring they cleanly fall back into a single "Unmatched" group.
- Views: Added the `[('allow_timesheets', '=', True)]` domain to `project_id` and `task_id` fields in `aw.rule` views to prevent users from creating invalid rules.
Task: 6267401
Forward-Port-Of: odoo/enterprise#1194039 changes
Enhancements to existing features
This update enhances the payment confirmation screen in the Point of Sale system. Now, customers see a "Processing..." message during payment finalization and a visual checkmark with the amount paid upon successful completion. The screen also removes distracting warning notifications and utilizes a reusable animation, creating a smoother and more informative experience.
Original PR description
In this commit : - Show "Processing..." text while payment finalization is running - Show animated success checkmark and "Amount Paid" once processing completes - Remove warning notification when clicking during processing - Extract shared checkmark animation into reusable template - Update tour tests to verify the success state Task:6246377 Forward-Port-Of: odoo/odoo#267635
This update changes the 'To Review' status badge on employee records from grey to orange. This improves readability, particularly in dark mode, ensuring that HR staff can quickly identify and address outstanding tasks. The change was made to enhance user experience and operational efficiency.
Original PR description
The 'To Review' status on employees uses a grey badge ('secondary'), which has poor contrast and is nearly invisible in dark mode.
Update the 'review_state' field options to change '2_to_review' to 'warning' (orange). This ensures the badge is readable in both light and dark modes.
Task: 6289919Resolved issues and error corrections
This update fixes a previous issue where sales employees moving to non-commission roles incorrectly accrued commission losses for public holidays and sick time. Now, employees in non-sales positions will no longer experience these inaccurate commission deductions, ensuring accurate payroll calculations.
Original PR description
If a salesman moves to another job that doesn't pay commission, he shouldn't have loss on commissions for public holidays and sick time off. Forward-Port-Of: odoo/enterprise#120386
This update fixes an issue where timesheets linked to partially refunded invoices were incorrectly being added to new invoices. The fix ensures that timesheets associated with fully invoiced orders are no longer considered when generating new invoices, preventing duplicate invoicing and ensuring accurate financial reporting. This improves the reliability of our invoicing process.
Original PR description
### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create 2 lines for the services product in the SO, invoicing policy = based on timesheets - Create 2 timesheets for both SO items - Invoice the SO - Create a credit note for line 1 => only line 2 is invoiced and line 1 is now released - Back to the SO > create invoice again > Line 2 is added to the invoice again. ### Cause of Issue: When generating the new invoice, `_recompute_qty_to_invoice` identifies timesheets linked to refunded invoices. Because the original invoice was partially refunded, all timesheets attached to that invoice match the domain used to locate timesheets—even the timesheets for line 2, which wasn't refunded. ### Fix: Ensures that lines that have already been completely invoiced are safely ignored and not inadvertently re-added to subsequent invoices. opw-6217684 Forward-Port-Of: odoo/odoo#268972 Forward-Port-Of: odoo/odoo#265840
This update prevents the 'Project: Task Rating Request' email template from disappearing when project stages are set to disable ratings. The change ensures users can always select this template from the dropdown, improving usability and workflow. The fix involved setting a default active status for the template and adjusting testing procedures.
Original PR description
Currently, when the `rating_active` feature is disabled on the last project stage using it, the default 'Project: Task Rating Request' email template is automatically archived. This creates a UX issue where the template disappears from the "Rating Email Template" dropdown on the stage form, preventing users from selecting it. This commit resolves the issue by: - Setting `active="True"` by default on the XML template record. - Removing the background archiving logic from the `write` method of `project.task.type`. - Appending a check to `test_send_rating_review` to ensure the template remains active even when all stages in the database have ratings disabled. Task-6102227 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264394
This update ensures Polish company invoices sent to KSeF (a Polish tax system) correctly include a required field ('PrefiksPodatnika') in the FA(3) XML format. This is necessary for legal compliance with Polish tax regulations for common EU transactions like intra-Community sales and services. The fix addresses a technical issue where the field was missing, preventing proper processing by the KSeF system.
Original PR description
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed…
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed in the buyer's EU country) or Triangular Sale. 3. Send the invoice to KSeF and download the generated FA(3) XML. Issue The Podmiot1 (seller) block in the rendered FA(3) XML omits the PrefiksPodatnika element, see https://github.com/odoo/odoo/blob/89219a843545d8bb0cad6ea806a1167cee6289da/addons/l10n_pl_edi/data/fa3_template.xml#L34-L42. According to the official Ministry of Finance documentation (https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf, page 11), this conditional field must carry the value "PL" when the invoice documents: - the intra-Community supply of goods, - the provision of services referred to in Article 100 sec. 1 item 1 of the Act for EU VAT taxpayers, - the supply carried out under a simplified triangular transaction by the second taxpayer (Article 135 sec. 1 item 4 (b) and (c)). The XSD marks the element as optional (minOccurs="0", fixed="PL") so KSeF accepts the XML, but the seller's tax reporting is still legally non-compliant for the three cases above, and the field is missing from the KSeF PDF viewer rendering. opw-6213178 Forward-Port-Of: odoo/odoo#264659
This update resolves an error that occurred when generating payslips for employees with contracts exceeding 35 years. The fix adjusts a key calculation parameter to correctly account for Mexican labor law rules regarding seniority and holiday accrual, ensuring accurate payroll processing for all employees. This change improves payroll accuracy and compliance.
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-6090590
Forward-Port-Of: odoo/enterprise#113536This update fixes an issue where images in email marketing templates were stretched and distorted when paired with long text. By removing specific styling, images now maintain their natural aspect ratio and fit appropriately alongside the text, ensuring a cleaner and more professional email design. This improves the visual consistency of our email campaigns.
Original PR description
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the…
The media list snippet forces the image to fill the height of its row. The image column carries align-self-stretch and the image carries h-100, so when the text next to the image is longer than the image is tall, the row grows to fit the text and the image is stretched to that height (and cropped through object-fit: cover). The longer the text, the more the image is distorted. Drop h-100 from the image and align-self-stretch from its column in the s_media_list snippet and in the mass_mailing_themes templates that reuse it. With no forced height the image keeps its natural aspect ratio and the row height follows its content, so the image is laid out next to the text instead of being stretched to match it. Steps to reproduce: 1. Open Email Marketing and create a new mailing. 2. Select the Blogging template for the mail body. 3. In a media item, replace the text next to an image with a very long paragraph. => The image is stretched and cropped to match the height of the text. Ticket [link](https://www.odoo.com/odoo/project.task/5117571) opw-5117571 Forward-Port-Of: odoo/odoo#268675 Forward-Port-Of: odoo/odoo#238138
This update resolves a critical issue where VoIP registration would fail due to idle sessions, causing error dialogs and preventing users from making calls. The fix ensures that the registration process is reliably restarted when a session becomes inactive, improving VoIP stability and user experience. It prevents a frustrating 'reconnection' loop and ensures calls can be established.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#120107
Forward-Port-Of: odoo/enterprise#1197012 changes
Resolved issues and error corrections
This update resolves a critical issue where VoIP registration would fail due to a delayed response when a session remained idle. The fix automatically recreates the registration process, preventing error dialogs and ensuring consistent VoIP connectivity. This improves the user experience and prevents disruptions to calls.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#120107
Forward-Port-Of: odoo/enterprise#119701This update resolves an issue that prevented users from successfully editing the names of multiple projects simultaneously. The fix ensures that the system handles multi-editing of project names correctly, preventing a technical error that would have blocked the update. This improves the user experience when managing project names.
Original PR description
Currently, an error will occur when user multi edits name of projects. Steps to replicate: - Install `documents_project` and open any project's settings using kebab menu (3 dots). - Click new > name…
Currently, an error will occur when user multi edits name of projects. Steps to replicate: - Install `documents_project` and open any project's settings using kebab menu (3 dots). - Click new > name `Test` > open settings page and unselect `Documents` > Save. - Click new > name `Test1` > Save. - From the list view select `Test` and `Test1` and edit their name. Error: ``` ValueError: Expected singleton: project.project(9, 10) ``` Cause: - During `multi-edit`, self contains multiple project records. - When only one of the selected projects has a documents folder (i.e. `use_documents` enabled), `self.documents_folder_id` contains that single folder, making `len(self.documents_folder_id.project_ids) == 1` to be True [1]. - The condition then proceeds to access `self.name` on the `multi-recordset`, raising singleton. Solution: - Avoided accessing `self.name` on a `multi-recordset` during multi-edit. - Filtered projects individually and updated the document folders using the name in vals. [1]: https://github.com/odoo/enterprise/blob/3c2985ca6011700c271ed14e40e08c89be822753/documents_project/models/project_project.py#L101 sentry-7452096418 Forward-Port-Of: odoo/enterprise#119060
2 changes
Enhancements to existing features
This update automatically refreshes KYC status information for French PDP users. Previously, users had to manually update this status; now, the system receives a notification from IAP and updates the status automatically. This streamlines the process and improves data accuracy.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596 Forward-Port-Of: odoo/odoo#268528
Resolved issues and error corrections
This update resolves a critical issue where VoIP registration would fail due to a delayed response when a session remained idle. The fix automatically recreates the registration process, preventing error dialogs and ensuring consistent VoIP connectivity. It improves the user experience by reliably establishing and maintaining VoIP connections.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#120107
Forward-Port-Of: odoo/enterprise#1197013 changes
Resolved issues and error corrections
This update fixes a bug that prevented proper error messages from appearing when IoT scale operations encountered problems. Previously, the system didn't clearly communicate these errors, making it difficult to diagnose and resolve issues. This ensures users receive timely notifications about scale failures, improving operational efficiency.
Original PR description
This completes odoo/enterprise#11196, which missed error message handling for new IoT Boxes errors. `message_body` was undefined on `data.status` when `data.status === "error"`. <img width="1871" height="942" alt="image" src="https://github.com/user-attachments/assets/30b54c5b-da0d-497d-8d9e-912f7139140b" /> Forward-Port-Of: odoo/enterprise#119228
This update resolves an issue where marketing automation campaigns would fail when users attempted to adjust the scheduling of activities. The fix prevents modifications to trace hierarchies during campaign execution, ensuring campaigns run smoothly and avoiding errors related to outdated scheduling information. This improves campaign reliability and reduces potential disruptions for users.
Original PR description
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing…
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save > IndexError: tuple index out of range ### Issue: The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: https://github.com/odoo/enterprise/blob/3e788e28dc76c928935d874e4e5a18d467c65539/marketing_automation/models/marketing_trace.py#L149 ### Fix: Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-6251614 Forward-Port-Of: odoo/enterprise#118994
This update resolves a critical issue where VoIP registration would fail due to idle sessions, causing error dialogs and preventing users from making calls. The fix ensures a robust reconnection process by automatically recreating the registration request when a timeout occurs, preventing the system from getting stuck and improving user experience.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#120107
Forward-Port-Of: odoo/enterprise#11970124 changes
New functionality added to Odoo
This update adds support for a new e-gov code (1298006) to all Circumstantial leave types within the Odoo Enterprise HR payroll module. This change aligns with recent regulations from the Belgian government, ensuring accurate payroll processing for employees covered by these specific leave types.
Original PR description
Add e-gov3.0: 1298006 to all Circumstantial leave types task: 6275799
This update introduces a new button within the payroll process, allowing administrators to easily add multiple salary adjustments to individual payrun records. This simplifies the process of correcting pay errors and applying retroactive changes, improving payroll accuracy and efficiency.
Original PR description
Adding a server action to allow for multiple salary adjustments to be added to the selected records on the payrun. task-6296109
Enhancements to existing features
This update improves the Field Service product to align with the new field service feature, streamlining the setup process. Additionally, a simplification was made to the planning role configuration, removing a requirement for resource assignments and allowing for more flexible resource selection within the auto-planning feature.
Original PR description
…duct This commit updates the Field Service product to better fit the new field service feature. task-5264800
This update simplifies the appraisal process for all users by adding a helpful message and adjusting access controls. Light users now have a streamlined view with simplified fields, while managers retain full editing capabilities for goal assignments. This enhances usability and ensures the right level of access for each user type.
Original PR description
### Dashboard: Added a helper message "Request an Appraisal with your manager to assess your work" to the empty state view of appraisals. ### Goals Form: - Set employee_id to invisible for light users to simplify the view. - Restricted the visibility of the "Save as Template" button to exclude light users. - Updated the manager_id field to be editable for light users, allowing them to assign or update their supervisors on specific goals. task-6133003
This update improves AI chat by allowing it to display rich, clickable previews of website records like products and events. Previously, AI responses only showed record names. Now, users can quickly access detailed information directly from the chat, boosting efficiency and engagement. This enhancement leverages website data to provide a more comprehensive and user-friendly experience.
Original PR description
### Summary This PR adds **AI preview cards** for website records. When an AI agent returns supported website content, the chat can now show rich, clickable cards instead of only plain record names.…
### Summary This PR adds **AI preview cards** for website records. When an AI agent returns supported website content, the chat can now show rich, clickable cards instead of only plain record names. Supported records include products, product variants, events, blog posts, appointment types, courses, lessons, and jobs. ### What changed #### Record preview flow Add `_ai_tool_prepare_record_previews` to prepare AI search results for display before the final answer is posted. The tool keeps the result order, stores preview links in the message body, and exposes metadata that the frontend can use to either render visual cards or keep normal records' links visible when cards are not available. #### Website card rendering Introduce `ai.preview.card.mixin` for website models that support visual previews. Each website bridge module provides its own `_ai_get_preview_cards_render_context`, so preview cards reuse the same public website templates and styling as the corresponding website pages. #### Frontend integration Add the `AIPreviewCardSet` component, preview-card cache, styling, and carousel behavior. Cards are rendered in website AI chat and embedded livechat. For embedded livechat, cards are injected through a light-DOM slot so website styles can still apply across the livechat shadow DOM. #### Website-aware pricing Add `ai.product.pricing.mixin` to expose website-aware pricing metadata for products, appointments, and paid slide channels. --- task-id-5153868
This update clarifies payslip corrections by showing the exact amount adjusted on PDF reports, rather than displaying original figures. It presents the difference in key figures like salary and worked days, making it easier to understand the change. The system now automatically handles related refunds and payments for accurate accounting.
Original PR description
When a payslip is corrected, the resulting correction payslip represents an adjustment, not a full re-statement of earnings. Showing absolute values on the PDF was confusing: the employee would see…
When a payslip is corrected, the resulting correction payslip represents an adjustment, not a full re-statement of earnings. Showing absolute values on the PDF was confusing: the employee would see the same gross/net figures as the original, making it unclear what actually changed. This PR makes correction payslips display the difference from the original in the PDF report (worked days, salary lines, totals), so it is immediately clear what was adjusted and by how much. On a correction PDF report, the Qty, Amount, and Rate columns are handled: - If only one of these three fields has changed, the report shows the delta for that field and the original values for the others, so that the product of the columns matches the total delta. - If two or more fields has changed, only the Total delta is shown, as a calculated product of multiple deltas would be misleading. To support this, two computed fields are introduced on hr.payslip: is_correction_payslip (True when the slip has an origin and is not a refund) and correction_net_delta (the net wage difference vs. the origin). A few related improvements are bundled: - The reverted (refund) payslip is automatically validated and created as a refund of the origin, while the correction payslip is left in draft. - Reverted payslips are excluded from PDF generation and e-mail notification. - When paying a correction, the system groups the amount between the correction and its corresponding reverted payslip and marks both as paid once the payment is confirmed (unless the reverted payslip was already paid). - When a negative correction delta occurs (the employee was overpaid), the workflow uses the existing negative-net warning: the correction sets 'has_negative_net_to_report' and 'negative_net_to_report', so the usual warning and salary attachment flow will handle recovery on next payslips. - The "wrong version" and issues detection now accounts for worked-day-level versions and time-off changes on already-paid payslips. - The related payslips smart button has been extended to corrections and reverts to access their origin and its related slips.
This update modernizes the Romanian D300 VAT report generation within Odoo, aligning with the latest requirements from the ANAF (Romanian tax authority). It now creates an XML file, completing the necessary flow for submitting the report and ensuring compliance. This improves the accuracy and reliability of financial reporting for Romanian businesses using Odoo.
Original PR description
Rename VAT report fom Romania and generate XML file to complete flow for D300 return complying with the latest ANAF specifications. https://static.anaf.ro/static/10/Anaf/Declaratii_R/300.html task-5423935 Forward-Port-Of: odoo/enterprise#109849
This pull request completely redesigns the appointment booking page, focusing on a cleaner mobile experience and simplified flow. Key changes include a foldable calendar, harmonized user selection, streamlined data loading, and automated confirmation features, resulting in a more intuitive and efficient booking process.
Original PR description
The slot selection page in appointment has been changed a large number of times. Adding a lot of small features to a complex flow made the code a mix of old and new, mixing interaction features and…
The slot selection page in appointment has been changed a large number of times. Adding a lot of small features to a complex flow made the code a mix of old and new, mixing interaction features and DOM manipulations. Parts were starting to get outdated, and the flow extremely complex to maintain, as comporting a lot of variation depending on the appointment type setup. Main changes --- In order to modernize the UI of the page, as well as to provide a cleaner mobile experience, we redesign it completely, rebuilding the js code and templates around the existing fundations. - The calendar is now foldable in a dropdown - The user / resource selection is harmonized: cards are used for both values of select_first (entity / date) - Selection is also foldable in a dropdown when starting with the entity. - Loaders and helpers are harmonized and streamlined into fewer cases / elements on the page. - When capacity is managed, 2 is selected as default if possible. We fallback to 1 otherwise. - The two-column design is abandoned. Also, some auto-confirmation is implemented: - When clicking on an entity, when it is last thing to select, submit the slot selection. - When selecting the time for the slot, submit the selection if no additional step is required. Technical Improvements --- - The previous way to refresh the availability was to rerender the full calendar template in the controller, return it and replace its outerHtml in the page. This is not dynamic nor interactive. We changed this old behavior to a more classical approach: the controller only returns a JSON with relevant data, and we render the calendar directly from the JS. We therefore moved the template into a JS one. - Controllers are cleaned from redundant data, and reworked to match previous change. - JS is streamlined as much as possible, reducing unjustified differences between similar elements. Interaction features are exploited as much as possible Other changes --- - Currently, we only compute one month of availability at a time for performance reasons. Keep this behavior, but replace the context key by real arguments in the controller. Also enable this behavior for flexible appointments - Remove 'discard' button when adding guests - Some ui polishing of various views in the booking flow - Added a small summary, only visible on mobile, at the top of the registration page. This allows a quick look in the booking details on mobile before starting filling details. Task-5358867
Resolved issues and error corrections
This update fixes an issue where the 'Cancel Reason' wasn't being properly transmitted to the Peruvian EDI (SUNAT) documents when reversing invoices. The change ensures that all cancellation details, including the user-provided reason, are accurately reflected in the electronic credit note, meeting regulatory requirements. This improves data accuracy and compliance for Peruvian businesses using Odoo.
Original PR description
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit…
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit Note. Only the Credit Reason is successfully reported. ### Steps to reproduce the issue: 1. Download Accounting and l10n_pe 2. Switch to PE company 3. Create an invoice and confirm it 4. Create a credit note for the invoice with a cancel reason and a credit reason and click the reverse button 5. See that in the Peruvian EDI tab only the Credit Reason is reported but not the Cancel Reason ### Cause of the issue: In the l10n_pe_edi module, the override of the _prepare_default_reversal method maps the l10n_pe_edi_refund_reason to the new move's values, but completely omits the mapping of the wizard's textual reason field to the l10n_pe_edi_cancel_reason field of the resulting credit note. ### Reason to introduce the fix: To ensure the generated credit notes contain all required information for the Peruvian EDI (SUNAT). Mapping the cancel reason guarantees that the electronic document accurately reflects both the refund code and the descriptive cancellation text provided by the user. opw-6238525 Forward-Port-Of: odoo/enterprise#119610 Forward-Port-Of: odoo/enterprise#118479
This update optimizes the way Odoo recalculates styles, specifically in large tables like the Accounting Balances Sheets. By removing unnecessary selectors, the system now processes changes more efficiently, leading to faster performance during scrolling, resizing, and sorting.
Original PR description
Adapt selector to remove the :has value since it not needed to have the effect applied. This reduces work during the "Recalculate Style" phase (for example when hovering rows in large tables such as the Accounting > Balances Sheets). It lowers recalculation time during window resizes, heavy scrolling, and table sorting by preventing broad selector matches and limiting style checks to elements with the specific class. This commit is a follow up of https://github.com/odoo-dev/enterprise/commit/8aa63b3c726d825e68430bb0a64a54c1b58d6af7 Note: We also fixes the scss button variable not correctly overided Forward-Port-Of: odoo/enterprise#119779 Forward-Port-Of: odoo/enterprise#119521
This update fixes an issue where untaxed invoice lines were incorrectly inheriting datev code from the previous line, leading to inaccurate reports. The change ensures that untaxed lines now properly display an empty datev code, aligning with German accounting standards and improving report accuracy. This resolves a technical problem impacting financial reporting.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update fixes a misleading error message displayed when a shift template's start hour was set after its end hour. The message has been corrected to accurately state that the start hour must precede the end hour for a valid shift template. This ensures users receive clear and helpful guidance.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
This update corrects issues with VoIP call records not accurately reflecting user presence, particularly when calls were stuck in an ongoing state. It ensures call records are consistently updated, improving the accuracy of call status displays and preventing misleading presence indicators. This improves the overall user experience and data reliability.
Original PR description
[FIX] voip: make sure any create/write on voip.call syncs user presence Commit [1] introduced a "in-call" presence icon. Before this commit, code updating call records had to call a specific function…
[FIX] voip: make sure any create/write on voip.call syncs user presence
Commit [1] introduced a "in-call" presence icon. Before this commit,
code updating call records had to call a specific function if user
presence potentially had to be changed after the record update. While
not hacking create/write to do that might be prettier, it is also
subject to mistakes and one was already made: demo data call record
creation did not update user presence properly. Commit [2] indeed
introduced calling/ongoing call demo data and the user presence was not
correct just after database initialization.
This commit fixes that by now potentially syncing in writes and always
syncing on create.
[FIX] voip: unstuck user call presence sooner in case of stuck calls
At the moment, the Odoo phone has a freshness system for call records
that appear still calling/ongoing for a strange duration. Indeed, there
are still cases where a call ended and we could not detect it. For
example, the user simply closing the tab where a call is ongoing (we try
to warn the user before he leaves but if agrees to leave anyway, the
call is just stopped when connexions are lost but the call record stays
marked as "ongoing"). In those cases, we have 2 things:
- A once-a-month cron checks all cases that are calling for more than
5 minutes or ongoing for more than 4 hours. It moves them to "ended
unexpectedly".
- The displayed status in views, shows "calling" / "ongoing" only if the
record is not older than 5 min / 4 hours. Otherwise it shows "ended
unexpectedly" already (as if the cron already did its job), despite
the record still having the "calling" / "ongoing" status.
It is weird and non-perfect but this allows to not have a "heavy" cron
job and consistent-enough call records display in views.
Of course, the long-term plan is to have more reliable call records
status (PBX, ...).
A new problem related to this appeared though. Since [1], a call icon
is used as the discuss presence icon in case the user is currently on a
call. The "currently on a call" data being transferred based on a field
"has_active_call" synchronized on call operations. Problem: in the case
mentioned above (call stuck in ongoing), that field will stay wrong for
a full month, showing the user as being on call. This commit makes it
so the check for active calls now considers fresh-enough calls (just
like the display in views does). It is only updated on a new call
operation though, so if an user has a stuck call, he will still be shown
as being on call until he starts/ends another call (or manually correct
the stuck call record).
Again, hopefully, stuck call records will be a thing of the past soon
enough so that issue will be minimized.
Note: this also uses `effective_start_date` instead of `start_date` to
check for stale calls, as it handles the potential no start_date while
ongoing that would stay stuck forever (that should not happen but,
better safe than sorry).
[FIX] voip: not consider incoming calling calls for presence status
Commit [1] introduced a "in-call" presence status. Commit [2], alongside
several fixes (e.g. parents of this commit and mentioned commit),
introduced new call demo data, including calling/ongoing calls:
- One incoming calling for Mitchell Admin
- One outgoing calling for Marc Demo
- One incoming ongoing for Marc Demo
- One outgoing ongoing for Marc Demo
Consequence: both Mitchell Admin and Marc Demo always have the "in-call"
presence icon, which might not be the best for demo. Still nice to test
VoIP but misleading for the rest.
In the end, we can have the best of both worlds: at the moment Mitchell
Admin only has an incoming calling call... and actually, that kind of
situation should not lead to being consider as "in-call". Calling
someone does, but receiving a call that we are potentially ignoring at
the moment does not.
This commit makes it so incoming calling calls are not considered for
presence anymore, at the same time thus making Mitchell Admin presence
not impacted by default VoIP demo data.
[1] - https://github.com/odoo/enterprise/commit/f1e0c41fa7b4f425e45303e5e912bf093c56480a
[2] - https://github.com/odoo/enterprise/commit/f16faa029220ca7152289180c4de78783bab03be
task-6239844
Forward-Port-Of: odoo/enterprise#118645This update simplifies call logging within Odoo Enterprise. Now, users can only log completed calls as activities, eliminating the option to schedule calls through the softphone log wizard. This change streamlines the logging process and aligns with current workflow best practices.
Original PR description
From now, only allow to log a done activity for a call, no more schedule activity from softphone log wizard. Task-[6276059](https://www.odoo.com/odoo/5778/tasks/6276059)
This update resolves an issue preventing users in Peru from generating closing entries within their tax reports. The fix introduces a dedicated Peruvian tax report variant, ensuring accurate VAT calculations and restoring the automatic closing account configuration process. This improves the reliability of financial reporting for Peruvian businesses.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes an issue where DATEV exports incorrectly included EU-specific fields for customers outside the European Union. The change ensures that the correct country information ('Land' field) is populated for non-EU customers, aligning with DATEV's data format requirements. This improves data accuracy and compliance for international reporting.
Original PR description
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries…
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries For non-EU countries, the `Land` field should be filled instead, and is required whenever the country is not Germany https://developer.datev.de/en/file-format/details/datev-format/format-description/debitorskreditors ### Cause: `_l10n_de_datev_get_partner_list` did not distinguish between EU and non-EU countries As a result, any partner with a VAT number could populate `EU-Land` and `EU-UStID`, even if the country was outside the EU Greece also requires a special case: its VAT prefix is `EL` so the `EU-Land` too, while the country code used in `Land` must remain `GR` ### Steps to reproduce: - Install `l10n_de_reports` and switch to the DE company - Create a customer in Switzerland with a valid VAT number - Create and confirm an invoice for that customer - Go to Accounting → Audit Reports → General Ledger - Select the full year - From the gear menu, export DATEV DATA (zip) - Open the `EXTF_customer_accounts` file ### Before the fix: `EU-Land` and `EU-UStID` are filled for the Swiss customer, while `Land` is empty ### After the fix: `EU-Land` and `EU-UStID` are empty for non-EU countries such as Switzerland, while `Land` is correctly filled `Land` is filled using the following priority: 1. Partner country_code 2. Country extracted from the VAT number 3. Empty opw-5902565 Forward-Port-Of: odoo/enterprise#119780 Forward-Port-Of: odoo/enterprise#113835
This update resolves an issue where users were encountering errors when attempting to use property fields within auto-fields in the Sign module. The fix restricts property field selection, ensuring data integrity and preventing the original error.
Original PR description
Currently, an error occurs when user tries to select a property field in auto field. Steps to replicate: - Install `sale_management` and `sign`. - Open Sales > Products > Products > Open any product.…
Currently, an error occurs when user tries to select a property field in auto field.
Steps to replicate:
- Install `sale_management` and `sign`.
- Open Sales > Products > Products > Open any product.
- From the Gear icon, Click Edit Properties and save the record.
- Enable Debug mode if you are using a version lower than 19.0 .
- Open Sign > Configuration > Field Types.
- Create a new Field > Give a name > Select model as `Product`.
- Select Field as `Property > Property 1` and click save.
Error:
- saas-18.3 and later:
```
File '/home/odoo/odoo18/enterprise/sign/models/sign_item_type.py', line 57, in _check_auto_field_exists
auto_field_value = record.mapped(sign_type.auto_field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/odoo18/community/odoo/orm/models.py', line 5472, in mapped
field = records._fields[field_name]
^^^^^^^^^^^^^^^
AttributeError: 'Property' object has no attribute '_fields'. Did you mean: 'field'?
```
- saas-18.2:
```
File '/home/odoo/odoo18/enterprise/sign/models/sign_item_type.py, line 41, in _check_auto_field_exists
auto_field_value = record.mapped(sign_type.auto_field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/odoo18/community/odoo/orm/models.py', line 5744, in mapped
if len(records) > PREFETCH_MAX:
^^^^^^^^^^^^
TypeError: object of type 'bool' has no len()
```
Cause:
- As the user gave auto fill field as a Property field the [line] called `mapped()` to access its value, this caused the error to occur.
- This occurs because `mapped()` expects a `recordset` (models.Model), but instead it receives a Property object, which does not have `_fields`.
Solution:
- Using `'allow_properties': 'False'`, the property fields wont appear in the list of field selection.
[line]: https://github.com/odoo/enterprise/blob/cdaeb79e1f623831fffa553dbb658698367c7e19/sign/models/sign_item_type.py#L41
sentry-7378769090
Forward-Port-Of: odoo/enterprise#119641
Forward-Port-Of: odoo/enterprise#113091This update resolves a performance issue impacting the calculation of payroll data (DPV). The fix optimizes a key process within the Be-HR payroll module, leading to faster and more efficient payroll processing. This ensures accurate and timely payroll calculations for our Belgian clients.
Original PR description
Forward-Port-Of: odoo/enterprise#118996 Forward-Port-Of: odoo/enterprise#118929
This update resolves an issue where employees with overlapping contracts would incorrectly receive a 'Duplicate Payslip' warning. The change restricts duplicate checks to payslips sharing the same version ID, ensuring accurate payroll reporting. This improves the reliability of payroll data.
Original PR description
If an employee has a contract that ends in the middle of the month and another contract starts in the same month, the two payslips that are created for the month trigger the "Duplicate Payslip" warning, even though they use different version IDs. This commit limits the search domain for the duplicate payslips to only consider payslips with the same version ID. task-6226391 Forward-Port-Of: odoo/enterprise#118652
This update resolves an issue where users received access errors when attempting to delete appraisal forms that weren't in the draft stage. The change now provides a user warning instead, offering a smoother and more intuitive experience. This improves usability and avoids unnecessary disruptions.
Original PR description
[IMP] hr_appraisal: appraisal form deletion error There was a security rule that throws access error when we try to delete the appraisal if it is not in draft stage There was also a user warning about that and we want user warning instead of access error. That's why i updated the security rule to exclude draft stage part. task - 6253595
This update resolves an issue where PDF reports for Mexican SAT Invoices didn't accurately reflect changes in the underlying CFDI XML data. Now, the reports directly use the CFDI data, ensuring accurate representation of product information, taxes, and discounts. This improves the reliability of Mexican invoice reporting within Odoo.
Original PR description
In Mexico, the pdf of a SAT Signed Invoice should be the graphical representation of the CFDI XML. This introduce us a problem as sometimes the information used to create the CFDI in Odoo changes or is ommited (product or contact information, hidden taxes, discount lines, etc.) To fix this, now the invoice report for Signed Mexican Invoices are now generated taking directly the values from the CFDI document, replacing most of the information taken from the invoice. task-4983567
This update resolves a crash in the payslip PDF report that occurred when employees didn't have a bank account configured. The fix adds a simple check to ensure the bank account section is only displayed if an employee actually has a bank account linked, improving report stability and reliability.
Original PR description
The payslip PDF report crashed when the employee had no bank account configured because the template tried to access bank_account_ids[0] unconditionally. Add a t-if guard on the bank account div to only render it when the employee has at least one bank account linked. Forward-Port-Of: odoo/enterprise#115893
This update fixes an issue where the field service report was displaying incorrect information. The report now correctly uses the Planning Shift name and start date, aligning with recent updates in version 19.2. This ensures accurate reporting for field service operations.
Original PR description
…port title - Removed the 't-if' condition containing 'doc.name', as 'doc.name' now refers to the Planning Shift name following the changes introduced in v19.2. - The report now displays 'start_datetime', which is automatically populated when a Planning Shift is created. - As a result, the 't-if' condition is no longer necessary. - This change aligns with the new behavior introduced in v19.2 and effectively replaces the Task name that was previously displayed before the report was migrated from 'project.task' to 'planning.slot'. Task-ID: 6284967 Forward-Port-Of: odoo/enterprise#119712
Miscellaneous changes
This pull request updates the .weblate.json files, which control the internationalization (I18N) of the Odoo Enterprise software. These updates ensure that the application's text is accurate and consistent across different languages, improving the user experience for international customers. This is a routine maintenance task to keep Odoo localized correctly.
8 changes
Enhancements to existing features
This update enhances the clarity of bank statements when transactions are split into multiple lines. By adding transaction category data, Odoo now provides more descriptive labels for each line, closely matching the details from CodaBox. This makes it easier for users to understand and track their financial activity.
Original PR description
Currently, when global transaction is split into multiple lines, Odoo assigns the exact same communication text to every single split line. This makes it difficult for users to identify what each specific charge is for. To fix this, this commit introduces the transaction category data. Using this data to append specific transaction details to the end of the communication label. As a result, each split line now has a clear, descriptive label that closely matches the detailed breakdown provided by CodaBox. task-6059709
Resolved issues and error corrections
This update fixes an issue where the 'Due' button wasn't appearing on customer forms when balances existed at the line level within journal entries. The fix ensures all customers with outstanding balances, regardless of how they're linked to journal entries, now have the 'Due' button available. This improves the user experience for managing customer accounts.
Original PR description
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open…
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open the customer form. Issue: The Due smart button is not visible on the partner form even though an outstanding balance exists for the customer. Note: This issue does not reproduce when Point of Sale is installed, as the POS module overrides `_compute_has_moves` with its own implementation that checks the outstanding balance directly. Root Cause: The `_compute_has_moves` method queries only `account.move `for partner matching. When a partner is referenced only at the account.move.line level, the partner is never picked up by this query, resulting in `has_moves = False` and the Due button remaining hidden. Fix: Replaced the EXISTS-based implementation with a UNION-based approach as the EXISTS implementation evaluated the query per partner row, whereas UNION processes all partners in a single batch query. Additionally extended the UNION to also include account.move.line partner matching, ensuring partners referenced only at the line level, are correctly detected and has_moves is set to True. Result: The Due smart button is now correctly visible for all partners with an outstanding balance, regardless of whether the partner is set at the journal entry level or only at the line level. owp = 6243562 Forward-Port-Of: odoo/enterprise#120155 Forward-Port-Of: odoo/enterprise#119084
This update resolves a bug that was preventing users from adding cover images to Knowledge articles. The issue stemmed from a missing callback function during the upload process. The fix ensures that cover uploads complete successfully, improving the user experience for adding visual content to articles.
Original PR description
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback:…
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback: `Uncaught Promise > this.props.setAbortUploadsCallback is not a function` Cause: - `KnowledgeCoverSelector` extends the html_editor `ImageSelector`, whose upload flow registers an abort callback through setAbortUploadsCallback. The generic MediaDialog provides this callback, but KnowledgeCoverDialog renders KnowledgeCoverSelector directly and did not pass it. As a result, the inherited upload flow called a missing prop. Solution: - Pass setAbortUploadsCallback from KnowledgeCoverDialog to KnowledgeCoverSelector and abort pending uploads when the cover dialog is discarded. Alternative approach: - Make ImageSelector tolerate callers that do not provide setAbortUploadsCallback by calling it with optional chaining. opw-6176716 Forward-Port-Of: odoo/enterprise#116906
This update fixes a previous issue where salespeople moving to non-commission roles incorrectly accrued commission losses for public holidays and sick time. The change ensures accurate commission calculations for all employees, regardless of their job role, improving payroll accuracy and reporting.
Original PR description
If a salesman moves to another job that doesn't pay commission, he shouldn't have loss on commissions for public holidays and sick time off.
This update fixes a bug where 401k matching contributions were incorrectly calculated for hourly employees with zero fixed wages. The fix ensures that matching contributions are accurately determined based on actual gross pay, providing correct retirement savings calculations for all employee types. This improves payroll accuracy and compliance.
Original PR description
*= test_l10n_us_hr_payroll_account The employer matching cap for pre-retirement plans (401KMATCHING) evaluates to zero for hourly wage employees if wage is set to zero. ### **Steps to Reproduce:** 1)…
*= test_l10n_us_hr_payroll_account The employer matching cap for pre-retirement plans (401KMATCHING) evaluates to zero for hourly wage employees if wage is set to zero. ### **Steps to Reproduce:** 1) Install l10n_us_hr_payroll. 2) Create an employee with an hourly wage and set the fixed wage to 0. 3) Configure the retirement plan parameters as follows: - 401(k) = 3% - Matching Amount = 100% - Matching Yearly Cap = 100% 4) Generate a payslip for this employee and compute the sheet. ### **Observed Behavior:** The "Benefits Matching to Retirement Plans" line computes as zero for the hourly employee. ### **Expected Behavior:** The employer matching contribution should dynamically scale based on the actual gross pay period earnings instead of evaluating to zero. ### **Root Cause:** The calculation of `partial_cap` uses `version.wage` directly at [1]. For hourly employees, the fixed 'wage' field defaults to zero, causing the entire multiplication to cancel out. [1]- https://github.com/odoo/enterprise/blob/4c540f450d4de8b59b871662123f85ed54cca2a9/l10n_us_hr_payroll/data/hr_salary_rule_data.xml#L167 ### **Fix:** This commit computes the retirement matching eligibility cap from `gross annualized wages` and applies the employer matching percentage on the eligible contribution amount. This ensures retirement matching is calculated consistently regardless of the employee's contract type. **opw-6181024**
This update resolves a technical issue where VoIP registration would fail with an error message when a user left a session open and inactive. The fix ensures that registration requests are properly handled and retried, preventing the appearance of error dialogs and maintaining a stable VoIP connection. It improves the user experience by ensuring consistent registration.
Original PR description
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog: UncaughtPromiseError > RequestPendingError REGISTER request already in progress, waiting for final…
Leaving a session open and idle (page open, no activity at all) eventually pops an error dialog:
UncaughtPromiseError > RequestPendingError
REGISTER request already in progress, waiting for final response
at Registerer.register (sip.js)
at Registerer.register (registerer.js)
at UserAgent.attemptReconnection (user_agent_service.js)
When the WebSocket transport drops while a REGISTER is in flight (which happens on an idle tab: SIP.js sends a periodic re-REGISTER before the registration expires, and the socket may be closed by an idle timeout or by the machine going to sleep in the meantime), the final response never comes back. SIP.js only clears its internal `waiting` flag from the REGISTER response callbacks (onAccept/onReject/onRedirect); it is never reset on transport loss or request timeout. The Registerer is then stuck `waiting` forever, and every subsequent register() rejects with a RequestPendingError.
On top of that, our wrapper's register() did not return the SIP.js promise, and attemptReconnection() called it without awaiting, so the rejection escaped the surrounding try/catch and surfaced as an unhandled promise rejection. Worse, the WebSocket error was resolved right after, so the user appeared reconnected while VoIP registration was actually dead until the page was reloaded.
This commit makes register() recreate the underlying SIP.js Registerer when it is stuck `waiting` (a clean instance starts with waiting=false), and return the promise so callers can await it. attemptReconnection() now awaits it, so any rejection goes through the existing retry/back-off logic instead of bubbling up as an uncaught error.
The recreation is intentionally conditional: disposing a healthy registerer would send an unregister (REGISTER expires=0) racing with the fresh register (expires=600) and could leave us unregistered, so we only recreate when a request is actually stuck.
Forward-Port-Of: odoo/enterprise#120107
Forward-Port-Of: odoo/enterprise#119701This update resolves an issue where manually added by-products on manufacturing orders caused errors during production closure. The fix ensures that serial numbers are correctly assigned when a by-product is added outside of the standard BOM definition, preventing user error messages and improving production workflow.
Original PR description
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application.…
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application. **Steps to reproduce** - Activate by-product in the settings - Create a product with an empty BOM (final product) - Create another product tracked by serial number (by-product) - Create and confirm a MO for the final product with 1 unit of the by-product - Go to Miscellaneaous -> operation Type -> shopfloor - Activate the option "Pre fill lot/serial numbers in shop floor" - Return to the MO and open the shopfloor view - Click on the '+' button next to the by-product and assign a serial number - Try to close the production -> A user error is raised stating that the by-product requires a serial number. **Cause** When the by-product is added manually on the MO, a stock move is created with an initial move line that does not contain any serial number. Later, when assigning a serial number from the shopfloor view: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L121-L122 a new move line containing the serial number is created: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L116-L119 However, the original empty move line is not removed (the issue): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L124-L125 Because `self.picking_type_prefill_shop_floor_lots` is True, but `self.byproduct_id` is an empty recordset since: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1304-L1311 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1279 Indeed, `byproduct_id` is only populated from BOM-defined by-products. As a result, while confirming the production, there is 2 sml and among them, the original one without SN, which triggers the error: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L590 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L634-L635 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L658-L659 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L661-L669 opw-6223158
This update resolves an error that occurred when calculating payroll for employees with contracts exceeding 35 years. The fix adjusts a key parameter in the payroll rules to accommodate Mexican labor law, specifically allowing for additional holiday days based on seniority beyond 35 years. This ensures accurate payroll calculations for all employees.
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-6090590
Forward-Port-Of: odoo/enterprise#11353613 changes
New functionality added to Odoo
This update introduces a system to automatically refresh KYC (Know Your Customer) status updates. Previously, users had to manually refresh the status, which is now handled through a webhook from IAP. This streamlines the process and ensures accurate KYC information within the system.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596
Resolved issues and error corrections
This update resolves a technical issue in the payroll calculation process for employees with contracts exceeding 35 years. The fix adjusts a key parameter to correctly account for Mexican labor law regulations regarding holiday accrual beyond the initial 35-year limit. This ensures accurate payslip generation for all employees.
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-6090590This pull request removes a redundant two-factor authentication (2FA) requirement for the l10n_fr_pdp module. Initial assessments incorrectly identified a need for 2FA, but subsequent investigation revealed it wasn't necessary. This change simplifies the setup process and improves efficiency.
Original PR description
We iniatially though the 2FA was needed by the administration. But in fact, it was not. So we will remove it. Commit of the 2FA: https://github.com/odoo/odoo/pull/239576/changes/7535ce70391348019b4d9b668e49ca928c03052b Commit of the reregister also changed a bit that https://github.com/odoo/odoo/commit/22ba6294d3a2da6cada9dd519bd870c99d0b51b9 no task id --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue causing inconsistent results in Odoo's tests for how many2one fields are used within one2many relationships. By backporting fixes from previous pull requests, the tests are now more reliable and predictable, ensuring greater stability in the Odoo platform. This improves the overall quality and reliability of the software.
Original PR description
This commit is a backport of [1] and [2] which fix non deterministic one2many tests involving a many2one. [1] https://github.com/odoo/odoo/pull/266344 [2] https://github.com/odoo/odoo/pull/256582 runbot error~243512 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 an issue where stock relocation incorrectly swapped the order of reservations for deliveries. After moving stock, reservations were reassigned in the wrong order, leading to incorrect quantity tracking. This fix ensures reservations are maintained in the original priority after internal stock movements.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Enable `Storage Locations` from Inventory settings - Create a tracked storable product with on-hand 8…
Version: ---------- - 18.0+ Steps to reproduce: ------------------- - Install `stock` module - Enable `Storage Locations` from Inventory settings - Create a tracked storable product with on-hand 8 units in `Shelf 1` - Create Delivery 1 for 5 units and click `Mark as To Do` - Create Delivery 2 for 5 units and click `Mark as To Do` - Verify reservations: - Delivery 1 reserves 5 units - Delivery 2 reserves remaining 3 units - Relocate all 8 units from `Shelf 1` to `Shelf 2` using the `Relocate` action from `stock quant` - Reopen both deliveries Issue: ------ After relocating stock between internal locations, reservations are reassigned in the wrong order: - Delivery 2 becomes fully reserved with 5 units - Delivery 1 is reduced to 3 reserved units This incorrectly swaps the original reservation priority between deliveries. Cause: ------ The relocation wizard starts from: `stock.quant.relocate.action_relocate_quants()` which calls `move_quants()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/wizard/stock_quant_relocate.py#L70 `move_quants()` validates an internal stock move through `_action_done()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_quant.py#L1572 During validation, `_synchronize_quant()` moves the stock quantity from `Shelf 1` to `Shelf 2`. However, the already reserved delivery move lines still reference `Shelf 1`. This temporarily makes the source quant negative (`available_qty < 0`), triggering `_free_reservation()`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L695-L700 Inside `_free_reservation()`, move lines are ordered using `current_picking_first`: https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L816-L821 Since both deliveries share the same scheduled date, the fallback ordering uses `-cand.id`, causing Delivery 2 (higher id) to be processed before Delivery 1 (lower id). The reservation cleanup therefore happens in this order: - Remove Delivery 2 reservation (3 qty) - Remove Delivery 1 reservation (5 qty) The corresponding moves are then added to `move_to_reassign` in the same order: `[Delivery 2, Delivery 1]` https://github.com/odoo/odoo/blob/d3eebbd1c27e8a039bb55cdf2a82d464e06ffa8c/addons/stock/models/stock_move_line.py#L849 Later, `move_to_reassign._action_assign()` processes the moves in recordset order: - Delivery 2 reserves 5 units first - Delivery 1 only gets the remaining 3 units As a result, reservation priority is unintentionally reversed after relocation. Fix: ---- Before calling `_action_assign()`, reverse `move_to_reassign` This ensures reassignment preserves the original reservation order: - Delivery 1 is reassigned first and recovers 5 units - Delivery 2 receives the remaining 3 units The reservation state therefore remains consistent before and after internal stock relocation. --- opw-6218256 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where product images in the grid layout didn't display in the correct visual order. The change reorders images based on their visual placement, ensuring a consistent and intuitive browsing experience for customers. This resolves a visual regression introduced during a recent layout update.
Original PR description
This commit ensures product images follow their visual order in the product image viewer when using the grid layout. Steps to reproduce: - Open a product page with multiple images (or add Extra Media…
This commit ensures product images follow their visual order in the product image viewer when using the grid layout. Steps to reproduce: - Open a product page with multiple images (or add Extra Media to the product) - Change layout mode to "Grid" and click save - Click any image to open the product image viewer - Navigate between images Images do not follow the visual left-to-right order. This regression was introduced by [commit], which replaced the row-based grid with a column-first layout. As a result, `querySelectorAll` returns images in DOM order, which no longer matches the visual order. To fix this, images are now reordered based on their visual placement in the grid so navigation matches the order seen by the user. Images are traversed in visual left-to-right order while also accounting for varying image heights and multi-column alignment. [commit]: https://github.com/odoo/odoo/commit/9a3628b9735550bf8ecc2252ea1b7338f68ab966 task-[4364143](https://www.odoo.com/odoo/project/974/tasks/4364143)
This update resolves an issue where the link editor state was incorrectly duplicated when creating multiple tracked links. Now, the system correctly clears the editor when a new link is generated, ensuring a smoother user experience and preventing confusion. This improves the overall reliability of the Link Tracker feature.
Original PR description
Steps to reproduce: - Go to the Link Tracker page - Generate a first tracked link - Click on the button to start editing the code - Click on "create another tracker" - Generate a second tracked link => When you access the screen to see/edit the tracked link url, the buttons "ok" and "cancel" are already present. Clicking on "ok" display a traceback. To fix this issue, this commit also cancels edition when clicking on "create another tracker". task-4531974
This update corrects an issue in the Datev ledger export, ensuring accurate currency calculations. Previously, the system incorrectly used the company currency instead of the invoice's currency, leading to discrepancies in reported values. This fix ensures Datev exports reflect the correct financial data.
Original PR description
There is an issue in the Datev export functionality. In the current functionality, the code calculates a delta between the taxes in the `tax_totals` and the ones on the journal items. Issue is, the tax amounts from tax_totals were always in company currency, while the entry itself can use a foreign one. This replaces the use of company currency with the use of the invoice's currency and appropriately adjusts the test featuring foreign currency. Steps: Create a foreign currency. Create an invoice with a taxed product using the currency. Export the ledger to Datev. Inspect the resulting csv. Note that neither the final listed price, nor the rate listed for the currency align with the ones in the db. opw-6275889
This update resolves an issue where move records needed to be sent to be properly processed within the French VAT (VAT_PD) flow. The fix also corrects errors related to copied zip files during address validation based on country, ensuring accurate data processing for French businesses.
Original PR description
This fix removes the condition that moves must be sent to be part of a flow 10 and correct copy-pasted zip by country_id in address check.
This update resolves an issue where errors occurred when downloading ETA invoices as PDFs. A recent change introduced a new type of error that wasn't being caught, leading to potential download failures. This fix adds a necessary catch block to ensure all JSON decoding errors are handled correctly.
Original PR description
When we download the ETA invoice PDF, a JSONDecoderError can happen when calling the json() method on the request. This error is properly caught by Odoo : https://github.com/odoo/odoo/blob/7a9a340e0dbac470c4bea3f8ce8a32e55f3e82e6/addons/l10n_eg_edi_eta/models/account_edi_format.py#L58-L60 However, the following commit introduced a monkeypatch to handle errors when the simplejson library is installed : 2435fe76eec1fc4320ef71726fc7f16ece653a32 If we meet the conditions, the original error is replaced by a json.JSONDecodeError which is not caught during the previous process. We propose to add this error to the catch block. This modification was inspired by the commit d483dac144a9caf84c44b9d8d394ea327ca87cfe. opw-6266862 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268309
This update fixes an error in the Luxembourg fiscal localization settings. The incorrect valuation account (60761 Merchandise) has been replaced with the correct current asset account (301 Inventories of raw materials), ensuring accurate accounting for Luxembourg businesses. This change improves the reliability of financial reporting.
Original PR description
**Problem:** Valuation account for luxembourg is currently 60761 Merchandise which is incorrect because it's an expense account. We should rather use a current asset account like 301 Inventories of raw materials **Steps to reproduce on a fresh db:** - create a new db with modules stock_account and accountant (without demo data) - On the 'fiscal localization setting' set the package as 'Luxembourg' and save - ativate the automatic accounting setting **Current Behavior:** The 'stock valuation account' appearing below the automatic accounting setting is : 60761 Merchandise **Expected behaviour:** It should be 301 Inventories of raw materials
This update resolves a critical error that prevented French eInvoicing invoices from being sent correctly in demo mode. The issue stemmed from a mismatch in data formats between the demo environment and the actual IAP service, specifically related to invoice message structures. This fix ensures invoices can be successfully processed during testing.
Original PR description
**Steps to reproduce:** * Install `l10n_fr_pdp` module. * Activate French eInvoicing in demo mode and enable "Participate in the pilot phase". * Create an invoice for a French client and send it via…
**Steps to reproduce:**
* Install `l10n_fr_pdp` module.
* Activate French eInvoicing in demo mode and enable "Participate in the pilot phase".
* Create an invoice for a French client and send it via the French E-Invoicing.
**Observed behavior:**
* A traceback is raised with `KeyError: 'messages'` in `_send_peppol_documents`.
**Cause:**
* `DEMO_ENDPOINTS['send_document']` in `l10n_fr_pdp` was returning `{'ppf_messages': [...]}`, missing the `messages` key that `_send_peppol_documents` in `account_peppol` unconditionally reads for flow 2.
* Additionally, the demo mock was returning `uid` instead of `uuid` inside `ppf_messages`, which does not match the real IAP response structure.
* Finally, in `l10n_fr_pdp/models/pdp_flow.py`, after successfully sending a flow 10 batch, the system attempted to log `response['uid']` despite the `_send_to_proxy()` method returning `uuid`. This caused a crash during the chatter logging step.
**Fix:**
* Fix `DEMO_ENDPOINTS['send_document']` to return `{'messages': [...]}` with `message_uuid` entries, matching the real IAP response structure for flow 2.
* Update `ppf_messages` in the demo mock to return `uuid` instead of `uid`.
* Fix `pdp_flow.py` to correctly access `response['uuid']` instead of `response['uid']` when posting the success message.
IAP Response: https://github.com/odoo/iap-apps/blob/b0462b9dded36a4d6dd45d00ddd13cd36e31807e/iap_services/l10n_fr_pdp_proxy/controllers/message_controller.py#L63
opw-6289723This update optimizes how Odoo retrieves related mailings during mass email campaigns. Previously, a slow process scanned all mailings, causing performance issues with large campaigns. This fix significantly improves the speed and efficiency of this process, preventing crashes and ensuring smoother campaign execution.
Original PR description
**Description of the issue/feature this PR addresses:** The method _get_ab_testing_siblings_mailings currently scans all mailings in a campaign to apply a simple filter, which becomes expensive on databases with many large mailings. **Steps to reproduce bug:** 1) Run this script to get [enough sufficiently large mailings](https://gist.github.com/brcut-odoo/bb0d6d334bfe110afe16021d17d1b443) 2) Open one of the mailings and recieve a crash from the _get_ab_testing_siblings_mailings **Current behavior before PR** https://drive.google.com/file/d/19xftvzsGSQ9DxB67LNiLkKApzsD192ax/view?usp=drive_link **Current behavior after PR** https://drive.google.com/file/d/1apTJ0rWTKaATYa67ZmmN-7bKhrw4KuTx/view?usp=drive_link opw-6245908 Forward-Port-Of: odoo/odoo#268283
3 changes
Resolved issues and error corrections
This update significantly speeds up the calculation of future timesheets based on public holidays. The previous process was slow due to repeated timezone conversions, which has now been optimized to only localize times when absolutely necessary. This improves the responsiveness of the system, especially when managing a large number of employees and holiday schedules.
Original PR description
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several years in the future), then it takes excessively long and the action may not complete. **Cause:** The pytz method `localize` and comparing times with non-static timezones is done repeatedly and unnecessarily which becomes costly with more records. **Solution:** Only localize the time when absolutely necessary (determining the date of the leave in the calendar timezone). **Performance Stats:** |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |100 |3.1s |393 |0.8s |117 | |1,000 |22.3s |2,090 |1.5s |183 | |10,000 |Timeout |N/A |6.7s |541 | opw-6087422
This update fixes a potential issue where errors during coupon redemption weren't clearly displayed to users. Now, if a coupon redemption fails, an error message will be shown, helping staff quickly identify and resolve problems with loyalty programs. This improves the overall reliability of the point-of-sale system.
This update optimizes the process of validating purchase orders by preventing unnecessary calculations of location weights. By reordering checks, the system avoids calling a computationally intensive method when other conditions already rule out a location. This results in significantly faster validation times, particularly when dealing with a large number of locations.
Original PR description
When checking if a stock.move.line can use a location as destination with the method `_check_can_be_used()`, we start by checking if the incoming products can be stored without exceeding the maximal…
When checking if a stock.move.line can use a location as destination with the method `_check_can_be_used()`, we start by checking if the incoming products can be stored without exceeding the maximal weight of the location. This needs to call the `_get_weight()` method to compute the forecasted weight for the location. This method relies on heavy computations and can become a bottleneck when we need to loop over a high number of locations. In some cases, we can rule out the location based on less expensive conditions that are verified after the weight one. We propose to invert the conditions check order to avoid computing the location weight when other conditions are not met. Steps to reproduce --------------- - Install stock and purchase modules; - Enable storage locations and categories in the settings; - Create a storage category: allow_new_product = same, max_weight=10.0 kg; - Create N locations using this category, parent_id=WH/stock; - Create a putaway rule to each location from WH/stock, for the new storage category and using a product A with a weight of 2 kg; - Create a stock.quant per location to store a product B, weight=2kg; - Create a purchase order with X lines for 1 unit of product A; - Validate the purchase order. The validation should take several seconds to execute as every locations will be rejected due to the storage category, but it will call _get_weight() first. Benchmark --------------- This improvement is very data specific and will be most useful when a lot of locations are using a storage category of type "empty" or "same". In addition, it also relies on the order in which we are treating the locations, if the acceptable locations are the first to be received in the method, it won't need to loop over all of them. The following benchmark was established in a production database in which every 6068 locations are using a category of type "same". | No stock.move.lines | Before PR | After PR | |---------------------|-----------|----------| | 40 | 168 s | 7.3 s | | 72 | 264 s | 12.33 s | When the only condition that can reject locations is the exceeding weight, this modification will slow down the process. However, the time loss in this case is smaller than the gain in the first case. The following benchmark was obtained by validating a purchase 1 line order with only fully filled locations. | No locations | Before PR | After PR | |--------------|-----------|----------| | 500 | 2.02s | 2.37 s | | 2000 | 7.85s | 9.76 s | | 10000 | 39.16 s | 48.86 s | opw-5949370 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr