Wednesday, March 25, 2026
33 changes · saas-19.2
Enhancements to existing features
This update enhances the Project Side Panel by allowing more detailed budget information to be displayed. By enabling inheritance of a key method, the system now includes a broader range of budget items, providing project managers with a more complete financial overview. This improves decision-making related to project costs.
Original PR description
Enabling the inheritance of the method _get_budget_items to include more budget information, by adding a method for the budget items domain. Forward-Port-Of: odoo/enterprise#107466
This update enhances debugging of Odoo's Chrome browser integration by capturing detailed logs when Chrome encounters issues, such as tab terminations. These logs provide more specific information than previous methods, aiding in identifying and resolving stability problems. The logging level can be adjusted for control and noise reduction.
Original PR description
Followup and partial revert of #232612: turns out chrome's stderr is worthless at best and confusing at worst (because it logs a bunch of dbus errors which don't actually matter), however chrome…
Followup and partial revert of #232612: turns out chrome's stderr is worthless at best and confusing at worst (because it logs a bunch of dbus errors which don't actually matter), however chrome turns out to have pretty extensive debug logging facilities which are somewhat valuable: https://www.chromium.org/for-testers/enable-logging/
For instance if the oomkiller decides to nuke a chrome tab (example selected for no reason whatsoever), the debug log will have an entry along the lines of
[...:WARNING::chrome/browser/ui/sad_tab.cc:256] Tab Killed: http://127.0.0.1:8069/
which is a much more helpful hint than just being told a test timed out (to say nothing of being told that chrome was not able to do dbus stuff when we never asked for that).
Because it can be useful for all sort of debugging, this log is saved not just when chrome fails to start, but also when a Chrome completes, successfully or unsucessfully (in the latter case it's logged as RUNBOT to be available from the runbot UI).
The chrome logging facilities are controlled by a new envvar `ODOO_BROWSER_LOG_VERBOSITY`, it can be set to `-1` to disable logging, or a strictly positive integer for ever increasing amounts of logging. At `1` chrome will log every network request it attempts which can be useful for debugging some races but is already extremely noisy.
Forward-Port-Of: odoo/odoo#255548
Forward-Port-Of: odoo/odoo#255054Resolved issues and error corrections
This update resolves an issue where the Modelo 390 BOE file generated for Spanish tax reports was being rejected by the AEAT portal. The fix ensures a default date format ('00000000') is used when a legal entity's procuration date is not specified, aligning with AEAT's requirements and allowing successful file uploads.
Original PR description
Steps to reproduce: - Install the `l10n_es_reports` module and switch to the `ES company`. - Go to Invoices and create an invoice with taxes, then confirm it. - Navigate to Accounting > Reporting >…
Steps to reproduce: - Install the `l10n_es_reports` module and switch to the `ES company`. - Go to Invoices and create an invoice with taxes, then confirm it. - Navigate to Accounting > Reporting > Tax Report. - From the smart button, select `Report: Tax Report (Mod 390) (ES)` and choose the year as `This Financial Year`. - Download the `BOE` file using the dropdown and fill the wizard fields (e.g., Natural Person – Name: Test, Principal activity: Test, Activity Code: 12345). - Upload the generated .txt file to the AEAT portal. (AEAT credentials are required) **Observation:** AEAT rejects the file with: `Caracteres no válidos '4. Representante - Personas Jurídicas - Represent. 1 - Fecha Poder (DDMMAAAA)'` **Root cause:** At [1], when `judicial_person_procuration_date` is `false`, an empty string is written to the BOE file, resulting in blank spaces in the exported file. This does not comply with AEAT’s required numeric format and causes the file to be rejected. **Fix:** This commit ensures the file contains '00000000' when `judicial_person_procuration_date` is false, complying with AEAT numeric format requirements. [1]: https://github.com/odoo/enterprise/blob/45d3a537c3b2eaccee425d959e89d26229e376cd/l10n_es_reports/models/aeat_tax_reports.py#L1696 opw-5995290 Forward-Port-Of: odoo/enterprise#109652
This update fixes an issue where payroll attendance calculations were incorrectly high when public holidays were present. The change ensures accurate attendance line amounts by properly accounting for public holiday hours during the calculation process. This improves payroll accuracy and reporting.
Original PR description
Fixes the calculation of the worked day lines amount, in cases where a public holiday is set. The current computation doesn't account for hours of public holiday when calculating the attendance amount; causing it to be higher than expected. This is caused by the calculation of work_time, which comes from the calendar data from _work_intervals_batch. If there is a public holiday, the work interval for that day is being removed from the result, causing it to wrongly calculate a lower work_time than expected and increasing the attendance line amount. task-5979501 Forward-Port-Of: odoo/enterprise#111741
This update resolves two issues preventing new employee creation in the Belgian payroll module. The first prevented saving a new employee with a start date, while the second caused errors when adding a wage. The fix ensures that employee records are created correctly and reliably.
Original PR description
First bug: Steps: - Switch to belgian company - Create new employee - Set contract start date - Click save manually -> boom Cause: in _trigger_l10n_be_next_activities, we create a new mail activity for the created employee which is already created in the default create function leading to duplicate follower records. Fix: in the super.create, pass the context variable mail_create_nosubscribe=True to disable adding the current user as a follower again to the same record Second bug: Steps: - Switch to belgian company - Create new employee - Set contract date - Add a wage then click anywhere -> boom Cause: _trigger_l10n_be_next_activities is called before the record is saved, hence trying to link to a null object Fix: check if the record is created before working on the activities Forward-Port-Of: odoo/enterprise#111780 Forward-Port-Of: odoo/enterprise#109799
This update enhances payroll processing, particularly for employees with changing contracts during a pay period. By layering payslip calculations and introducing new tools for tracking totals, the system now accurately handles contract adjustments, preventing overpayments and ensuring correct contribution calculations, especially in Hong Kong.
Original PR description
This commit aims to provide better support for contract changes that happen in the middle of a pay period. It has a few impacting changes, notably: 1) Payslip calculation sequencing As of now, all…
This commit aims to provide better support for contract changes that happen in the middle of a pay period. It has a few impacting changes, notably: 1) Payslip calculation sequencing As of now, all payslips of a same payrun have their line calculated all at once. While this is better for performances, it has a negative effect when a single employee has multiple payslips in the same payrun. In such cases, we may want or need for the payslips to know what was already calculated in the same payrun to avoid overpaying contributions or allowances that have caps. To solve this issue, we now group payslips by employee, sort them chronologically, and evaluate them in horizontal "layers": - Layer 1: Computes the 1st payslip for ALL employees simultaneously. - Layer 2: Computes the 2nd payslip for the subset of employees who have one, etc 2) More tools in HK payroll to support these cases The payslip rules now have a `l10n_hk_payrun_totals` dict that contains the total amount already reported in previous payslips of a same payruns for a selection of rules that needs it. We also provides a `worked_days_prorata_rate` which gives the ratio of worked days vs unworked days in a month for cases where we need to adjust amounts based on that ratio. 3) Rule updates The last part of the fix requires some updates in a few rules that are fixed amounts/not based on the wage and ends up being counted double in our use case. These rules will now take into account already computed amounts as said above to avoid going over the limit. In most cases it will only affect that specific use case, with a small exception for fixed mpf voluntary contributions, which have been updated to be prorated based on the worked days in the month. Forward-Port-Of: odoo/enterprise#111814 Forward-Port-Of: odoo/enterprise#111570
This update fixes an issue where currency rates for businesses in Bulgaria were incorrectly calculated due to a misinterpretation of data from the Bulgarian National Bank (BNB). The change ensures accurate EUR-to-unit and unit-to-EUR conversions, resolving a potential discrepancy in financial reporting. This update improves the reliability of currency calculations for our Bulgarian customers.
Original PR description
Issue: after Bulgaria switched to EUR, currency rate fetching from BNB was incorrectly set to still use reversed currency rates from the fetched XML, resulting in unit-to-EUR and EUR-to-unit rates being flipped in the database. Solution: adjusting the parser to get rate from 'RATE' rather than 'REVERSERATE', as the XML provides both. task-6050519 Forward-Port-Of: odoo/enterprise#111753 Forward-Port-Of: odoo/enterprise#111275
This update fixes a previous issue where users couldn't access worksheet properties within the Quality Check process. The changes now display the relevant worksheet tab and add a simple 'Validate' button, streamlining the workflow and improving the overall user experience. This enhances efficiency and clarity for users managing quality checks.
Original PR description
- Display the Worksheet tab to user in Quality Check and Maintenance Request form views when a worksheet template is set. Previously, the tab was hidden, preventing users from viewing or accessing the worksheet properties. - Added a Validate button in the Quality Check form view for worksheet-based checks, allowing users to validate directly based on worksheet property values Removed the Pass and Fail buttons in this case to streamline the validation flow and reduce user confusion. - Remove the worksheet template title from the Quality Check wizard when displaying worksheet properties to provide a cleaner interface. These changes ensure that users can easily access relevant worksheet properties and improve overall UI clarity. Community PR: [254794](https://github.com/odoo/odoo/pull/254794) Task Id: 5955976
This update fixes a persistent error that occurred when attempting to activate payments through Odoo. The issue stemmed from discrepancies between payment activation status on the provider side and Odoo, leading to a misleading error message. This change ensures payments are correctly activated within Odoo, improving payment processing reliability.
Original PR description
It may be possible that payments are activated on provider side / odoofin side and not on Odoo side, in that case when we want to activate the payments it leads to an userError but the value is never changed on the db so the error will continue to happen indefinitelly. task-5490817
This update resolves an issue where invoices for foreign customers (e.g., from Colombia) generated by Peruvian companies resulted in errors from SUNAT. The change ensures a default 'schemeID' of '0' is used for the receiver identification type, preventing invalid UBL/QR files and ensuring compliance.
Original PR description
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an…
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an empty l10n_pe_vat_code, since there are no cross-country dependencies between LATAM identification types. In that case, the generated UBL leaves the receiver identity type empty and SUNAT returns an error like: ``` 2015/2015 - El XML no contiene el tag o no existe informacion del tipo de documento de identidad del receptor... (missing schemeID value). ``` Odoo already defines schemeID = 0 for some foreign identification types in l10n_pe data, but it cannot cover identification types coming from other countries’ localizations (e.g. Colombia): https://github.com/odoo/odoo/blob/18.0/addons/l10n_pe/data/l10n_latam_identification_type_data.xml#L4 This change ensures that, when the partner is not from Peru and the PE VAT code is missing, we fallback the receiver identification type to "0" in: - PartyIdentification/ID/@schemeID - AccountingCustomerParty/AdditionalAccountID - the QR payload identification type field This prevents generating invalid UBL/QR content for foreign customers in multi-country setups. Forward-Port-Of: odoo/enterprise#110324 Forward-Port-Of: odoo/enterprise#105115
This update fixes an issue where project budget totals were incorrectly summing expenses and revenue. The fix adjusts how budget amounts are calculated to ensure accurate totals are displayed on the project dashboard, reflecting the true financial status of the project. This improves reporting accuracy and financial oversight.
Original PR description
### Steps to reproduce: - Create a billable project - Create two budgets one expense and the other revenue or both each for 100$ - Create a vendor bill with the analytic account of the created project - Notice in the project dashboard the two budgets are summed up in the total ### Cause: When calculating the total spent and total allocated we add up the amount whether it is an expense or revenue. https://github.com/odoo/enterprise/blob/1dccb87a48ac44735da4c78594e37d4783789cd6/project_account_budget/models/project.py#L120-L121 ### Fix: Set the expense budget to -ve and the revenue/both to +ve amount when calculating the total spent and total allocated opw-5488131 Forward-Port-Of: odoo/enterprise#106504
This update corrects a legal requirement for invoices generated using the l10n_gt_edi module. Previously, essential 'complementos' data were missing from the PDF invoices for specific document types (FCAM, FCAP, FESP), while they were present in the XML files. This ensures compliance with Guatemalan tax regulations.
Original PR description
**PROBLEM** For some documents types, the "complementos" are not present in the pdf while they are present in the xml. It's legally required that they are added in the pdf. **STEP TO REPRODUCE** 1. Install l10n_gt_edi. 2. Create an customer invoice. 3. Set the document type to FCAM, FCAP, or FESP. 4. Send the invoice using the cfdi. 5. download the xml and the pdf, notice the complementos are in the xml, but not in the pdf. opw-5970285 Forward-Port-Of: odoo/enterprise#109061
This update corrects an issue preventing Romanian SAFT reports from passing validation. The team restored a key data element and used a sanitized bank account number, ensuring compliance with Romanian tax regulations. This resolves a technical problem that could have impacted report accuracy and processing.
Original PR description
Problem --------- In odoo/odoo#184131 and odoo/enterprise#72206, UOM's categories where removed. Along side the removal, the Description tag in the Romanian SAFT UOM table tag. However, without this node, the SAFT is flagged as invalid by validator in Romanian. Furthermore, in the RO SAF-T, we use the bank account number and not the sanitized one, which may lead to some spaces in the document. Spaces that are not accepted either. Solution --------- Add back the Description node and use the UOM name instead of category. Use the sanitized account number. opw-5956277 Forward-Port-Of: odoo/enterprise#111664
This update resolves a bug where custom snippets created in the website builder didn't correctly display their dynamic content in the preview. The fix ensures that dynamic content is properly reflected when previewing custom snippets, addressing a previous issue related to the website builder refactor. This improves the user experience when creating and testing dynamic website content.
Original PR description
The interaction for filling the dynamic content of dynamic snippets did not run inside the iframe to preview the snippet to add. This is not an issue for the initial dynamic snippet, as they are…
The interaction for filling the dynamic content of dynamic snippets did not run inside the iframe to preview the snippet to add. This is not an issue for the initial dynamic snippet, as they are filled with fake content. But when saving a custom snippet, the dynamic content is cleared, and they seem empty when previewed. This is the case since the [website builder refactor] as the previous builder re-used the preview of the initial snippet. This commit adds the interaction to fill dynamic content in the preview iframe, and changes the interaction to avoid emptying the fake content from initial dynamic snippets during preview. Steps to reproduce: - Open website builder - Add a dynamic snippet (for example "Events") - Save the snippet as a custom snippet - Click on "Custom" snippet category - Bug: The preview for the custom snippet does not have the dynamic part (there is no event, just the title) [website builder refactor]: 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-5427353 Forward-Port-Of: odoo/enterprise#110696 Forward-Port-Of: odoo/enterprise#108912
This update fixes a bug preventing the proper synchronization of XML documents (like e-invoices) related to accounting moves. Previously, invoices created from various sources didn't always attach the original XML files to the Documents app, leading to data discrepancies. Now, all XML attachments are correctly linked, ensuring accurate document tracking.
Original PR description
[FIX] documents_account: sync all XML documents for account moves Before this commit, the synchronization between accounting attachments and the Documents app was incomplete regarding XML files…
[FIX] documents_account: sync all XML documents for account moves Before this commit, the synchronization between accounting attachments and the Documents app was incomplete regarding XML files (e.g., e-invoices, Peppol). This caused several specific issues: 1. When creating an invoice via the Accounting upload interface, only the generated PDF was synced to the correct Documents folder, leaving the original XML file unsynced. 2. When creating an invoice from an existing file in the Documents app (via server action), the system correctly synced the generated PDF, but failed to move or sync the original XML source file to the target folder. 3. When receiving vendor bills via Peppol or other EDI networks, the proxy attaches the fetched XML to the `account.move` via an `ir.attachment` write. Because this bypassed the existing sync filters, the Peppol XMLs were never pushed to the Documents app. This commit updates the `ir.attachment` logic in both `create` and `write`. It ensures that whenever an XML file (mimetype `application/xml` or `text/xml`) is attached to an `account.move`—regardless of the move type or whether it was uploaded manually or fetched via EDI—the document synchronization logic is triggered, properly linking and filing the XML alongside the PDF. Task-5909245 Task-5917535 Forward-Port-Of: odoo/enterprise#111881 Forward-Port-Of: odoo/enterprise#106574
This update corrects a display issue where the 'Pick Up in Store' option was incorrectly shown for products with excluded tags. The fix ensures that unavailable delivery methods aren't presented to customers, maintaining a consistent and accurate shopping experience. This improves usability and prevents customer confusion.
Original PR description
Currently, when a product has a tag that is configured as an Excluded Tag on the Pick Up in Store delivery method, the method is still shown on the product page. Steps to produce: --- - Install…
Currently, when a product has a tag that is configured as an Excluded Tag on the Pick Up in Store delivery method, the method is still shown on the product page.
Steps to produce:
---
- Install `website_sale` module.
- Enable `Click and Collect` in settings.
- Go to `website > ecommerce > products > product tags.`
- Create a new tag and add a product in product template.
- Go to` website > configuration > ecommerce > delivery method.`
- Open` pick up in store`:
- In the `Stores` tab, set your company warehouse.
- In the `Availability` tab, add the created tag to Excluded Tags.
- Publish the delivery method.
- Open the tagged product on the website.
Issue:
---
- The Pick Up in Store option is still displayed on the product page, even though the product has a tag listed in the carrier’s Excluded Tags.
Root cause:
---
- Here at [1], the method `_get_additional_combination_info ()` does not check whether the product has tags that are excluded by the delivery method.
- However, at [2], during checkout, the exclusion works correctly because `_match_excluded_tags` in `delivery.carrier` filters the carrier based on excluded tags.
Solution:
---
- Hide the Pick Up in Store option when the product has tags excluded
for that delivery method. This keeps the behavior consistent across
the website, avoids showing unavailable delivery options, does not
impact other flows and aligns with the existing behavior during
checkout.
[1]https://github.com/odoo/odoo/blob/1c483c3a8d7d079bd34a378f9f8716551e4bab93/addons/website_sale_collect/models/product_template.py#L17-L21
[2]https://github.com/odoo/odoo/blob/1c483c3a8d7d079bd34a378f9f8716551e4bab93/addons/delivery/models/delivery_carrier.py#L192-L194
opw-5921268
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#255482
Forward-Port-Of: odoo/odoo#250837This update resolves issues preventing the preview record field in email templates from functioning correctly. Specifically, it corrects a data access error and ensures the record selector remains visible when removing records, improving the email preview experience. This ensures users can accurately preview their email templates.
Original PR description
Steps to reproduce =============== Issue 1 --------- 1. Open any email template's form view 2. Click the `Preview` button -> Preview wizard will open 3. Remove the record from the record selector 4.…
Steps to reproduce =============== Issue 1 --------- 1. Open any email template's form view 2. Click the `Preview` button -> Preview wizard will open 3. Remove the record from the record selector 4. Click the next button of the pager. -------> Traceback Issue 2 --------- 1. Open email marketing 2. Open any mailing 3. Click the `Preview & Test` button -> Preview wizard will open 4. Remove the record from the record selector. -------> Record selector and the pager will disappear. Technical ======== Issue 1 ---------- The [line] mistakenly used `display_name` instead of `displayName` to access from the record, making the _first_ record's display_name `undefined`. When we switch to the next record, the code used the resModel of the current record raising the error through `update -> _update -> _preprocessReferenceChanges -> _completeMany2OneValue -> webRead`, the cause being the `undefined` value of resModel passed to the `webRead`. Notably, this problem would've been omitted if: -> `display_name` of the first record wasn't `undefined` as it would've prevented the call to `_completeMany2OneValue` or -> use the `getRelation` method as `resModel` of the reference field while updating. After this commit, we make sure to apply the above both points. Issue 2 ---------- The reference field sets the `relation` of the current field from the current value or the provided `model_field`. When unsetting the record, the current value is set to `false`. Therefore, the `relation` value is `undefined` making the record selector disappear (See [Ref]) After this commit, we add the computed `model_id` field to the wizard's model and provide it to the preview record field. [line]: https://github.com/odoo/odoo/blob/07378556a633f50938c92b7abe094cf2adf43c2c/addons/mail/static/src/views/web/fields/mail_preview_record_field/mail_preview_record_field.js#L24 [Ref]: https://github.com/odoo/odoo/blob/35785af180c68075a94f3f1464b8dddf526a0646/addons/mail/static/src/views/web/fields/mail_preview_record_field/mail_preview_record_field.xml#L5 Task-5944834
A recent issue caused user mail inboxes to crash when accessing multiple companies. This fix addresses a permissions problem that prevented notifications from being properly processed, leading to inbox lockups. The update ensures that users can reliably access their mail regardless of the company they're working with.
Original PR description
### Issue: Due to this bug, user's inbox can crash and become inaccessible by another user. #### Steps to reproduce: 1- Create a db with two companies and sale installed with demo data. 2- Demo user should only have access to company A 3- Demo user preference should be handle in Odoo 4- Admin should access both companies 5- Create a partner called partner_b with company set to company B 6- Using admin create a SO in company B, with the partner_b 7- Send a message (not internal note) in SO chatter, and mention Demo user 8- Login using Demo user 9- Open discuss app. As you see the inbox is not accessible anymore. ### Cause: This is caused because Demo user doesn't have read access to partner_b. This cause issue in adding notification for partner_b. https://github.com/odoo/odoo/blob/6e262e8cf7666216305a04f92c213578452fd652/addons/mail/models/mail_message.py#L1042-L1064 opw-5089738 Forward-Port-Of: odoo/odoo#252298 Forward-Port-Of: odoo/odoo#232894
This update resolves an issue preventing users from editing multiple stock counts simultaneously in the Physical Inventory list view. The fix synchronizes the editing process, allowing users to accurately update quantities in bulk. This improves efficiency and reduces manual data entry for stock adjustments.
Original PR description
# How to reproduce - Go to the Pysical Invetory list view - Select more than one record - In the Counted field, try to type a two digit number # The problem A popup asking for confirmation for…
# How to reproduce - Go to the Pysical Invetory list view - Select more than one record - In the Counted field, try to type a two digit number # The problem A popup asking for confirmation for editing a field is shown before the user has the time to type in the other digits. This makes it so it is not possible to input a number that has more than one digit. # Cause The Counted (invetory_quantity) field in the list view uses a special widget (CountedQuantityWidgetField). This widget has the responsability to set the inventory_quantity_set field to true when the the value of the inventory_quantity field is updated. The inventory_quantity_set field is updated on input : https://github.com/odoo/odoo/blob/f450bb6379b5c0354c048abcc688428d8bff1172/addons/stock/static/src/widgets/counted_quantity_widget.js#L33-L35 The inventory_quantity field is updated on blur : https://github.com/odoo/odoo/blob/f450bb6379b5c0354c048abcc688428d8bff1172/addons/stock/static/src/widgets/counted_quantity_widget.js#L44-L49 This does not make a lot of sense, because we tell the backend that the quantity has been changed before sending the new quantity. This was not really an issue before but starting in 19.0, this commit (https://github.com/odoo/odoo/commit/9f0470b48e4e8c783513788e269ad16cbf84b7af) made the Physical Invetory list view multi-editable, highlighting the desynchronization This fix aims to resynchronize the editing of both of theses values, allowing the bulk edit at the same time. opw-5908205 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254399
This update optimizes how Odoo calculates inventory values, specifically for large warehouses. By directly using valued locations instead of redundant expansion, the process is significantly faster. This change reduces the time taken to generate inventory valuation reports, improving overall system performance.
Original PR description
To compute the inventory valuation report, stock_account builds a valuation context through `_with_valuation_context()` and passes the valued internal/transit locations to stock quantity computation.…
To compute the inventory valuation report, stock_account builds a valuation context through `_with_valuation_context()` and passes the valued internal/transit locations to stock quantity computation. Without `strict=True`, stock quantity domains treat these locations as hierarchical anchors and expand them again through the location tree. This is redundant in this specific call site because `_with_valuation_context()` already provides the valued locations to filter on. On databases with a large location tree, this extra expansion makes the inventory valuation load much slower than necessary. Using `strict=True` makes quantity computation use the provided valued locations directly. ### Benchmark: - active products: 5912 - stock moves: ~785k - internal locations: 4213 | Before | After | |---------|--------| | 99.285s | 1.853s | opw-5944584 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254354 Forward-Port-Of: odoo/odoo#253656
This update fixes a bug where duplicating a manufacturing order (MO) would incorrectly link a new purchase order to the wrong quantity, leading to inaccurate inventory counts. The fix prevents the MO reference from being copied during duplication, ensuring purchase orders are correctly associated with the intended production order. This improves data accuracy and reduces potential order fulfillment issues.
Original PR description
Steps to reproduce the bug:
- Create a storable product "P1" with the following BoM:
- Component: C1 with the following routes: - Buy + MTO
- Create a MO to produce one unit of P1:
- Confirm the MO -> a purchase order is created because the component uses MTO
- Duplicate the MO
Problem:
A new MO is created, but the reference is copied. As a result, the purchase order becomes linked to the new MO and the quantity in the purchase order line is updated from 1 to 2 units.
Explanation:
When the purchase order is created, the MO reference is stored on the PO, which links both records together. Since the reference is also copied when duplicating the MO, the new MO is incorrectly linked to the same purchase order.
opw-5873769
Forward-Port-Of: odoo/odoo#255335This update corrects an issue where two separate RFQs were generated for subcontracting orders, leading to inefficiencies. The change ensures that a single, shared stock reference is used for manufacturing orders, streamlining the RFQ process and preventing duplication. This improves the grouping of RFQs for better order management.
Original PR description
Steps to reproduce: - Go to Azure Interior contact form: - Sales & Purchase tab > Group RFQs > Always - Create a storable product "P1": - Route: Resupply Subcontractor - BoM: - Type: Subcontracting -…
Steps to reproduce:
- Go to Azure Interior contact form:
- Sales & Purchase tab > Group RFQs > Always
- Create a storable product "P1":
- Route: Resupply Subcontractor
- BoM:
- Type: Subcontracting
- Component: C1 with Dropship route and azure interior as vendor
- Create a storable product "P2":
- Route: Resupply Subcontractor
- BoM:
- Type: Subcontracting
- Component: C2 with Dropship route and azure interior as vendor
- Create a purchase order with one unit of P1 and P2
- Confirm the purchase order
Problem:
Two RFQs are generated (one for C1 and one for C2) instead of a single grouped RFQ.
When confirming the purchase order, a stock reference is created and assigned to it. This reference is correctly propagated to the picking and stock moves.
However, when the two manufacturing orders are created, new stock references are generated instead of reusing the original one. As a result, each MO ends up with a different reference:
https://github.com/odoo/odoo/blob/2713876dbc70d3984e584a9037a2206dcda4e84a/addons/mrp_subcontracting/models/stock_picking.py#L69-L72
This prevents from grouping RFQs, since the grouping logic relies on identical references. When the first RFQ is created for C1, it uses the MO reference, and when searching for a candidate RFQ for C2, none is found due to the reference mismatch:
https://github.com/odoo/odoo/commit/77dc92e4a0db0575a1a0e865cdd0c82978d593f6#diff-201f9fd7ec1067f7530aafeaa88420021930be82ce89e912d595ed55bb885f26R370-R372
Solution:
Reuse existing stock references when creating subcontracting MOs instead of creating new ones.
opw-5895378
Forward-Port-Of: odoo/odoo#254327This update resolves an issue where using a delivery address in the POS for invoicing incorrectly calculated Cost of Goods Sold (COGS). The fix ensures accurate COGS tracking by correctly linking the invoice to the relevant stock movements, aligning with Anglo-Saxon accounting practices. This prevents inaccurate financial reporting.
Original PR description
When a delivery address is selected as the customer in the POS UI and an invoice is generated from the POS order, it results in two different `partner_id` being set on the `pos.order` and the…
When a delivery address is selected as the customer in the POS UI and an invoice is generated from the POS order, it results in two different `partner_id` being set on the `pos.order` and the `account.move`. It is expected, as a delivery address cannot logically be used as an invoicing address. Anglo-saxon accounting registers the COGS with additional account.move.line on the invoice and, when using real time valuation, the balance of these lines is calculated from values found on the corresponding `stock.move`. Currently, the `stock.move` cannot be found if the `partner_id` on the `pos.order` and the `account.move` are different. The system then falls back on the `standard_price` of the `product_id`, which is incorrect. In version 19+, the `product_id` used to calculate the unit price is fetched from the `stock.move` but, because it's an empty recordset, the balance of the COGS is 0 and the lines are not created. An easy fix could be to remove this check of equivalence between the two `partner_id`. The invoice is created directly from the POS order anyway. I am not sure why it is necessary. Am I missing something? Steps to reproduce: 1. Create a product with fifo and automated valuation. Make sure that the product type is storable. 2. Validate one purchase and its delivery for the product (qty 5, unit price 5). 3. Validate another purchase and its delivery for the product (qty 5, unit price 10). 4. Configure the point of sale to allow invoicing. 5. Open a pos session then sell 1 item of the product. Select a delivery adress as the customer and generate an invoice. 6. Since the product is fifo, this means that the cost of goods sold is 1 * 5. 7. The correct expense account line should have balance of 5.0. 8. The correct output account line should have balance of -5.0. 9. The COGS lines instead have a balance of 8.13 and -8.13 which corresponds to the standard price of the product at the time of the invoice. Related ticket: opw-5467877 Forward-Port-Of: odoo/odoo#245208
This update corrects a validation issue that prevented invoices with Recupel taxes applied to negative lines from generating valid XML files for Peppol transmission. The fix ensures that negative fixed taxes are correctly identified as allowances, resolving a compatibility problem with PEPPOL standards. This ensures accurate invoice processing and compliance.
Original PR description
**PROBLEM** If you set a recupel tax (fixed tax affecting base) and use it on a negative line, the generate xml will not pass validation. **STEP TO REPRODUCE** 1. Setup Peppol. 2. Create a recupel tax (fixed tax of 1€, affecting the base). 3. Create an invoice with a negative line, with a VAT and the recupel tax. 4. Send the invoice using peppol, and validate the xml. 5. Notice the xml doesn't pass validation. **CAUSES** 1. The negative fixed tax should be an allowance, but is marked as a charge in the xml. 2. Only fixed taxes that are charges influences the line_extension_amount, but it should also be the case with negative fixed taxes. 3. Negative fixed taxes should have a ChargeAllowanceReasonCode that is in the AllowanceReasonCode list. opw-5955289 Forward-Port-Of: odoo/odoo#255436 Forward-Port-Of: odoo/odoo#252716
This update resolves a validation error occurring when generating Peppol invoices with Belgian company settings. The fix addresses a rounding discrepancy in the invoice data, ensuring the XML output complies with VAT regulations. It achieves this by explicitly declaring rounding amounts in the XML.
Original PR description
**Steps to reproduce:** - Install Accounting and l10n_be - Switch to a Belgian company (e.g. BE Company CoA) - In Accounting settings: * activate Peppol * set "Rounding Method" to "Round Globally" -…
**Steps to reproduce:**
- Install Accounting and l10n_be
- Switch to a Belgian company (e.g. BE Company CoA)
- In Accounting settings:
* activate Peppol
* set "Rounding Method" to "Round Globally"
- Create an invoice:
* Customer: [a Belgian customer with a VAT]
* Invoice Lines:
| Label | Quantity | Price | Taxes |
| ------- | ---------- | ------- | ------- |
| Line 1 | 1.0 | 90.30 | 0% |
| Line 2 | 0.45 | 2.54 | 6% |
| Line 3 | 0.28 | 6.87 | 6% |
- Confirm the invoice
- Send the invoice to Peppol
**Issue:**
The generated XML has a line with `<cbc:LineExtensionAmount>` set to 90.31, `<cbc:InvoicedQuantity>` set to 1.0 and `<cbc:PriceAmount>` set to 90.30, which fails the validation with the following error:
`[BR-E-08]-In a VAT breakdown (BG-23) where the VAT category code (BT-118) is "Exempt from VAT" the VAT category taxable amount (BT-116) shall equal the sum of Invoice line net amounts (BT-131) minus the sum of Document level allowance amounts (BT-92) plus the sum of Document level charge amounts (BT-99) where the VAT category codes (BT-151, BT-95, BT-102) are "Exempt from VAT".`
**Cause:**
The use of decimal number in quantity generates a 0.01 rounding difference in the base amounts.
The extra cent is dispatched in one of the `<cbc:LineExtensionAmount>` node.
**Solution:**
There is no easy solution to handle these rounding cases. The solution used in this fix is to handle the extra cents as if they are cash rounding amount and declare them in `<cbc:PayableRoundingAmount>` node.
opw-5933545
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#255224
Forward-Port-Of: odoo/odoo#253625This update resolves an issue where a down payment line was incorrectly added twice to POS order settlement. When automatic invoicing is enabled and online payments are processed, the system was creating duplicate down payment records. This fix ensures that only one down payment line is created, streamlining the order settlement process and improving data accuracy.
Original PR description
Case 1: --- **Steps to produce:** - Install `pos_sale` module. - Enable `Automatic Invoice` in settings - Create a new SO with product price 1000. - In `Other Info`, set `Online Payment` to 30%. -…
Case 1: --- **Steps to produce:** - Install `pos_sale` module. - Enable `Automatic Invoice` in settings - Create a new SO with product price 1000. - In `Other Info`, set `Online Payment` to 30%. - Preview > make payment > down payment of 300 is created in SO. - In POS, open Furniture Shop register > Actions > Quotation/Order > select the SO > settle order. **Issue:** - The down payment line is added twice in the POS order. **Root cause:** - At [1], `sale_order.amount_paid` = 300, so `addDownPaymentProductOrderlineToOrder` adds the line in order. - At [2], the down payment line from the SO is added again. - Here, when `Automatic invoice` is on and we make the online payment then `amount_paid` is updated and the downpayment invoice is also created. - So, we have also downpayment line in sale order also. **Solution:** - Ensure that if a downpayment line has already been added to the POS order, the first downpayment line matching `amount_paid` is skipped. [1]: https://github.com/odoo/odoo/blob/54a62bdbe927108a7f85374db26787f8ba45f6ac/addons/pos_sale/static/src/overrides/models/pos_store.js#L88-L93 [2]: https://github.com/odoo/odoo/blob/54a62bdbe927108a7f85374db26787f8ba45f6ac/addons/pos_sale/static/src/overrides/models/pos_store.js#L109-L111 Before: <img width="484" height="279" alt="image" src="https://github.com/user-attachments/assets/c803c9bd-0751-4a90-81f4-8fb3da3b393e" /> After: <img width="490" height="235" alt="image" src="https://github.com/user-attachments/assets/2ec4ac43-1db3-4c2e-bfcf-8c52a4830dac" /> Case 2: --- **Steps to produce:** - Install `pos_sale` module. - Enable `Automatic Invoice` in settings - Create a new SO with product price 1000. - In `Other Info`, set `Online Payment` to 30%. - Preview > make payment. **Issue:** -The computed value of amount_unpaid is 400, whereas it should be 700. **Root cause:** - When Automatic Invoice is enabled and an online payment is made, the invoice is automatically created and amount_paid is also updated. - At [3], the logic subtracts both the total invoice amount and amount_paid from the actual total, which results in an incorrect calculation. **Solution:** - When an online payment is made, a transaction is created and linked to an invoice. - While computing the total invoice amount, if the transaction’s invoice ID is encountered again, it should be skipped to avoid double-counting. [3]: https://github.com/odoo/odoo/blob/75f6be6744006ed1a3c0857881822723f90f5d4a/addons/pos_sale/models/sale_order.py#L46-L51 opw-5415404 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255474 Forward-Port-Of: odoo/odoo#242026
This update ensures that when replenishing stock from one warehouse to another (using the 'resupply' feature), the delivery address correctly reflects the destination warehouse. Previously, the delivery address wasn't being set properly, causing issues with tracking stock movements. This fix resolves a bug related to how the system handles stock replenishment across warehouses.
Original PR description
### Steps to reproduce: - Ensure that sale_stock is installed - In the settings enable Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Warehouses - Create a second warehouse…
### Steps to reproduce: - Ensure that sale_stock is installed - In the settings enable Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Warehouses - Create a second warehouse WH2 and enable: Resupply from WH1 - Create a physical product using the route: Resupply from WH1 - Click on the product form cog wheel icon > Replenish - Replenish 1 unit to warehouses 2 #### > The delivery that was created from WH1 to the inter company transit location does not set the `partner_id` (delivery address) to the partner of warehouse 2. ### Cause of the issue: Triggering the replenish will create a move chain relying on the `_run_pull` mechanich. In particular, the receipt move will be created first from Inter-company transit to `WH2/Stock` without `partner_id`: https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/stock/models/stock_move.py#L1709 https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/stock/models/stock_move.py#L1674-L1677 Then, during its confirmation, the delivery move from WH1/Stock to the intercompany transit location will be created based on the rule and, thanks to these lines: https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/stock/models/stock_rule.py#L342-L349 The `partner_id` of WH2 will be set as the `partner_id` of the delivery. Since there is a single partner this will also set the partner of the `move_values` of the delivery move we are creating to this partner: https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/stock/models/stock_rule.py#L355-L360 However, if `sale_stock` is installed that `move_value` is reset to the value provided by the procurement values just a few lines bellow: https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/stock/models/stock_rule.py#L381-L384 because the `partner_id` field is part of the field name returned by the `_get_custom_move_fields`: https://github.com/odoo/odoo/blob/b9845f693af28e1d9fac773ae391b29f6831e982/addons/sale_stock/models/stock.py#L173-L176 Since the `partner_id` value provided by the procurement values was `False`, it resets the the `partner_id` creation value to `False`. ### Fix: As the flow relies on the value provided here: https://github.com/odoo/odoo/blob/c4f8eb2824bef7348e3f94031140450daa4df651/addons/stock/models/stock_rule.py#L342-L349 when `sale_stock` is not installed but relies on the value of the procurement provided here: https://github.com/odoo/odoo/blob/c4f8eb2824bef7348e3f94031140450daa4df651/addons/stock/models/stock_move.py#L1709 https://github.com/odoo/odoo/blob/c4f8eb2824bef7348e3f94031140450daa4df651/addons/stock/models/stock_move.py#L1674-L1677 if `sale_stock` is installed, it is necessary that both provide the same value to keep coherence in the flow. However, since the partner is will be expected to be set also via the procurement values, it is necessary to adapt the condition to which we will set a partner on the reception of the inter-company-transit: https://github.com/odoo/odoo/blob/c4f8eb2824bef7348e3f94031140450daa4df651/addons/stock/models/stock_rule.py#L349 Which is the reason why we moved this line should be triggered only if no partner was set by the procurement values. opw-6034309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254855
This update fixes a bug where custom snippets didn't display their dynamic content in the preview. The change ensures that dynamic snippet data is correctly reflected when previewing custom snippets, improving the website builder experience and allowing users to accurately see the content they're creating.
Original PR description
*: website_blog, website_event, website_sale The interaction for filling the dynamic content of dynamic snippets did not run inside the iframe to preview the snippet to add. This is not an issue for…
*: website_blog, website_event, website_sale The interaction for filling the dynamic content of dynamic snippets did not run inside the iframe to preview the snippet to add. This is not an issue for the initial dynamic snippet, as they are filled with fake content. But when saving a custom snippet, the dynamic content is cleared, and they seem empty when previewed. This is the case since the [website builder refactor] as the previous builder re-used the preview of the initial snippet. This commit adds the interaction to fill dynamic content in the preview iframe, and changes the interaction to avoid emptying the fake content from initial dynamic snippets during preview. Steps to reproduce: - Open website builder - Add a dynamic snippet (for example "Events") - Save the snippet as a custom snippet - Click on "Custom" snippet category - Bug: The preview for the custom snippet does not have the dynamic part (there is no event, just the title) [website builder refactor]: 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-5427353 Forward-Port-Of: odoo/odoo#253985 Forward-Port-Of: odoo/odoo#246328
This update ensures that thread unread counters accurately reflect the number of unread messages in the Inbox, even after refreshing the page. Previously, the counters were incorrect after a refresh, leading to misleading information. This fix improves the user experience by providing accurate thread status.
Original PR description
***: test_discuss_full** **Description of the issue this PR addresses:** Thread unread counters should reflect the actual backend state as soon as Inbox messages are loaded, not only after a new bus…
***: test_discuss_full** **Description of the issue this PR addresses:** Thread unread counters should reflect the actual backend state as soon as Inbox messages are loaded, not only after a new bus notification is received. **Steps to Reproduce:** - Log in as User A and User B. - Ensure User A preferences set to Handle in Odoo. - From User B, mention User A in the chatter of a record. - From User A, Open the messaging menu, counter for that related thread is correct. - Refresh the page. - Open the messaging menu again, the thread now shows a grey badge instead of the expected unread counter. **Current behavior before PR:** - When loading Inbox messages, related `mail.thread` records (such as project.task) did not include unread counters in the store payload. As a result, threads that already had unread messages appeared as (grey badge) after a refresh, leading to an incorrect counter state. - Additionally, frontend-only counter adjustments could sometimes lead to inconsistent or even negative unread values due to missing initial sync. **Desired behavior after PR is merged:** - Threads with existing unread messages now receive the correct counter state, when Inbox messages are fetched. - This also prevents inconsistent or negative counter values caused by frontend-only updates. - This also ensures updating the `inbox query list` and corresponding `query count`: task-[5474143](https://www.odoo.com/odoo/project/1519/tasks/5474143) Before/After (**on refresh**): <img width="461" height="55" alt="image" src="https://github.com/user-attachments/assets/2fc57aba-049c-4129-95b1-1d2b2770ac66" /> <img width="469" height="57" alt="image" src="https://github.com/user-attachments/assets/111d10bb-2aec-4711-8f5a-af7f332021d8" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252611 Forward-Port-Of: odoo/odoo#247569
This update corrects a bug where manual Stripe SEPA payments were immediately canceled, even when the transaction was pending. Previously, this caused subscriptions to close after a delay. The fix ensures payments remain in a 'pending' state until the Stripe transaction is confirmed, preventing subscription closures.
Original PR description
**Problem:** When manually registering a payment using a Stripe SEPA Direct Debit token, the associated `account.payment` is immediately canceled, even though the Stripe transaction is in "Pending"…
**Problem:** When manually registering a payment using a Stripe SEPA Direct Debit token, the associated `account.payment` is immediately canceled, even though the Stripe transaction is in "Pending" status. Later, when Stripe confirms the transaction, the payment remains canceled, leading to subscription closures after 90 days of apparent non-payment. **Steps to reproduce:** 1) Set a customer address to Belgium and add a SEPA Direct Debit payment token via Stripe. 2) Change the company currency to euro. 4) Create a manual invoice for that customer. 5) Pay the invoice using the pre-configured Stripe SEPA token. 6) Observe the `account.payment` is immediately canceled despite the transaction being "Pending". 7) When Stripe confirms the transaction, the payment stays canceled. **Cause:** In `account_payment.action_post()`, after sending the payment request, all payments whose transaction state was not `done` were canceled. For asynchronous payment methods like SEPA Direct Debit, the transaction starts in `pending` (not `done`), so the payment was wrongly canceled. **Solution:** - Only cancel payments whose transaction ended in a failure state (not in `done`, `pending`, or `authorized`), so pending/authorized payments stay in draft/in_process. **NOTE** In v19.2 the states naming got changed by this commit https://github.com/odoo/odoo/commit/34280f6e14e291ba4414eaf6d00d1cee7bbdac5b so now a payment state is set to "paid" no "in_process" after the `payment.action_post()` opw-5934381 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253876
This update fixes an issue where snippet dropzones weren't correctly activated within the editor, preventing users from adding certain snippets to specific areas. The change ensures that dropzones are now dynamically determined by the selected snippet, resolving a conflict where sanitization rules were bypassed. This improves editor functionality and allows for more accurate snippet placement.
Original PR description
Before this commit, the dropzones activated would not always be correct clicked on a group and then selected a snippet. The dropzones would be determined based on a default section and not based on the selected snippet. Therefore, even though there could be rules preventing a snippet from behing in a certain dropzone, the dropzone would still be activated because the snippet chosen would not be taken into account. This commit fixes the issue by using the chosen snippet to activate the dropzones. task-5428387 Forward-Port-Of: odoo/odoo#240547
This update optimizes the process of exporting financial data (FEC) from large Odoo databases. Previously, the entire export file was loaded into memory, causing potential errors. Now, the data is streamed to the user, improving performance and preventing memory issues for complex transactions.
Original PR description
On large databases (millions of account moves), The FEC exported file can be huge. This resulted in memory error since at some point we have the entire file in memory. This commit aims to overcome this issue by streaming the content of the file to the user. task-5404142 Forward-Port-Of: odoo/odoo#254683 Forward-Port-Of: odoo/odoo#240981
This update resolves a frequent issue where EU tax ID checks failed due to VIES server errors, particularly in France. We’ve switched to a more reliable system using the IAP server, which automatically updates tax ID validity. This ensures accurate intra-com processing and enhances data integrity.
Original PR description
Currently, when changing the Tax ID of a partner that is another EU country, we perform a VIES check to know whether it is valid (i.e. can do intra-com). However, it is often the case that the VIES check fails because of an internal error on their side (timeout, max concurrent update, ...), especially for France. Instead, we will now use the IAP server which stores the validity of a Tax ID for some time. If the IAP server does not have the info (because VIES is down), we will not actively wait. Instead, IAP will perform a push to a webhook on the client database once it has the information. For security purposes, an HMAC is generated and sent to IAP so that only IAP can contact the db with the up-to-date info, and not anyone on the internet that calls this new webhook. task-5977584 PR IAP: https://github.com/odoo/iap-apps/pull/1473 Forward-Port-Of: odoo/odoo#255279 Forward-Port-Of: odoo/odoo#251988