Thursday, March 12, 2026
26 changes · saas-19.1
New functionality added to Odoo
This update introduces support for accepting MPESA payments in Kenya through two methods: Express and Lipa Na Mpesa. These integrations allow businesses to accept payments via mobile apps and QR codes, streamlining the checkout process for customers using Safaricom.
Original PR description
This pr introduces MPesa payment methods using Safaricom APIs for Kenya. There are two types of payment methods : - Mpesa Express: This is implemented with the M-Pesa Express API. It's the Merchant…
This pr introduces MPesa payment methods using Safaricom APIs for Kenya. There are two types of payment methods : - Mpesa Express: This is implemented with the M-Pesa Express API. It's the Merchant Initiated payment method. The merchant create a payment method M-Pesa Express with Safaricom payment provider. The merchant is allowed to ask for payment through the API with an USSD prompt on the customer phone number. Customer enters the PIN and the API call the callback of the POS to reconcile transaction with order. (https://daraja.safaricom.co.ke/dashboard/apis?api=MpesaExpressSimulate) - Lipa Na Mpesa: This is implemented with the Customer To Business (C2B) API. This payment method is different from the first one. It is a Merchant-Initiated payment method. The POS registers callback URLs through the register URL. The POS listen on its callbacks. Customer sends a payment through his Safaricom or MPesa application with some informations of the business. When a transaction is catch in the callback, POS displays it. The cashier needs, manually, to reconcile it with the current order. To reconcile, cashier see a popup with every transaction done on this business account number. (https://daraja.safaricom.co.ke/dashboard/apis?api=CustomerToBusiness) Dynamic QR Code API is also implemented to allow customers to scan the QR Code in the official Safaricom application and send the payment easily without errors of amount or till number. (https://daraja.safaricom.co.ke/dashboard/apis?api=DynamicQRCode) Note : The problem with this payment method is that there is two steps. The first step is a "Verification" step, which is optional. Businesses needs to manually sends an email to Safaricom to allows them to add this step. This step is useful because it is used to accept or reject a transaction before charging the customer. But, in reality, not all of the businesses ask Safaricom to add this step. So, we don't configure it for the moment. The second step is the "Confirmation" step, before this step, the customer is already charged. The API sends transaction data to the POS, we display it in the POS to allow cashier to reconcile the current order with a transaction. Requirements : If you want to test this API, https is needed and a valid kenyan (+254) phone number is also needed. But, you can simulate requests in the Daraja Portal. (https://daraja.safaricom.co.ke/dashboard/apis) task: 5886047 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247615
Enhancements to existing features
This update enhances the testing of accrual calculations within the US HR Payroll module, ensuring accurate leave tracking. It also addresses a security issue by granting access to tracking values to non-admin users, allowing for broader use of this functionality. This improves the reliability and flexibility of payroll calculations.
Original PR description
Accrual is computed based on tracking values, checking added or removed leaves in a given request, based on their datetimes. This feature does not seems tested currently, so let us cover it. That way we ensure future changes in tracking model do not break current feature. By the way, fix an ACL issue when trying to access tracking values and not being admin. Task-5935695 ([mail, various] Cleanup and test tracking usage) Prepares Task-3645865 ([mail] In-body tracking) Co-Authored-By: Prakash Prajapati <ppr@odoo.com> Forward-Port-Of: odoo/enterprise#110302
Resolved issues and error corrections
This update resolves an issue preventing proper printing using wkhtmltopdf. The HTML editor now utilizes a static file box instead of an embedded component, restoring its printing capabilities. This change was previously addressed in another pull request and is aligned with the Enterprise version.
Original PR description
Purpose of this commit: - Restore the static file box implementation and drop the embedded component, as it breaks printing with wkhtmltopdf. - The original issue with the static file box was fixed in [#241591](https://github.com/odoo/odoo/pull/241591) Reverts: https://github.com/odoo/odoo/pull/216572 enterprise: https://github.com/odoo/enterprise/pull/108999 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251098
This update fixes an issue preventing UK users from correctly accessing Stripe funding instructions. The team reworked the testing framework to specifically handle UK requirements and added a secondary check for Euro currency to ensure accurate funding instructions are provided. This improves the user experience for UK customers.
Original PR description
### [IMP] hr_expense_stripe: Rework tests for UK Rework the test framework to handle the United Kingdom specific tests ### [FIX] hr_expense_stripe: Fix UK account creation Add UK account creation funding instructions as it was made available to us by Stripe ### [FIX] hr_expense_stripe: Fix funding instruction EU Before this commit: The funding instructions were using the country group Europe as a reference to see if the country should use the EU funding instructions The issue comes from the fact that a lot of people remove their country from that country group, locking themselves out of stripe issuing EU. This adds second way of telling the user is in the EU flow if their stripe currency is set to Euros. Forward-Port-Of: odoo/enterprise#109667
This update corrects tax reporting templates for Belgium, Netherlands, Luxembourg, and France, ensuring accurate UBL/CII tax category and exemption reason codes are used. Specifically, the BE tax template now correctly assigns tax codes for all taxes, resolving previous inconsistencies and improving compliance with local tax regulations. This ensures accurate financial reporting and reduces potential tax discrepancies.
Original PR description
Before this commit : NL,FR,LU tax templates did not define the UBL/CII tax category and exemption reason codes. In BE tax template, all cocontracting taxes had "AE" tax code and "VATEX-EU-AE" tax exemption reason code, even for non-0% cocontracting taxes. Some other taxes didn't have the correct codes. After this commit : All relevant NL,FR and LU tax templates now define their UBL/CII tax category and exemption reason codes. Specific reason codes are assigned where applicable. In BE tax template, taxes are now corrected, all taxes have their relevant tax codes. task-4976471 --- I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/odoo#250013
This update corrects a technical issue preventing electronic invoices under the RIMPE Emprendedor regime from processing correctly. The change ensures the system recognizes only the approved string value for this regime, resolving a validation error during invoice signing. This ensures compliance with Ecuadorian tax regulations and proper invoice processing.
Original PR description
Corrected the hardcoded string for the RIMPE Emprendedor regime to match the SRI structure According to SRI technical specifications, the <contribuyenteRimpe> tag only accepts two specific values:…
Corrected the hardcoded string for the RIMPE Emprendedor regime to match the SRI structure According to SRI technical specifications, the <contribuyenteRimpe> tag only accepts two specific values: CONTRIBUYENTE RÉGIMEN RIMPE (Fixed value) CONTRIBUYENTE NEGOCIO POPULAR - RÉGIMEN RIMPE Steps to reproduce: Install l10n_ec_edi module Go to Settings > Invoicing > Ecuadorian Localization In Electronic Invoicing > Regime, select rimpe_emprendedor In Electronic Invoicing > Regime, configure a SRI Connection Post an customer invoice **Validation error occurring during the electronic signing process (using .p12 certificates):** `35 - Se encontró el siguiente error en la estructura del comprobante: cvc-pattern-valid: Value 'CONTRIBUYENTE EMPRENDEDOR - RÉGIMEN RIMPE' is not facet-valid with respect to pattern 'CONTRIBUYENTE RÉGIMEN RIMPE|CONTRIBUYENTE NEGOCIO POPULAR - RÉGIMEN RIMPE' for type 'contribuyenteRimpe'.. - ARCHIVO NO CUMPLE ESTRUCTURA XML - ERROR ` Forward-Port-Of: odoo/enterprise#109147
This update optimizes how Odoo identifies user devices, leading to faster data retrieval when viewing user sessions and devices. Previously, a performance bottleneck prevented efficient indexing, but this change utilizes a more direct approach using IDs, resulting in a noticeable improvement in speed. This ensures smoother user experience and faster reporting.
Original PR description
When a view of `res.users` with the `session/device_ids` field(s) is used, the ORM will translate the `One2Many` relationship by performing a query that uses the `id` column to retrieve the rows. The problem is that before this commit, it is impossible for postgresql to use the index on this column, because the value is retrieved via aggregation. This commit improves the performance of these models by performing deduplication without using the `GROUP BY` clause, but using `NOT EXISTS` instead. Note: It is necessary to perform the missing aggregations in a computed field (for the `first_activity` field). Task-6002927
This update resolves an issue where Dutch tax returns appeared to be submitted in the Odoo system but weren't actually being transmitted to the relevant tax authorities. The fix ensures that the necessary XBRL export is triggered when a Dutch tax return is submitted, aligning the UI with the actual submission status.
Original PR description
Commit 647699eeb4b8a1cc37ca074fa57844871c5086c1 introduced account returns to the Dutch localization. However, the "Submit" action only updated the internal record state without triggering the actual XBRL export to the Dutch tax authorities. This led to a mismatch where the UI displayed "Submitted" despite no data being transmitted. This commit fixes the flow by: - Overriding `action_submit` on the account return to launch the XBRL wizard when the return type is a Dutch tax return. - Ensuring the SBR tax report wizard calls `_proceed_with_submission` on the associated account return to correctly finalize the process (including locking the period and generating the closing entry). opw-5974711 Forward-Port-Of: odoo/enterprise#110015 Forward-Port-Of: odoo/enterprise#109691
This update resolves an issue where sale orders would fail to confirm if a product wasn't added before confirmation. The tour tests have been updated to ensure product additions are fully processed before order confirmation, preventing order drafts and ensuring the tour completes successfully. This impacts the sale and purchase workflows.
Original PR description
There is an inaccuracy in the steps of the tour: - test_basic_sale_flow_with_minimal_access_rights Indeed, in this test a new line is added on the order and a product is selected but the next step…
There is an inaccuracy in the steps of the tour: - test_basic_sale_flow_with_minimal_access_rights Indeed, in this test a new line is added on the order and a product is selected but the next step confirms the order without waiting for all the associated onchanges to be taken into accounts: https://github.com/odoo/odoo/blob/b5511e5ebb919c2c506131bf9e2a4196dac25f79/addons/sale_management/static/tests/tours/sale_flow_tour.js#L14-L20 https://github.com/odoo/odoo/blob/b5511e5ebb919c2c506131bf9e2a4196dac25f79/addons/sale/static/src/js/tours/tour_utils.js#L27-L47 In the case where the confirmation happends before the product edition is taken into account, the order fails to confirm and stays in draft which makes the rest of the tour fails. Note: The same issue could happen at some point on the equivalent purchase test, so that we also modify the test: - test_basic_purchase_flow_with_minimal_access_rights runbot-241198 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252154
A technical update resolved an issue preventing the Quote Builder from generating PDF quotes, which was causing errors. This change updates the PDF generation library to a compatible version and adds a necessary field definition to ensure proper PDF creation.
Original PR description
Issue: --- Due to this issue, generating PDF Quote using Quote Builder leads to traceback. Steps to reproduce: --- 1- Using a python 3.13 env, install requirements.txt. (You could instead uninstall…
Issue: --- Due to this issue, generating PDF Quote using Quote Builder leads to traceback. Steps to reproduce: --- 1- Using a python 3.13 env, install requirements.txt. (You could instead uninstall pypdf2 and install pypdf==5.4.0) 2- Enable Quote Builder. 3- Create a SO and in quite builder tab, select a document. 4- Print -> PDF Quote. This will lead to traceback. Cause: --- There is a requirement change on https://github.com/odoo/odoo/pull/233600, as pypdf2 will not be supported in future. Instead we use pypdf==5.4.0. In pypdf 5.4.0 it is required to have `Fields` present in `Acro Form` (introduced in [1] v3.13.0): https://github.com/py-pdf/pypdf/blame/f20954f2241640feb484800e191373f8fbdfa44b/pypdf/_writer.py#L1060-L1061 FIX: --- We could add an empty `fields` dictionary when it's not present. The entry should be `/Fields`: https://github.com/py-pdf/pypdf/blob/f20954f2241640feb484800e191373f8fbdfa44b/pypdf/constants.py#L362-L370 Note: --- In this fix, we replace `is_upper_version_pypdf2` with specific version comparison. To be precise `getNumPages` is depreciated in version 1.28.0 [2]. References: --- [1]- https://github.com/py-pdf/pypdf/commit/dcf997a028e993b215457c5629cb4e78186e11c0 [2]- https://github.com/py-pdf/pypdf/blob/3ab1581a51f446f86dd445662005f8747941c2b6/pypdf/_writer.py#L507-L514 opw-5784464 Forward-Port-Of: odoo/odoo#250329
This update corrects a visual issue where the unit price wasn't shown on product pages when using the 'boxed' layout in the ecommerce section. The fix ensures all layout styles display the crucial unit price information for customers, maintaining a consistent and informative shopping experience. This resolves a prior bug introduced during a recent website update.
Original PR description
### Issue before the commit: In the product page of ecommerce app choosing the "boxed" style layout the price per unit was not displayed. ### Steps to reproduce the issue: - Download website and…
### Issue before the commit:
In the product page of ecommerce app choosing the "boxed" style layout the price per unit was not displayed.
### Steps to reproduce the issue:
- Download website and create one
- Activate "Product reference type" from settings
- Create a product inserting selling price and base unit count
- Go to website with smart button
- Edit and go to "style" tab
- The "purchase style" is not working for "boxed" style
### Cause of the issue:
During the refactoring of the product page templates from version 18.4 to 19.0 (commit 670b1daa2254d7600b54bae675dd673f457aa8fa), in the website_sale.product template, the logic responsible for rendering the unit price information was omitted in the "boxed" layout, whereas it remains correctly implemented in the "default" and "large" views.
### Reason to introduce the fix:
To ensure UI uniformity across all available layout styles and to restore the visibility of critical unit price data for customers.
### Fix details:
Added the base_unit_price in the website_sale.cta_wrapper_boxed layout:
```
<small t-if="combination_info.get('base_unit_price')"
class="ms-1 text-muted o_base_unit_price_wrapper d-none">
<t t-call="website_sale.base_unit_price">
<t t-set="base_unit_price" t-value="combination_info['base_unit_price']"/>
</t>
</small>
```
Before the change:
<img width="489" height="373" alt="image" src="https://github.com/user-attachments/assets/1cee4cfc-0109-4647-a925-b183a19cad48" />
After the change:
<img width="471" height="362" alt="image" src="https://github.com/user-attachments/assets/863e98b2-6297-4388-a538-5ee0c1a568fa" />
opw-5920598
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#250319This update ensures that the system accurately reflects outstanding POS amounts after an order is cancelled. Previously, cancelled orders were incorrectly included in payment calculations. This change prevents inaccurate reporting and ensures financial data integrity following order cancellations.
Original PR description
Add `pos_order_line_ids.order_id.state` to the depends of `_compute_pos_amount_unsettled` so that cancelling a POS order triggers a recompute. Also exclude cancelled order lines from `total_pos_paid` to avoid counting payments that were rolled back. opw-5997872 Forward-Port-Of: odoo/enterprise#109542
This update fixes an issue where currency exchange differences weren't correctly displayed in DATEV exports. The fix adjusts how the system calculates amounts for exchange difference entries, ensuring accurate reporting of financial transactions. This improves the reliability of data sent to DATEV.
Original PR description
**Steps to reproduce: 1. Create DE company (EUR currency) 2. Add USD -> EUR exchange rates for XX/01/26 and XX/15/26 (XX is target month) 3. Install l10n_de_reports 4. Make sure bank journal has…
**Steps to reproduce: 1. Create DE company (EUR currency) 2. Add USD -> EUR exchange rates for XX/01/26 and XX/15/26 (XX is target month) 3. Install l10n_de_reports 4. Make sure bank journal has 'outstanding receipts' set for incoming manual payment [Accounting -> Config -> Journals -> Bank] 5. Create USD invoice for XX/02/26 and confirm it 6. Register a Payment for XX/16/26 and confirm it (you should see the exchange difference entry matched alongside the payment) 7. Go to [Accounting -> Reporting -> General Ledger] and export DATEV data **Description of issue: The currency exchange rate difference entries in the exported file are shown as 0 **Expected behavior: The actual currency exchange difference values should be displayed **Why this happens? The DATEV export currently sets the amount based on 'amount_currency'. For currency exchange difference entries, this value is 0.0 in the General Ledger, resulting in 0 values in the export. **The fix: Updated the logic to use the line balance when the entry is identified as a currency exchange difference. opw-5358954 Forward-Port-Of: odoo/enterprise#109655 Forward-Port-Of: odoo/enterprise#107268
This update adjusts the order in which taxes are processed for Mexican accounting (l10n_mx). Previously, the order caused incorrect tax calculations due to how taxes are prioritized. This change ensures accurate tax calculations and avoids potential financial discrepancies for Mexican users.
Original PR description
The current layout has the IEPS first, then IVA, and finally the Withholding, this will cause calculations to be wrong because of tax hierarchy. Most users are not aware that the tax order affects the calculation, so this would help prevent incorrect results. task-5247176 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252780
This update ensures that taxes are automatically calculated for charge and discount lines in UrbanPiper orders, even when tax data isn't directly provided by the UrbanPiper system. Previously, taxes weren't applied if UrbanPiper didn't send tax information, and it was limited to India. Now, taxes are calculated using standard product tax rules, ensuring accurate tax handling for all UrbanPiper orders.
Original PR description
Before this commit: --- - If UrbanPiper did not send tax data for charge and discount lines, taxes were not applied. - Tax data was only provided by UrbanPiper for the India region. After this commit: --- - When the payload does not include tax data, compute taxes for charge and discount lines using the product tax, the same way as for normal order lines. task-5895987 Forward-Port-Of: odoo/enterprise#109096 Forward-Port-Of: odoo/enterprise#106686
This update fixes a stock management error that previously lacked specific details about the problematic package. By identifying the package causing the issue, users can quickly diagnose and resolve inconsistencies, especially during large product transfers. This improves efficiency and reduces downtime for our customers.
Original PR description
The current error does not specify which package is problematic. This cause issues on big transfers with many products / packages. Specifying the package in the error helps the customer identify the issue, and correct it themselves. OPW-5923839 --- <img width="673" height="252" alt="image" src="https://github.com/user-attachments/assets/0ccb45be-d813-4933-86fd-0dd3506d2775" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252351 Forward-Port-Of: odoo/odoo#249290
This update fixes a critical issue where AI chat failures resulted in confusing error messages for users. The changes now provide more informative messages – ‘oops’ or ‘Connection Interrupted’ – and ensure a smoother user experience when the AI chat encounters problems, preventing data loss and improving reliability.
Original PR description
Steps to reproduce: 1. Open the Website Editor 2. Select some text 3. Click the AI tool from the toolbar 4. Send a message in the chat window 5. Observe a non-standard error dialog showing 500 HTTP…
Steps to reproduce:
1. Open the Website Editor
2. Select some text
3. Click the AI tool from the toolbar
4. Send a message in the chat window
5. Observe a non-standard error dialog showing 500 HTTP error
The AI chat was not properly handling server errors and connection
interruptions, causing unhandled exceptions to be thrown to the user.
This commit improves error handling for both public and internal AI chat
by:
- The generator function handles error, such that it still yields data
even in error.
- Simulate RPCError for both the fetch of the streaming endpoint and during
error when streaming (error data is converted to RPCError).
- Properly provide error handler for StreamInterruptedError.
- Use a dedicated cursor for the LLM agent loop, wrapped in try/finally. When
the loop crashes, a new cursor is opened in the finally block to persist the
last text response. This ensures the loop cursor can roll back DB updates from
already-executed tool calls without losing the response message.
The following behavior will now be observed during error in the UI.
- Public AI chat:
- Initial fetch failed: shows "oops" message
- Stream interrupted:
- Server handled: shows "oops" message
- Server stopped: shows "Connection Interrupted" dialog
- Internal AI chat:
- Initial fetch failed: show RPCError dialog
- Stream interrupted:
- Server handled: shows RPCError dialog
- Server stopped: shows "Connection Interrupted" dialog
We also include a fix in the livechat where the ai spinner never goes away
when posting of message failed.
TASK-ID: 5886825This update resolves an issue where the HTML editor wasn't accurately reflecting changes made by users. Previously, multiple edits could lead to the field incorrectly showing as 'clean,' preventing users from seeing and applying updates. This fix ensures that the editor correctly tracks all changes made within the field, improving data accuracy and usability.
Original PR description
Prior to this commit, it was possible to: - make change A inside a html_field - save/commitChanges - make change B inside the html_field, before the end of the save/commitChanges - the field ends up incorrectly marked as "not dirty" (user can't use the FormStatusIndicator) even though change B was not committed yet. Solution: Give an id to the dirtiness, and associate that id with an extracted value from the editor. When the record update is done, mark the field as not dirty ONLY IF the current dirty id is the same as the id previously associated with the extracted value, else the field stays dirty. task-5976348 Forward-Port-Of: odoo/odoo#253192 Forward-Port-Of: odoo/odoo#252655
This update corrects a display issue on Arabic receipts where phone numbers were printed right-to-left instead of left-to-right. The fix ensures phone numbers are correctly formatted in Arabic language environments, improving the user experience for Arabic-speaking customers. The change involves adjusting the HTML formatting to explicitly set the direction of the phone number text.
Original PR description
# Steps to reproduce: - Open the company, change the language to Arabic - Go to POS, open the shop - Buy anything and click on receipt # Problem: When clicking on the receipt, you would find the…
# Steps to reproduce:
- Open the company, change the language to Arabic
- Go to POS, open the shop
- Buy anything and click on receipt
# Problem:
When clicking on the receipt, you would find the phone number is written right to left, although it should be printed left to right.
# Cause:
Normally when another language is selected, this line will adapt to it, and translate the whole block "Tel: `props.data.company.phone`" to arabic (right to left)
https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/point_of_sale/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml#L12
# Fix:
We need to specify the direction of the phone number to be Left to right.
```
<div>Tel:<span dir="ltr"><t t-esc="props.data.company.phone" /></span></div>
```
**Result:**
<img width="167" height="86" alt="HATEF" src="https://github.com/user-attachments/assets/4fe0bdd0-fe77-430f-9136-cd7086c4d5d9" />
There is also alternative fixes:
# First alternative fix:
Replace the '+' with '00' (there is no difference when trying to copy), and make a function in js that preserve the whole thing in a string variable.
```
get phoneText() {
return _t("Tel:") + " " + this.props.data.company.phone.replace("+", "00");
}
```
**Result:**
<img width="215" height="148" alt="hatef2" src="https://github.com/user-attachments/assets/e9cb4415-baad-4d66-a04b-ecdb308e3e72" />
**Drawback:**
- The inconsistency between how the number is stored and how we view it.
# Second alternative fix:
**File:** `/home/odoo/codebase/odoo/addons/point_of_sale/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.js`
```diff
import { _t } from "@web/core/l10n/translation";
import { Component } from "@odoo/owl";
+ import { localization } from "@web/core/l10n/localization";
```
```diff
+ get direction() {
+ return localization.direction;
+ }
```
**File:** `/home/odoo/codebase/odoo/addons/point_of_sale/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml`
```diff
<t t-if="props.data.company.phone">
- <div>Tel:<t t-esc="props.data.company.phone" /></div>
+ <t t-if="direction == 'ltr'">
+ <div>Tel:<t t-esc="props.data.company.phone" /></div>
+ </t>
+ <t t-elif="direction == 'rtl'">
+ <div><t t-esc="props.data.company.phone" />Tel:</div>
</t>
</t>
```
**Drawback:**
- Too much code for a small issue that probably won't bother the client.
- The need to change in multiple translation files for all RTL languages in odoo.
- Readability
opw-5881503
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#252348
Forward-Port-Of: odoo/odoo#249060This fix addresses an issue where the price calculation from a BOM wasn't accurate when the BOM was created without specifying a product variant. The update ensures the work center efficiency is correctly applied during the cost computation, leading to more precise pricing for multi-variant products.
Original PR description
**Issue** Computing the price from BOM can be incorrect when the BOM is defined on a multi-variant product. **Steps to reproduce** - Create a product with several variants - Create a BOM for that…
**Issue**
Computing the price from BOM can be incorrect when the BOM is defined on a multi-variant product.
**Steps to reproduce**
- Create a product with several variants
- Create a BOM for that product without specifying the product variant
- Define an operation restricted to a specific variant V
- Associate the operation with a workcenter with:
- Non-null cost per hour (e.g. 100)
- Time efficiency lower than 100% (e.g. 50%)
- Go to the product page > Variants > variant V
- Click on "Compute price from BOM"
-> The result will be 100 instead of 200 in this example.
Please notice that the price is correctly computed in the BOM overview
**Cause**
Accessing the BOM triggers a `web_read` including `operation_ids`,
which requires computing `time_total`:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/models/mrp_routing.py#L77
During this computation, the associated product is retrieved:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/models/mrp_routing.py#L106
But since no product is given in the context and the BOM has been created without specifying the product variant
(`bom_id.product_id` is empty), then it retrieves all the product variant associated to the BOM, which leads to
arbitrary default value that ignores work center efficiency:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/models/mrp_routing.py#L107-L111
While clicking on "Compute price from BOM":
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp_account/models/product.py#L33
it will ultimately needs to compute the cost:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp_account/models/product.py#L74
which relies on `time_total`:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/models/mrp_routing.py#L131
and since no context is provided, `time_total` is already in the cache, so the default value is used.
Please notice that in BOM overview, the problem does not occur because the provided context retriggers the compute method:
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/report/mrp_report_bom_structure.py#L806
https://github.com/odoo/odoo/blob/233316f322d891ebaadb51412ea0df039bfd312a/addons/mrp/report/mrp_report_bom_structure.py#L835
opw-5909570
Forward-Port-Of: odoo/odoo#248758This update corrects a bug where generating PIX payment QR codes would fail if company names included special characters like emojis. The fix ensures company names only contain valid characters, guaranteeing QR code validity and successful payment processing. This improves the reliability of PIX payments for Brazilian businesses.
Original PR description
When generating the QR code for PIX payment, if the company name contained incorrect characters (like emojis), the generated code was invalid and the payment could not be processed. Steps to reproduce: ------------------- * Install l10n_br and PoS * Create a PIX payment method and set it on the PoS session * Change the company name to contain an emoji (e.g. "Company emoji 😇") * Open the PoS session and try to pay with PIX > Observation: If you try to verify the generated QR code, it will be invalid Why the fix: ------------ We apply the same regex as defined here: https://github.com/odoo/odoo/blob/72654c3596660e3ec4b6885c5b957739465de097/addons/l10n_br/models/res_partner_bank.py#L81 To make sure the company name only contains valid characters, and the generated QR code is correct. This also modify the other tests because it removes the `_` that is not an allowed character. opw-5907530 Forward-Port-Of: odoo/odoo#250917
This update fixes a server error that occurred when merging tables in the Point of Sale system, specifically when a table was empty or had an incomplete order. The fix ensures the system waits for order synchronization before merging, preventing the error and improving table management functionality. This enhances the reliability of the POS experience.
Original PR description
Steps to reproduce: - On an empty table, change the guest count - Create an order and send it to the kitchen - Open another table without an order - Merge the first table with the second one Issue: - A server error occurs while merging the tables Fix: - Wait for the merge order to sync before returning the result Task-5502511 Related PR - https://github.com/odoo/odoo/pull/245162 Forward-Port-Of: odoo/enterprise#104577
This update resolves an issue where purchase orders created with the Dropshipping route were missing the required 'Dropship Address' field, preventing order confirmation. The fix ensures that this field is automatically populated when setting the delivery type to 'Dropship', allowing users to complete the purchase process smoothly.
Original PR description
## Issue When setting up a product with both the MTO and the *Dropship* routes, the *Purchase Order* genereated when confirming a *Sales Order* does not contain a *Dropship Address*…
## Issue
When setting up a product with both the MTO and the *Dropship* routes, the *Purchase Order* genereated when confirming a *Sales Order* does not contain a *Dropship Address* (`purchase.order.dest_address_id`). It is problematic because that field is both readonly and required to confirm the order.
## Steps to reproduce
1. Install *Stock* (`stock`), *Purchase* (`purchase`) and *Sales* (`sale_management`)
2. In Settings, enable *Dropshipping* and *Replenish on Order (MTO)*
3. Create a Product P
- Set a vendor in the Purchase tab
- Enable the *Buy*, *Dropship* and *Replenish on Order (MTO)* routes
4. Create a Sales Order
- Any Customer
- Product P
- Confirm the Sales Order
5. Click on the *Purchase* smart button
6. Set the *Delivery To* (`purchase.order.picking_type_id`) field to *"Dropship"*
7. **The _Dropship Address_ (`purchase.order.dest_address_id`) field appears, but it's empty and readonly. The purchase order cannot be confirmed, as the field is required and cannot be updated.**
## Cause
When confirming a Sales Order, the created Purchase Order has a `dest_addres_id` set by `StockRule._prepare_purchase_order`:
https://github.com/odoo/odoo/blob/19.0/addons/purchase_stock/models/stock_rule.py#L350
At that point, the `picking_type_id` of the PO is set to `"Receipts"`, which `default_location_dest_id` is the user's Stock, and the `usage` of that location is set to `"internal"`. When `_compute_dest_address_id` is triggered, it starts by calling the method in `sale_purchase`:
https://github.com/odoo/odoo/blob/9d96a8a4ae23bd331296ee0fd628c2be3de4bfe3/addons/sale_purchase/models/purchase_order.py#L25-L30
Which calls the one in `purchase_stock`:
https://github.com/odoo/odoo/blob/9d96a8a4ae23bd331296ee0fd628c2be3de4bfe3/addons/purchase_stock/models/purchase_order.py#L80-L82
Which sets the `dest_address_id` to `False`. This impacts the rest of first `_compute_dest_address_id`, as the PO does not have a `dest_address_id` anymore, its value will never be updated by the `_compute_dest_address_id` methods.
## Fix
The `dest_address_id` should only be set when dropshipping. The easiest way to do so is to override the `_compute_dest_address_id` in the `stock_dropshipping` module by following a similar logic as in `sale_purchase`:
https://github.com/odoo/odoo/blob/7a39185f83d0daca207c8007512f4700537c7e88/addons/sale_purchase/models/purchase_order.py#L25-L30
opw-5426322
Forward-Port-Of: odoo/odoo#245284This update resolves an error that occurred when users attempted to generate lots in Odoo. The issue stemmed from a missing lot sequence ID, which caused the system to fail. This fix ensures that lot generation works correctly, even if a product's lot sequence hasn't been defined.
Original PR description
Currently, an error occurs when a user tries to generate lots while providing a lot number. **Steps to replicate:** - Install purchase (without demo). - Create a product `test`. - Install stock and…
Currently, an error occurs when a user tries to generate lots while providing a lot number.
**Steps to replicate:**
- Install purchase (without demo).
- Create a product `test`.
- Install stock and turn on `Lots and Serial Numbers`
- Open the product `test` and turn on `Track Inventory` `by Lots`.
- Open Receipts > add the product `test`> give demand as 3 > and go to its form view using view button.
- Click `Generate Lots` > type `lot1` in `First lot Number` > Generate > Error-1
- Click `Generate Lots` > type 0 in Quantity received > Generate > Error-2.
**Error-1:**
```
File '/home/odoo/odoo18/community/addons/stock/models/stock_move.py', line 1026, in action_generate_lot_line_vals
if (first_lot and first_lot == product.lot_sequence_id.get_next_char(first_number)):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/odoo18/community/odoo/addons/base/models/ir_sequence.py', line 237, in get_next_char
interpolated_prefix, interpolated_suffix = self._get_prefix_suffix()
^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/odoo18/community/odoo/addons/base/models/ir_sequence.py', line 227, in _get_prefix_suffix
self.ensure_one()
File '/home/odoo/odoo18/community/odoo/orm/models.py', line 5640, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: ir.sequence()
```
**Error-2:**
```
File '/home/odoo/odoo18/community/addons/stock/models/stock_move.py', line 1025, in action_generate_lot_line_vals
first_number = product.lot_sequence_id.number_next_actual - product.lot_sequence_id.number_increment
^^^^^^^
UnboundLocalError: cannot access local variable 'product' where it is not associated with a value
```
---
**Cause:**
- Both errors originated through a recent [PR].
**Error-1 (Expected singleton: ir.sequence()):**
- As the product was already created before Inventory was installed, the `lot_sequence_id` was empty. (Note:`lot_sequence_id` field has a default value , but default value
assignment triggers only during the record creation, any records created
before stock is installed will not be assigned any value for
`lot_sequence_id`.)
- As no `lot_sequence_id` is assigned to `test` product the line [1] calls `get_next_char()` on an empty recordset which further calls `_get_prefix_suffix()` [2] and raises singletonerror from [here].
**Error-2 (UnboundLocalError: cannot access local variable 'product'):**
- As the `Received Quantity` was given 0, the `count` argument is received as 0 and as a result the `lot_qties` [3] and `lot_names` [4] are received as empty lists.
- This causes their [zip] to be empty list too and the loop never runs, so assignment to [product] variable never happens and causes the error to occur from here [5].
---
**Solution:**
**Error-1:**
- Now we perform write on `product.lot_sequence_id` only if it exists, otherwise we skip it.
**Error-2:**
- Moved the static assignment of variable `product` and `location_dest_id` outside the loop, this will also prevent the browse being called multiple times for browsing the same record.
[PR]: https://github.com/odoo/odoo/pull/240368
[1]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L1026
[2]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/odoo/addons/base/models/ir_sequence.py#L237
[here]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/odoo/addons/base/models/ir_sequence.py#L227
[3]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L989
[4]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L994
[zip]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L1000
[product]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L1004
[5]: https://github.com/odoo/odoo/blob/7ab52c1675b9764d11454c7b5216064bec4628f8/addons/stock/models/stock_move.py#L1025
sentry-7254849206,7265844194
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#248846This update resolves an issue where payments with outstanding receipt accounts weren't automatically matched in the accounting system. The fix allows for amount matching when outstanding receipts are present, ensuring accurate reconciliation of payments and bank transactions. This improves the reliability of financial reporting.
Original PR description
Steps to reproduce - Have a Bank journal with Outstanding Receipts accounts set - Create and confirm an invoice with a payment reference - Create the payment - Create a bank transaction with: - Label: any label - Partner: invoice partner - Amount: invoice full amount Issue: Transaction won't be matched automatically Analysis: Transaction will be automatically matched if the outstanding receipts account is not set. It occurs because in case it is set, the sytem will only try to match the communication pattern against the journal item of the payment, without trying amount matching Note: another solution could be to relax the communication matching. In the user case the invoice payment reference is something like `TEST-12345` and the payment communication `AAAAAAAAAAA /BBBBBBBBBBB TEST 12345` opw-5872387 Forward-Port-Of: odoo/enterprise#109992 Forward-Port-Of: odoo/enterprise#108564
This update resolves a bug where the barcode scanning app incorrectly identified products when using barcodes that include product pricing (price-embedded). The fix adds logic to match these barcodes, mirroring the functionality in the Point of Sale app, ensuring accurate product recognition. This improves the reliability of barcode scanning for all products.
Original PR description
Issue ----- Barcode app doesn't match products when using price-embedded barcodes. Steps to reproduce ----- - Use default nomenclature (so price embedded barcodes are 23...) - Create a product with barcode 2355555000004 - Go to barcode and scan 2355555009502 > The product isn't recognised Cause ----- There is no logic in place to handle such barcodes, but it can be added to mimic how it works in POS. https://github.com/odoo/odoo/blob/0fe2023dc57b6cc02bd399d3c8fc5d6c8ed6e833/addons/point_of_sale/static/src/app/screens/product_screen/product_screen.js#L212 ----- Ticket: opw-5901412 Forward-Port-Of: odoo/enterprise#110034 Forward-Port-Of: odoo/enterprise#109627