Thursday, July 10, 2025
12 changes · saas-18.4
Enhancements to existing features
Account merging has been optimized to avoid loading very large volumes of accounting entries during the final update step. This reduces the risk of memory errors and significantly improves completion time for companies with large accounting datasets.
Original PR description
### Issue --> The final step of the `_action_merge` method updates the `code` field of the account onto which the other accounts are merged. During the write call on `code`, a dependent field…
### Issue --> The final step of the `_action_merge` method updates the `code` field of the account onto which the other accounts are merged. During the write call on `code`, a dependent field `always_tax_exigible` on `account.move` gets added to the compute chain. This causes a fetch of all `account.move` records related to journal items related to the account that is getting updated. This can lead to a MemoryError on databases with large `account.move` tables. ### Solution --> We delegate the write of the `code` field to SQL. In the account merge wizard, accounts that can be grouped are grouped by the keys --> `'account_type', 'non_trade', 'currency_id', 'reconcile', 'deprecated','name'`. Therefore, the `account_type` does not change after the merge. We can safely assume that any fields dependent on `account_type` do not need recomputation and hence, bypass the ORM for this update. ### Benchmark --> For an account with ~1.17M related `account_move_lines` and ~570k `account_moves`, | Before Fix | After Fix | |--------|--------| | TO/Memory error past TO | ~24s | #### Additional change --> Disable the prefetcher in the write call in `account.account` to optimize memory usage on databases with a large number of journal items/journal entries when writing on `code` or `account_type` in general. opw-4839985 Forward-Port-Of: odoo/odoo#216768
Vietnam VAT number checks now recognize the updated formats required under recent regulations, including the 12-digit citizen ID format for individuals from July 2025. This helps businesses register and validate Vietnamese customers and partners without incorrectly rejecting valid tax identifiers.
Original PR description
The current validation uses stdnum.vn.mst.validate(), which only accepts 10- or 13-digit MST with legacy checksum logic. It does not support the 12-digit CCCD format now required for individuals from…
The current validation uses stdnum.vn.mst.validate(), which only accepts 10- or 13-digit MST with legacy checksum logic. It does not support the 12-digit CCCD format now required for individuals from 01/07/2025 (per Circular 86/2024/TT-BTC). * This patch introduces a separate format-level validator for: • 10-digit enterprise VAT • 13-digit branch VAT (10-digit + suffix) • 12-digit CCCD (from 01/07/2025) * References: • Circular 86/2024/TT-BTC (tax registration & CCCD admin): https://thuvienphapluat.vn/van-ban/Thue-Phi-Le-Phi/Thong-tu-86-2024-TT-BTC-dang-ky-thue-565309.aspx • CCCD replacing tax ID from 01 Jul 2025: https://thuvienphapluat.vn/ma-so-thue/bai-viet/cach-doi-ma-so-thue-sang-ma-so-dinh-danh-ca-nhan-tu-0172025-200926.html • VAT ID structure 10/13 digits (Law, TT 105/2020): https://thuvienphapluat.vn/phap-luat/cau-truc-ma-so-thue-la-10-chu-so-hay-13-chu-so-phan-loai-cau-truc-ma-so-thue-nhu-the-nao-theo-quy-d-796465-178397.html --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217914 Forward-Port-Of: odoo/odoo#217253
Resolved issues and error corrections
This fixes an issue where employees with minimal permissions could use the plus/minus button to set negative product quantities in the Point of Sale cart. The change helps ensure sales entries follow permission rules and reduces the risk of incorrect orders or unintended refunds.
Original PR description
Fix issue where minimum rights employee were able to put negative orderline qty in the cart with the `+/-` button task-id: 4922318 enterprise PR: https://github.com/odoo/enterprise/pull/89669 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217774
Purchase orders now choose vendor pricing that matches the intended unit of measure in manual and replenishment flows, avoiding unexpected cheaper prices from a different unit. Make-to-order purchasing now uses the best matching vendor price and sets the purchase line unit accordingly, helping keep costs and quantities consistent.
Original PR description
This commit adjusts setting `product_uom_id` field on the generated purchase order line in the 3 main scenarios: manual purchase order, procurement from MTO, and procurement from replenishment…
This commit adjusts setting `product_uom_id` field on the generated purchase order line in the 3 main scenarios: manual purchase order, procurement from MTO, and procurement from replenishment wizard. The intended behavior is as follows: * Manual PO: The selected pricelist must respect the uom of the PO line. Even if the quantity of the line matches a pricelist with a cheaper price (but different uom), it should not be selected. If there is no pricelist with the unit of the line, the pricelist with the product base unit is chosen. If it doesn't exist too, no pricelist is chosen, and the price is left to the user (default value of 0). * Procurement from MTO: The selected pricelist must be the cheapest pricelist that respects the requested quantity, even if that cheaper pricelist has a different uom than the source of procurement (SO, MO, etc.). However, the generated PO line uses the uom of the pricelist not the source. * Replenishment Wizard: The behavior is similar to manual PO. The selected unit in the wizard must be respected, even if there is a cheaper pricelist that matches the requested quantity (with different uom). Also now, the selected vendor in the wizard doesn't affect the chosen priclist. It's only used to look for pricelists with the same partner. Task-4471379 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218018 Forward-Port-Of: odoo/odoo#205525
Images copied or dragged from the web into the website editor are now stored as proper attachments instead of being embedded as large base64 data. This keeps website content cleaner, easier to manage, and more consistent after saving.
Original PR description
Before this commit copying an image from the web and pasting it into a text snippet in the website editor would cause the image to be saved as base64 instead of being properly converted into an attachment. Steps to reproduce - open editor - add a text snippet - go to Google images, find an image and copy it (copy the image itself, not the link) - paste the image in the text snippet - save and quit the editor => the image is saved as a base64 img After the change images get properly saved as attachments.
Fixes an issue where changing a website theme or completing website setup could trigger an error after the loading screen. It also ensures the website configurator opens on the correct step when a specific step is requested in the URL, making setup and theme changes smoother for users.
Original PR description
This commit fixes 2 little oversights of [`1b86bd7`][1] that removed `params` from `context`: - We can directly retrieve the configurator initial step from the `router` service. - `with_loader` was introduced by [`ccfca27`][2] to make sure the loader was still visible until the editor is open. Now it's only set by `button_choose_theme` and always to `True`. We can therefore remove it and `keepLoader` will still be set to `true` after we call `button_choose_theme`. [1]: https://github.com/odoo/odoo/commit/1b86bd7ecf4d [2]: https://github.com/odoo/odoo/commit/ccfca271b902
Point of Sale now includes archived products when loading missing product details for existing records such as paid orders. This helps keep historical sales data complete and prevents inconsistencies when orders contain products that are no longer active.
Original PR description
Before this commit, the Point of Sale system failed to load archived products when retrieving missing products for loaded records. This caused various issues, for instance, when loading paid orders, any archived products included in those orders would not be loaded, leading to data inconsistencies and operational problems. opw-4904124 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217541
Multi-currency invoice payments with exchange differences are now reconciled correctly after export and re-import. This prevents exchange difference lines from being left unmatched, avoiding unbalanced accounting entries in journal items.
Original PR description
# How to reproduce the issue - Create an invoice with price 1000 in a non-company currency (e.g., CHF). - Modify the currency rate after the invoice date, then generate the payment for this invoice.…
# How to reproduce the issue - Create an invoice with price 1000 in a non-company currency (e.g., CHF). - Modify the currency rate after the invoice date, then generate the payment for this invoice. - This will generate three journal entries (invoice, payment, and currency exchange difference). - Export those journal entries and include in the export the `matching_number`, `currency`, and `amount_currency` fields. - Import those three entries with the matching number and post them. - In the Journal Items, the line corresponding to the currency exchange difference is not matched with the lines from the invoice and the payment, leading to an unbalanced credit and debit. # Cause In `_prepare_reconciliation_single_partial` within `account_move_line`, the reconciliation is stopped by checking whether the debit/credit is fully matched. However, this check only considers `amount_residual_currency` and not `amount_residual`, which, in the case of an exchange difference, are different. opw-4776188 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217565 Forward-Port-Of: odoo/odoo#216097
When an expense is reinvoiced to a customer through a sales order, its analytic distribution is now copied to the related sales order line. This keeps reporting and cost allocation accurate without requiring users to re-enter analytic details manually.
Original PR description
#### Step to reproduce: - Enable Analytic accounting in Accounting settings - Create a sale order - Show Analytic Distribution - Create an expense and put this sale order in the "Customer to…
#### Step to reproduce: - Enable Analytic accounting in Accounting settings - Create a sale order - Show Analytic Distribution - Create an expense and put this sale order in the "Customer to Reinvoice" field. - Add an Analytic Distribution - Create Report - Submit to Manager - Approve - Post Journal Entries #### Curent behavior: - No analytic_distribution on the sale_order #### Expected behavior: - analytic_distribution form the expense should be copied to the sale_order #### Cause: analytic_distribution was not set at the creation of the sale order from the account_move `_sale_get_invoice_price()` is called only in `_sale_create_reinvoice_sale_line()` which is only called in `_prepare_analytic_lines()`. According to [this note](https://github.com/odoo/odoo/blob/18.0/addons/sale/models/account_move_line.py#L31-L32) `_prepare_analytic_lines()` is called only on `move.line` having an `analytic_distribution`. Ticket [link](https://www.odoo.com/odoo/project/967/tasks/4710137) opw-4710137 Forward-Port-Of: odoo/odoo#217725 Forward-Port-Of: odoo/odoo#216291
The point of sale integration now prevents employees with minimal access rights from setting negative quantities through the ticket refund flow. This keeps refund handling aligned with staff permissions and reduces the risk of incorrect order adjustments.
Original PR description
Fix issue where when `pos_urban_piper` was installed, minimal right employee were able to set negative orderline qty with a refund through the ticket screen. task-id: 4922318 community PR: https://github.com/odoo/odoo/pull/217774 Forward-Port-Of: odoo/enterprise#89669
Bank reconciliation now requires an exact reference or move name match before automatically pairing statement lines with accounting entries. This prevents incorrect matches when a shorter reference appears inside a longer label, reducing reconciliation mistakes.
Original PR description
Actually, we are matching to blindly for full matches. We only check if aml.move_name or aml.ref is present in st_line label.
But this cause issues with move names like dates, where you could have :
- move_name = 2025/123
- label contains 2025/1234567
In this case, we don't want to match, as 2025/123 is not perfectly present in the label.
So this commit update the condition so we need now to have a perfect full match between st_line label and aml.ref or aml.move_name.
no-task
Forward-Port-Of: odoo/enterprise#89248This fixes how Swiss payroll monthly summaries are grouped during ELM transmission preparation. It helps ensure payroll reporting totals are calculated correctly, reducing the risk of inaccurate monthly declarations.
Original PR description
Forward-Port-Of: odoo/enterprise#89839