Tuesday, November 25, 2025
20 changes · saas-18.4
Enhancements to existing features
This update allows users to backdate Saudi invoices within Odoo, resolving a previous limitation that prevented accurate reporting to ZATCA. By aligning the invoice confirmation date with the invoice date itself, this change ensures consistency and simplifies invoice processing for Saudi Arabia. This improves compliance and reduces potential discrepancies.
Original PR description
Previously, `l10n_sa_confirmation_datetime` represented the time where the invoice was posted, that meant that we could not backdate invoices, since it would cause disparity between what zatca receives and what we consider in odoo (i.e. `invoice_date`) This commit allows us to set the date component of `l10n_sa_confirmation_datetime` to the `invoice_date` so we can safely backdate invoices. task-5009969 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236979 Forward-Port-Of: odoo/odoo#229517
Resolved issues and error corrections
A recent update caused a bug where changing a journal's currency would erase outstanding account information from payment method lines. This change ensures that account details remain accurate after currency adjustments, particularly when using bank synchronization. This fix prevents financial discrepancies and maintains proper record-keeping.
Original PR description
Changing the currency on a journal triggers the compute of inbound/outbound method lines, which clears the method lines before reasign the default method lines. This leads to the loss of any outstanding account set on the method lines. Steps: - Have a bank journal with outstanding accounts set on the payment method lines - Change the currency (in our case, this is the bank sync that changed the currency of the journal) -> Outstanding accounts are missing on the payment method lines, even if the accounts currency is the same as the journals or no currency is set on the accounts. opw-5175794 Forward-Port-Of: odoo/odoo#234008
This update resolves a memory issue that occurred when processing invoices for the Serbian EDI system (l10n_rs_edi). By proactively retrieving country codes, the system now avoids running out of memory, ensuring smoother and faster invoice processing. This improves the overall efficiency of the system when handling RS-specific transactions.
Original PR description
Due to more number of moves during compute it out of memory while getting the country_code per move. So, just pre fetch the country code. So, it won't go for computing that and will be available in…
Due to more number of moves during compute it out of memory while getting the country_code per move. So, just pre fetch the country code. So, it won't go for computing that and will be available in memory records ``` sagu_3267671=> select count(id) from account_move; count --------- 1034179 (1 row) ``` ``` File "/home/odoo/src/odoo/17.0/addons/mail/models/mail_thread.py", line 424, in _compute_field_value return super()._compute_field_value(field) File "/home/odoo/src/odoo/17.0/odoo/models.py", line 4923, in _compute_field_value fields.determine(field.compute, self) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 102, in determine return needle(*args) File "/home/odoo/src/odoo/17.0/addons/l10n_rs_edi/models/account_move.py", line 85, in _compute_l10n_rs_edi_is_eligible move.l10n_rs_edi_is_eligible = move.country_code == 'RS' and move.is_sale_document() and move.l10n_rs_edi_state in (False, 'sending_failed') File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 1219, in __get__ self.compute_value(recs) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 1401, in compute_value records._compute_field_value(self) File "/home/odoo/src/odoo/17.0/addons/mail/models/mail_thread.py", line 424, in _compute_field_value return super()._compute_field_value(field) File "/home/odoo/src/odoo/17.0/odoo/models.py", line 4923, in _compute_field_value fields.determine(field.compute, self) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 105, in determine return needle(records, *args) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 695, in _compute_related values = [first(value[name]) for value in values] File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 695, in <listcomp> values = [first(value[name]) for value in values] File "/home/odoo/src/odoo/17.0/odoo/models.py", line 6695, in __getitem__ return self._fields[key].__get__(self, self.env.registry[self._name]) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 2933, in __get__ return super().__get__(records, owner) File "/home/odoo/src/odoo/17.0/odoo/fields.py", line 1182, in __get__ recs._fetch_field(self) File "/home/odoo/src/odoo/17.0/odoo/models.py", line 3824, in _fetch_field self.fetch(fnames) File "/home/odoo/src/odoo/17.0/odoo/models.py", line 3874, in fetch fetched = self._fetch_query(query, fields_to_fetch) File "/home/odoo/src/odoo/17.0/odoo/models.py", line 3984, in _fetch_query self.env.cache.insert_missing(fetched, field, values) File "/home/odoo/src/odoo/17.0/odoo/api.py", line 1135, in insert_missing field_cache.setdefault(id_, val) MemoryError ``` upg-3267671 opw-5246681 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#235919
This update fixes an issue where the price displayed in Point of Sale (PoS) was incorrect when using non-groupable units of measure. The fix ensures that the correct price unit is applied during order settlement, leading to accurate pricing calculations for products with these UoMs. This improves the reliability of PoS transactions.
Original PR description
Steps to reproduce ------------------ 1. Create a product with a UoM that is non groupable in PoS 2. Make a sale order with that product having a UoM that is based on the UoM of the first steps. If…
Steps to reproduce ------------------ 1. Create a product with a UoM that is non groupable in PoS 2. Make a sale order with that product having a UoM that is based on the UoM of the first steps. If the UoM in the first step was Kg for intsance, use Gram (g) here. 3. Confirm the order, and settle it in PoS. Notice that the price of that order in PoS is not correct. Why it's happening ------------------ When settling the PoS order, we first convert the sale_order's line UoM (g) to the original product UoM (kg), and we update the quantity accordingly (in this example by dividing by 1000). https://github.com/odoo/odoo/blob/fcc5a90d2d5754923676b11031e37f52729402fd/addons/pos_sale/static/src/overrides/models/pos_store.js#L94-L96 So this step updates both the qty and the unit_price. https://github.com/odoo/odoo/blob/fcc5a90d2d5754923676b11031e37f52729402fd/addons/pos_sale/static/src/overrides/models/pos_store.js#L160-L161 However, when the UoM is not groupable, we split the lines by taking into consideration the updated qty, but we still use the old price_unit, which creates an inconsitency and wrong calculations. The fix ------- When splitting the lines, we're just supposed to change the qty per line to max 1, but we're not supposed to change the price per unit for this qty. We now use the updated `price_unit` to have a correct math. opw-5232571 Forward-Port-Of: odoo/odoo#237172 Forward-Port-Of: odoo/odoo#236008
This update fixes an issue where a product valued by lot would incorrectly use the average value instead of 0 when a lot was specified with a value of 0. This ensures accurate stock valuation calculations, particularly when starting with a lot that has no initial standard price. The change improves the reliability of inventory tracking.
Original PR description
**Problem:** when selling a product valued by lot and chosing a lot with a value of 0 the average value of the product is used instead of 0. **Steps to reproduce:** - make sure your warehouse is in…
**Problem:**
when selling a product valued by lot
and chosing a lot with a value of 0
the average value of the product
is used instead of 0.
**Steps to reproduce:**
- make sure your warehouse is in single step receipt and delivery
- create a product tracked by lot and valued by lot
- set the category as avco
- create a PO for a quantity of 10 and a unit price of 10
- confirm and open the receipt
- open the stock move widget on the stock move
- write "lot A" in the lot column and save
- validate
- create a PO for a quantity of 10 and a unit price of 0
- confirm and open the receipt
- open the stock move widget on the stock move
- write "lot B" in the lot column and save
- validate
- create a quotation for 1 quantity of your product
- confirm
- open the delivery
- open the stock move widget on the stock move
- in the 'pick from' column enter lot B and save
- validate
- open the valuation smart button
**Current behavior:**
the value of the stock valuation layer is -5
**Expected behavior:**
it should be 0
**Cause of the issue:**
Inside _prepare_out_svl_vals
lot.standard_price is 0 so the if condition
is false and we don't use the price of the lot
https://github.com/odoo/odoo/blob/cd2a241182cf56fc36d03df9f0afdcea30f682d2/addons/stock_account/models/product.py#L277
**fix:**
deleting the lot.standard_price condition
is not possible because when the lot is created
at delivery it has no standard_price and in this
case we want to use the standard_price of the
product.
(see test https://github.com/odoo/odoo/blob/d3835668349d466ed4ba27c9eacdbd3339f2ac37/addons/stock_account/tests/test_lot_valuation.py#L58)
opw-5077671
Forward-Port-Of: odoo/odoo#234764This update resolves an issue where the 'Click to Start' navigator wasn't appearing for documents without sign items. The fix ensures the navigator displays when a document has sign items, improving the user experience and making it easier for users to initiate the signing process.
Original PR description
Version: - saas-18.4 Steps to reproduce: - Add multiple documents in sign app. - Add sign item for user in first document and keep second document without any sign item. - Try sign document. Issue: - The "Click to Start" navigator is not visible when signing. - `postRender` runs for all documents and calls `checkSignItemsCompletion`, which then calls `updateDocumentsWithUnsignedItems(false)` for documents without sign items. - This passes false to `controlNavigatorVisibility`, hiding the navigator even though the first document has unsigned items. Solution: - In `controlNavigatorVisibility`, instead of relying only on the `hasUnsignedItems` flag, check if the current document is unsigned and has sign items for the current signer before toggling the navigator. Impact: - The "Click to Start" navigator now appears correctly, helping users start the signing process smoothly. task-5148722
This update fixes a bug preventing users from marking strikethrough and multiline fields as both readonly and mandatory within the Sign app. Now, users can correctly configure these fields without causing sign requests to fail, improving usability and workflow efficiency. This resolves a technical limitation impacting document signing functionality.
Original PR description
**Version:** - saas-18.4 **Steps to reproduce:** - Install the Sign app - Upload a PDF and add a strikethrough or multiline field - Mark the field as readonly and mandatory - Try to sign the document **Issue:** - The sign request cannot be validated if the strikethrough or multiline field is both readonly and mandatory. **Solution:** - For strikethrough fields: use "striked" instead of the item name "strikethrough" to set the correct value when the strikethorugh field is constant. - For multiline fields: when the field is constant, the value doesn’t come through element.value; instead, it’s in element.textContent, so we need to set the value there. **Impact:** - Users can now mark these fields as readonly and mandatory without blocking the validation of the sign request. task-5098750
This update optimizes the performance of our sales order system. By adding an index to a key field, we've reduced the time it takes to search and filter sales orders based on which sales team they're associated with. This results in faster response times and a smoother experience for our sales teams.
Original PR description
`team_id` might be used in filters to conditionally see related `sale.order` for a specific (or set of) sales teams. If the field isn't indexed, it's a Sequential Scan on `sale_order`, which can be a large table. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#237116
This update resolves an issue where the Facturae export XML incorrectly displayed negative values for withholding taxes. The fix ensures that withholding tax amounts are always positive, preventing rejection by the FACE system. This improves the accuracy of invoice data sent to tax authorities.
Original PR description
## Issue: The `TotalTaxesWithhold` field in the exported XML could be negative, causing FACE to reject the document. ## Cause: A previous change (https://github.com/odoo/odoo/pull/229236) added `values['tax_amount_currency']` to `TotalTaxesWithhold` without converting it to a positive value: https://github.com/odoo/odoo/blob/88b7ee6d9d2a7fe96512da0a7eaf8efcf9020ee1/addons/l10n_es_edi_facturae/models/account_move.py#L449 ## Steps to reproduce: - Install `l10n_es_edi_facturae` - With the ES company, create an invoice with a product and a withholding tax (e.g., 15% WHI) - Confirm the invoice and Send (Facturae) - Open the XML attached in the chatter - Observe that `TotalTaxesWithhold` is negative opw-5220205 Forward-Port-Of: odoo/odoo#235774
This update fixes an issue where only the first CFE was processed from Uruguayan vendor bills. Now, all CFEs within the XML files are correctly handled, and new documents created manually or automatically receive unique suffixes ('-manual' or '-notification') for easier tracking and debugging. This ensures accurate bill processing and simplifies identification of document origins.
Original PR description
1) Update l10n_uy_edi translations. 2) When an uruguayan xml file is uploaded on a purchase journal it could contain the information of more than one CFE but before this commit only the first CFE was…
1) Update l10n_uy_edi translations. 2) When an uruguayan xml file is uploaded on a purchase journal it could contain the information of more than one CFE but before this commit only the first CFE was processed. Now all the CFEs are processed. 3) Add suffix '-manual' for new vendor edi documents uuid that are created by drag and drop xml file. 4) Create xml attachment in the edi document if it is created by drag and drop xml file. 5) Add suffix '-notification' for new vendor edi documents uuid that are created by 'UY: Create vendor bills (sync from Uruware)'. 6) Cron is run by batches (size=10). 7) Add tests. The suffixes -manual and -notification are used to differentiate between EDI documents generated manually and those generated automatically. This is useful to determine whether the document was created by a user or by an automated process, also helps users identify its origin more easily and also it is useful for debugging and tracking purposes. Task Adhoc side: 43467 Task latam side: 1355 Forward-Port-Of: odoo/enterprise#99308 Forward-Port-Of: odoo/enterprise#86829
This update resolves an issue where the invoice report incorrectly displayed currency symbols and incorrect total amounts for companies using the 'tax included' tax setting in Kenya. The fix ensures accurate reporting of prices, including tax, for these businesses, improving financial reporting reliability.
Original PR description
When the company is "tax included" for all taxes, after signing to eTims, the invoice report: - shows the currency symbol twice for "Taxable Amount". - The xpath for 'td_subtotal' is also doubled for no reason. - The "Total" columns is always price excluded instead of being price included. task_id: 5252530 Forward-Port-Of: odoo/enterprise#100050
This update resolves several issues impacting the mobile Kanban view for document management. Specifically, it addresses gaps in folder and document display and scrolling limitations, ensuring a smoother and more functional user experience. This enhancement improves usability and data accessibility for users.
Original PR description
This commit fix several issue in kanban mobile view: - When a folder has folders AND documents, there is a huge gap between the two because of the kanban ghost records. - In the 'Recent' folder, folders and documents doesn't take all width. - In the 'Recent' folder, we can't scroll to see all the documents. Task-4963198 Forward-Port-Of: odoo/enterprise#100134 Forward-Port-Of: odoo/enterprise#90647
This update fixes an issue in the 3-step manufacturing process where production quantity changes weren't correctly triggering replenishment orders when using the MTSO rule. The fix ensures that sufficient component quantities are automatically ordered to meet production needs, improving inventory management accuracy.
Original PR description
Issue ----- In 3step manufacturing, changing the pre-prod -> prod rule to MTSO doesn't have the expected behaviour. That is, if there is an insufficient quantity of component present in pre-prod,…
Issue ----- In 3step manufacturing, changing the pre-prod -> prod rule to MTSO doesn't have the expected behaviour. That is, if there is an insufficient quantity of component present in pre-prod, updating the producing qty doesn't update the replenishment quantity. Steps to reproduce ----- - Enable warehouses and multi-step routes - Set warehouse manufacturing to 3 step - Edit the 3 step production route - Change the pre-prod -> prod rule to mts else mto - Create a product "Comp" - Set a quantity of 5 in location pre-prod - Create a product "Prod" - Add a BoM with "Comp" as component - Create a MO for 10 of Prod - Confirm MO > There is a transfer stock -> pre-prod for 5 of Comp - Open the production quantity wizard, update value to 12 and confirm > The transfer still shows 5 of Comp instead of the needed 7 Cause ----- Changing the production quantity updates the raw moves of the MO. This triggers a write on the move with the new `product_uom_qty` so we do a `run_procurement` https://github.com/odoo/odoo/blob/322c6d0468bf79e9d29e1375c49aa13d4a7b7a67/addons/mrp/models/stock_move.py#L481-L485 Before actually running any procurement we do https://github.com/odoo/odoo/blob/322c6d0468bf79e9d29e1375c49aa13d4a7b7a67/addons/mrp/models/stock_move.py#L492 Since the procurement group's method is `mts_else_mto`, when we go through https://github.com/odoo/odoo/blob/322c6d0468bf79e9d29e1375c49aa13d4a7b7a67/addons/stock/models/stock_move.py#L2329-L2332 we go into the `else` part and set the move's `procure_method` to mts. This means that, in the `run_procurement` method https://github.com/odoo/odoo/blob/322c6d0468bf79e9d29e1375c49aa13d4a7b7a67/addons/mrp/models/stock_move.py#L504 is not true, so we don't add any procurement to run. Solution ----- In `_adjust_procure_method` we update the move's rule to the MTSO one we found https://github.com/odoo/odoo/blob/322c6d0468bf79e9d29e1375c49aa13d4a7b7a67/addons/stock/models/stock_move.py#L2328 This means that we can update the check in `run_procurement` to also add a procurement to run if the move's rule is MTSO. ----- Ticket: opw-5008871 Forward-Port-Of: odoo/odoo#235125
This update resolves an issue where timesheet entries linked to reversed invoices were previously uneditable. Now, after reversing an invoice, users can correctly modify timesheet entries associated with that invoice through the recorded hours feature, ensuring accurate time tracking and invoicing.
Original PR description
**Issue:** Timesheet entries linked to reversed invoices are uneditable. **Steps to reproduce:** - Create a service product invoiced by timesheets, and create a project & task. - In Sales, create a new quotation with the product. - Confirm the quotation, click on the task, and create a timesheet entry. - Create an invoice from the quotation. - Confirm the invoice, add a credit note, and reverse the invoice. - Go to the reversed invoice and access the timesheet through recorded hours. the timesheet entry is uneditable, even though the invoice is reversed. opw-4633121 Forward-Port-Of: odoo/odoo#236601 Forward-Port-Of: odoo/odoo#201921
This update resolves an issue preventing batch payments from correctly transitioning to 'reconciled' status, particularly when dealing with complex scenarios like early payment discounts and currency exchange differences. The fix ensures accurate reconciliation processing, streamlining the bank reconciliation workflow and improving financial reporting.
Original PR description
In the goal of fixing the batch payments with EPD in the bank rec widget, we discovered another bug that was preventing the batch payments to change their state to "reconciled". This was due to some compute not being triggered again when one of its dependences did change (during another compute). task-4681366 Forward-Port-Of: odoo/odoo#223310 Forward-Port-Of: odoo/odoo#222303
This update fixes how early payment discounts (EPD) are displayed in the bank reconciliation widget. It now accurately reflects EPD amounts when batch payments containing invoices are used, ensuring correct reporting of discounts and payments. This improves the accuracy of financial reconciliation processes.
Original PR description
In the bank reconciliation widget, it is now possible to have batch payments containing payments linked to only invoice_ids. Such batch payment, once mounted in the widget, should reflect the invoice or move amounts of its payments, and not only the payments amount. In the case of a payment-invoice combo that's elligible for an early payment discount, the early payment discount should also be displayed in the widget. Example: Invoice of 1000$ with possible EPD of 2%. A payment (with no move) is done (paid in the "early" period) for 980$. The payment is then put into a batch payment. Once in the bank rec widget, when mounting the 980$ batch payment to a statement line of 980$, the widget should display it as a batch payment line of 1000$ and add another 20$ Early payment Discount line. task-4681366 Forward-Port-Of: odoo/enterprise#92593 Forward-Port-Of: odoo/enterprise#83077
This update resolves an issue where changes to many2one fields within the website builder weren't correctly reflected in the sidebar. The fix ensures that the `data-oe-many2one-id` attribute is copied during replication, preventing incorrect data display and saving problems. This improves the accuracy of sidebar information.
Original PR description
When replicating changes from one field to other occurences of the same field in the document, the `data-oe-many2one-id` was not copied (for many2one fields). Thus it could lead to showing incorrect values in the sidebar, or saving them. This commit fixes that by adding a dispatch to handlers after the replication, and implementing a handler that copies the `data-oe-many2one-id` when needed. Steps to reproduce: - Open website builder on a blog post - Enable the "Sidebar" - Enable the "Author" in the sidebar - Click on the second occurence of the name of the author in the page - Change the "Contact" associated with the author of the post - Click on the first occurence of the name of the author in the page - Bug: the name of "Contact" is the old one - Change the "Contact" to yet another one - Save - Bug: the author is not the last one selected task-5252648
This update resolves a bug that occurred when translating content within the website editor. Specifically, adding a break element (BR) during translation caused save errors due to incorrect data handling. The fix ensures that translation branding is properly removed during non-translation mode, preventing these errors and improving website stability.
Original PR description
Scenario: - run Odoo with source code between [1] (29th october 2025) and [2] (19th november 2025) - translate a string in an embedded field with a BR added outside the translation contenteditable…
Scenario:
- run Odoo with source code between [1] (29th october 2025) and [2]
(19th november 2025)
- translate a string in an embedded field with a BR added outside the
translation contenteditable (eg. select completely a LI element and
replace the content by something else)
- save
- edit the content in source language, save (with or without any change)
Result: traceback error containing:
> File "addons/html_editor/models/ir_ui_view.py", line 66, in save_embedded_field
> model = 'ir.qweb.field.' + el.get('data-oe-type')
> ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
> TypeError: can only concatenate str (not "NoneType") to str
Cause:
Commit [1] removed o_editable on nodes that should not be editable, but
that caused those nodes to no longer have data-oe-readonly attribute.
When replacing the whole content translation node, the original content
is first removed, after which DeletePlugin.fillShrunkBlocks adds a BR
after the translation node.
This caused the ancestor [data-oe-model] to be set as o_dirty, event if
it was not editable or [contenteditable].
On save, the ancestor with .o_dirty[data-oe-model] was saved while
containing translation branding SPAN, which when editing the page in
source language, would cause an error on save.
Fix:
Up to 19.0, when the website editor is started in non-translation mode:
remove the translation branding SPAN.
[1] d4d428ff1d5be46135973aa806f206a1076bfcf7
[2] f09dc4d9d35e1e3707c9483fc6004cf162a3f4ca
opw-5234578This update fixes an issue where credit notes generated in Spain (l10n_es_edi_facturae) were failing validation by the FACe tax authority due to incorrect XML formatting. The fix ensures the required Spanish reason codes are used, improving compliance with Spanish tax regulations. Additionally, the reversal wizard has been streamlined for clarity.
Original PR description
In cases of credit notes, the xml would not be validated by the FACe. This was caused by the field 'ReasonDescription', which can only be one of the proposed field. We used to provide it in English when the available reasons are only in Spanish. Also fixed CorrectionMethodDescription. See https://www.facturae.gob.es/formato/Paginas/version-3-2.aspx for more documentation. ticket-5184181 Took the opportunity to improve the reversal wizard : In the reversal wizard, two fields 'Reason' would be displayed. Only kept the mandatory one and used it in place of the non-mandatory one. Forward-Port-Of: odoo/odoo#236684
This update ensures that the status of a sale order is correctly updated to 'Sales Order' in the Sales module after a payment is processed through the Point of Sale (PoS) system. Previously, the system didn't update the order status, leading to inconsistencies. This fix resolves a bug that prevented accurate order tracking after PoS transactions.
Original PR description
**Steps to reproduce:** - Make a quotation in the Sales module - Go to PoS, click Quotation/Order and select your quotation - Select Settle the order - Go through with the payment - Go back to the…
**Steps to reproduce:** - Make a quotation in the Sales module - Go to PoS, click Quotation/Order and select your quotation - Select Settle the order - Go through with the payment - Go back to the Quotation in the Sales module The Status widget still shows Quotation instead of Sales Order **Why the fix:** Since 18.3, the sale_order.state was not updated anymore when the state changed through the PoS. This happened because we would only change the sale_order state if there was a downpayment involved. In 18.2, we always recomputed the sale_order that was linked to the order we are currently settling. The way it is done now is part of the same way it was done in 18.2 and before, meaning we add the linked sale_order regardless of downpayments. In 18.2, we did an action_confirm on the selected sale_orders, but doing that in 18.3 will create another picking for this sale_order. This is not what we want as the picking is now handled and created by the PoS. This fix will just put the related sale orders in the "sale" state, so that users can no longer confirm it in the sales modules, which would create a second picking and create duplicates. opw-5033979 Forward-Port-Of: odoo/odoo#226008