Thursday, September 10, 2026
21 changes · saas-19.1
Resolved issues and error corrections
The scheduled process that sends Chilean electronic invoices now reports progress after each invoice, so large backlogs no longer cause the job to be disabled after repeated timeouts. This helps businesses keep invoice submissions moving reliably even during high-volume periods.
Original PR description
Steps to reproduce: - Have a large number of invoices (thousands) with l10n_cl_dte_status 'not_sent' - Let the "Cron Job - Send document to SII" cron run and time out before it can send them all -…
Steps to reproduce: - Have a large number of invoices (thousands) with l10n_cl_dte_status 'not_sent' - Let the "Cron Job - Send document to SII" cron run and time out before it can send them all - After a few consecutive timeouts, the cron gets deactivated by Odoo, leaving the backlog stuck and growing Cause of the issue: cron_send_dte_to_sii() searches for every 'not_sent' move and sends them one by one in a single unbounded loop, committing after each send but never reporting progress to the cron framework Odoo cron worker treats a job that times out without ever calling _notify_progress as a full failed run, even though most of the batch was actually sent and committed. After enough consecutive failures within a short time span, the cron is auto-deactivated, which is exactly what happens once daily invoice volume outpaces what a single cron run can send before the worker times out Solution: Report progress via ir.cron._notify_progress() after each invoice is sent. A timeout mid-run is then treated as partially done instead of failed, the cron gets rescheduled immediately instead of waiting for its daily interval, and it no longer counts towards deactivation, This lets the cron drain an arbitrarily large backlog safely over several runs instead of dying after a handful of timeouts opw-6487236 opw-6511624 Forward-Port-Of: odoo/enterprise#129789
This fixes an issue where shortened, already-approved time off could disappear from an employee's work calendar. As a result, final payslips now correctly treat those days as time off rather than worked attendance.
Original PR description
Problem ------- Fixes bug caused by PR odoo#249527. When a validated time off's dates are shortened while it stays validated (e.g. when the employee's departure date falls int he middle of the…
Problem ------- Fixes bug caused by PR odoo#249527. When a validated time off's dates are shortened while it stays validated (e.g. when the employee's departure date falls int he middle of the leave), the linked resource.calendar.leaves record was unconditionally unlinked. To reproduce: 1. Create and validate a time off request covering a whole month. 2. Register the employee's departure with a departure date in the middle of that time off. 3. Generate the employee's last payslip. The leave is correctly cut at the departure date, but since it never leaves the `validate` state, it never goes through `_validate_leave_request()` again, so its resource.calendar.leaves record is never recreated. The days that were covered by the deleted entry are no longer blocked in the employee's resource calendar, so the payslip's worked day lines (computed from resource.calendar.leaves) count them as attendance instead of time off. Cause ----- `hr.leave.write()` removed the resource.calendar.leaves record any time either the state changed away from `validate` or the leave's dates changed, regardless of whether the leave remained validated. Date-only changes on an already-validated leave never re-trigger validation, so the entry was not recreated. Solution -------- Only remove the resource.calendar.leaves record when the leave actually loses its validated state. When a validated leave's dates change but it stays validated, amend the existing resource.calendar.leaves record in place instead, falling back to creating one if none exists. Related PR: odoo#249527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287040 Forward-Port-Of: odoo/odoo#286465
Changing the delivery address on an outgoing rental transfer no longer resets the destination from the rental location to the standard customer location. This prevents rental deliveries from being routed incorrectly and keeps rental stock movements aligned with the expected rental workflow.
Original PR description
**Issue** Changing the `partner_id` of an outgoing rental transfer could reset its destination location to the partner customer location instead of the rental location. **Steps to reproduce** -…
**Issue** Changing the `partner_id` of an outgoing rental transfer could reset its destination location to the partner customer location instead of the rental location. **Steps to reproduce** - Enable Rental Transfers from Rental Configuration. - Create a Sales Order for a rental product. - Open the related delivery transfer. - Using Studio, make the Destination Location field visible. -> Current destination location is: Partner/Customer/Rental - Change the delivery address -> The destination location become: Partner/Customer **Cause** Changing the delivery address (i.e: the partner_id) triggers `_compute_location_id`: https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L949-L950 Since commit https://github.com/odoo/odoo/commit/8c90fc1fd336ee872fd67d8d72473e4f6c55b2e0, not only draft picking are recomputed. As a result, `location_dest_id` is set as `picking.partner_id.property_stock_customer` https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L959-L961 https://github.com/odoo/odoo/blob/85372b625a80ab50fe2d8a6bce49a890b2bf1665/addons/stock/models/stock_picking.py#L963 Regardless whether we are in rental setup opw-6237495 Forward-Port-Of: odoo/enterprise#123564
Fixed an issue where Time Off requests could be saved with zero days when an automation rule created an activity. This ensures employees and managers see the correct leave duration even when automated notifications or follow-up activities are configured.
Original PR description
Problem: A time off request is saved with a duration of 0 days instead of 1 day as soon as an automation rule on Time Off has an action that creates an activity. Cause: `_compute_field_value` runs…
Problem: A time off request is saved with a duration of 0 days instead of 1 day as soon as an automation rule on Time Off has an action that creates an activity. Cause: `_compute_field_value` runs the actions while the fields of the computation it wraps are still protected and not written yet. On `hr.leave` the actions run from a computation nested in `_compute_date_from_to`, so `date_from` is empty when the activity notification reads `display_name`, and `_compute_duration` stores 0. Setting `date_from` afterwards does not mark `number_of_days` to compute again since it is protected. Solution: Extract the snapshot `_filter_pre` already does into `_keep_to_compute` and wrap the post filter and the actions with it, so the fields depending on the running computation stay to compute. Same treatment as 488419a5ca49 (odoo/odoo#243611) on the pre filter. Steps to reproduce: - Enable the developer mode. - Go to Settings > Technical > Automation Rules and create a rule on the Time Off model with the trigger On create and edit. - Add an action of type Create Activity, set its Responsible to another user, and save. - Go to Time Off > New, pick an employee and a time off type, and request one working day. - Observe that the request shows a duration of 0 days. Ticket [link](https://www.odoo.com/odoo/project.task/6498783) opw-6498783 Forward-Port-Of: odoo/odoo#286791
Fixes a Point of Sale pricing issue where products with dynamically created variants could be charged with the variant extra price twice when selected from barcode search. This ensures customers are charged the correct total regardless of whether the item is scanned, searched, imported, or added as an optional product.
Original PR description
Steps to reproduce: - Create an attribute "Size" with values M and L, variants creation mode "Dynamically", and an extra price of 10 on L - Create a product at 30 using that attribute, and give the L…
Steps to reproduce:
- Create an attribute "Size" with values M and L, variants creation mode "Dynamically", and an extra price of 10 on L
- Create a product at 30 using that attribute, and give the L variant a barcode
- In the PoS, type that barcode in the search bar and click the card
Issue:
The line is added at 50 instead of 40. Scanning the barcode with a barcode reader was fixed by c1ae3261e895, but resolving the variant from the search bar still charges the extra price twice.
Cause:
The lst_price of a variant already contains the extra price of every attribute value that creates a variant ('always' and 'dynamic'); only 'no_variant' extras are missing from it and have to be carried by the order line as price_extra. This is what ProductConfiguratorPopup does, hence the correct price when the configurator opens.
Both openConfigurator(), when the resolved variant leaves a single value per attribute line and no popup is needed, and handleConfigurableProduct(), when configure is false, filter those values with create_variant !== 'always', so a 'dynamic' extra is added on top of a lst_price that already includes it. The same fix was made in 18.0 by d4fabfa08d1c but was lost when pos_store.js was refactored in saas-18.1.
Fix:
Filter on create_variant === 'no_variant' in both places, like the configurator popup. This supersedes the !opts.code condition of c1ae3261e895: product_template_variant_value_ids never holds 'no_variant' values, so the extra is now ignored however the line was added - scan, barcode search, sale order import or optional product.
opw-6531114
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#286460This fixes an issue where users could be blocked from creating records, such as sales orders, when Odoo calculated restricted fields in the background. The change lets those background calculations complete safely while keeping normal field access restrictions in place.
Original PR description
**Description of the issue/feature this PR addresses:** If a field is `computed`, `precomputed`, and has `groups` defined, an `AccessError` is raised when a user who does not have the required group…
**Description of the issue/feature this PR addresses:** If a field is `computed`, `precomputed`, and has `groups` defined, an `AccessError` is raised when a user who does not have the required group creates a record because the field is precomputed. After this commit https://github.com/odoo/odoo/pull/201565/changes/48521a311a6dc857c3808db70ed359c7866aa125, Odoo checks field access in `__get__`, so an `AccessError` is now raised. If the field is not precomputed, everything works fine. Therefore, this commit prevents the error by using `sudo()` to recompute the value. I have attached a module to demonstrate the issue. **Steps to reproduce the issue:** 1. Install the attached module. [sale_margin_security_test.zip](https://github.com/user-attachments/files/31967357/sale_margin_security_test.zip) 2. Create a sales order and add a product. 3. Try to save the sales order. The AccessError is raised. https://github.com/user-attachments/assets/54c7e4e2-005f-4ced-bb62-22d0e00049d9 For more context, this module is a simple example extracted from the OCA `sale_margin_security` module, which inherits from a mixin and adds groups to the fields: https://github.com/OCA/margin-analysis/pull/285 You can see the error in this PR: https://github.com/OCA/margin-analysis/actions/runs/34254749207/job/102157600233?pr=285#step:8:126 @Tecnativa @pedrobaeza @kmagusiak @rco-odoo @Feyensv, could you please review this? --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287257
Updates the spreadsheet component with fixes for search and replace, chart exports, chart display options, filtering, small-screen layout, and copy/paste behavior. This improves spreadsheet and dashboard reliability for users working with charts, merged cells, and loaded dashboard data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/619eeace70 [REL] 19.1.35 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/619eeace70 [REL] 19.1.35 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/fbcc69b182 [FIX] search and replace: manage invalid range [Task: 6483222](https://www.odoo.com/odoo/2328/tasks/6483222) https://github.com/odoo/o-spreadsheet/commit/67c9f4edeb [FIX] xlsx: fix geo chart xlsx export [Task: 4632983](https://www.odoo.com/odoo/2328/tasks/4632983) https://github.com/odoo/o-spreadsheet/commit/16fef34e48 [FIX] charts: show value do not work for combo chart [Task: 6528059](https://www.odoo.com/odoo/2328/tasks/6528059) https://github.com/odoo/o-spreadsheet/commit/6eeb66c497 [FIX] calendar chart: wrong groupBy choice filtering [Task: 5358625](https://www.odoo.com/odoo/2328/tasks/5358625) https://github.com/odoo/o-spreadsheet/commit/de13eebd4c [FIX] grid: hide AddRowFooter when the mainViewport is too small [Task: 6103620](https://www.odoo.com/odoo/2328/tasks/6103620) https://github.com/odoo/o-spreadsheet/commit/4e95ee8f6d [FIX] clipboard: typo on copy/paste on a merge [Task: 6515850](https://www.odoo.com/odoo/2328/tasks/6515850) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Users with Invoicing & Banks access can now undo bank reconciliations on entries that have not been reviewed without hitting an access error. Reviewed entries remain protected by the existing approval restrictions, preserving accounting controls while removing an unnecessary workflow blocker.
Original PR description
Steps to reproduce: - Install `Accounting` module - Change group of current user for "Accounting" to `Invoicing & Banks` - Accounting > Dashboard > Bank > Any reconciled bank statement line > Undo…
Steps to reproduce: - Install `Accounting` module - Change group of current user for "Accounting" to `Invoicing & Banks` - Accounting > Dashboard > Bank > Any reconciled bank statement line > Undo Reconciliation (<img width="38" height="48" alt="image" src="https://github.com/user-attachments/assets/b637e4f3-c43b-47d4-9de1-2f0e14d1efc9" />) Problem: Users with "Invoicing & Banks" access encounter an "AccessError" when undo a bank reconciliation when account move is not checked/reviewed. Cause: Upon undoing, `action_undo_reconciliation` method is called and recreates the statement move lines with `checked=True`. This value is forwarded to `account.move.write()`, where the `_is_user_able_to_review()` check requires `account.group_account_user`. As Invoicing & Banks users only have `account.group_account_basic`, therefor access check raises an AccessError. Solution: Preserve the existing `checked` state when resetting the statement line so that unchecked lines can be unreconciled while the access restriction remains for checked lines. opw-6409216 Enterprise PR: https://github.com/odoo/enterprise/pull/127895 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282411
Users with Invoicing & Banks access can now undo bank reconciliations for entries that have not been reviewed, avoiding an incorrect access error. Reviewed entries remain protected by the existing approval restrictions, preserving accounting controls.
Original PR description
Steps to reproduce: - Install `Accounting` module - Change group of current user for "Accounting" to `Invoicing & Banks` - Accounting > Dashboard > Bank > Any reconciled bank statement line > Undo…
Steps to reproduce: - Install `Accounting` module - Change group of current user for "Accounting" to `Invoicing & Banks` - Accounting > Dashboard > Bank > Any reconciled bank statement line > Undo Reconciliation (<img width="38" height="48" alt="image" src="https://github.com/user-attachments/assets/b637e4f3-c43b-47d4-9de1-2f0e14d1efc9" />) Problem: Users with "Invoicing & Banks" access encounter an "AccessError" when undo a bank reconciliation when account move is not checked/reviewed. Cause: Upon undoing, `action_undo_reconciliation` method is called and recreates the statement move lines with `checked=True`. This value is forwarded to `account.move.write()`, where the `_is_user_able_to_review()` check requires `account.group_account_user`. As Invoicing & Banks users only have `account.group_account_basic`, therefor access check raises an AccessError. Solution: Preserve the existing `checked` state when resetting the statement line so that unchecked lines can be unreconciled while the access restriction remains for checked lines. opw-6409216 Forward-Port-Of: odoo/enterprise#127895
This fix prevents invoice forms using document extraction from breaking when users click into code editor fields. It ensures the system only reacts to valid form fields, improving stability for accounting workflows that include code-based fields.
Original PR description
Follow-up of odoo/odoo#287085, as suggested by @aab-odoo: on a stable branch the fix belongs here rather than in the ace templates. Fixes odoo/odoo#286871. opw-6543997 ### The problem The `focusin`…
Follow-up of odoo/odoo#287085, as suggested by @aab-odoo: on a stable branch
the fix belongs here rather than in the ace templates.
Fixes odoo/odoo#286871.
opw-6543997
### The problem
The `focusin` listener of the extract mixin walks up from the focused node with
`closest(".o_field_widget,.o_field_cell")` and assumes whatever it finds
identifies a field. Not every `.o_field_widget` node does: a widget template
may render its own `.o_field_widget` inside the one the `Field` wrapper already
provides, and that inner div has no `name`. `web.AceField` (`widget="code"`)
does exactly that:
```html
<div name="my_field" class="o_field_widget o_field_code ...">
<div class="o_field_widget oe_form_field o_ace_view_editor oe_ace_open">
<div class="ace_editor">... <textarea class="ace_text-input">
```
The listener stops on the inner div, `getFullFieldName` finds no name and
builds `"<parent_field>.null"`. Since the name now contains a dot, `getBoxType`
takes the x2many branch:
```js
modelFieldType = this.props.record.data[parentField]?._config.fields[fieldName]?.type;
```
On a code field `record.data[parentField]` is a plain string. It is truthy, so
the optional chaining does not short-circuit, but it has no `_config` →
`undefined.fields` → `TypeError: Cannot read properties of undefined (reading
'fields')`, and the whole form breaks.
`account_invoice_extract` installs the renderer for `account_move_form` with
`force: true`, so this runs on every invoice form.
### Steps to reproduce
1. Install `account_invoice_extract`.
2. Put a `widget="code"` field on the `account.move` form view (with
`l10n_ar_edi` installed there are already two on the ARCA tab).
3. Give the field a value — with an empty value the error does not happen,
`record.data[parentField]` is `false` and the optional chaining cuts.
4. Enable developer mode and click inside the code editor.
Reproduced on a plain 19.0 runbot build.
### The fix
Restrict the selector to `.o_field_widget[name]`, so nodes that cannot identify
a field are skipped. The `focusout` listener a few lines below also matches
`.o_field_widget`, but it only calls `onBlurFieldWidget()` and never resolves a
name, so it is left as is.
The duplicated class in the ace templates looks like the actual root cause and
is handled separately in odoo/odoo#287085, retargeted to `master`.
Forward-Port-Of: odoo/enterprise#130952The Point of Sale customer list now avoids loading each row's action menu until a user actually opens it. This reduces freezes and makes browsing large customer lists much smoother, especially on slower devices.
Original PR description
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine`…
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine` instantiates a full `Dropdown` for its "≡" menu. Setting up a `Dropdown` registers about ten lifecycle hooks (`useDropdownNesting`, `useNavigation`, `useDropdownGroup`, `usePopover`, `useEffect`, ...), and each hook registration eagerly allocates two `OwlError` objects to keep a stack trace. Multiplied by hundreds of rows, this dominates the render: ~60% of the click task is spent constructing errors for menus that will never be opened. Render a plain button per row instead and only mount the `Dropdown`, driven by a `useDropdownState`, once that button is clicked. The `Dropdown` opens its popover on mount when its state is already open and is unmounted again when it closes. The placeholder button keeps the classes the `Dropdown` would add to its toggler so the DOM, the styling and the tour selectors (`button.dropdown`) are unchanged. opw-6453848 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285974
Customers using live chat embedded on an external website can now download files sent through the conversation without browser cross-origin errors. This improves the reliability of file sharing in live chat while avoiding broader changes to file access permissions.
Original PR description
**Steps to reproduce:** - Install `im_livechat` module - Copy the code from the livechat channel's widget tab - Paste it in an external website `<head>` (e.g., local python webserver on `0.0.0.0`) -…
**Steps to reproduce:**
- Install `im_livechat` module
- Copy the code from the livechat channel's widget tab
- Paste it in an external website `<head>` (e.g., local python webserver on `0.0.0.0`)
- Start a conversation and send a file from odoo
- Try to download it from the external website
- POST request is sent for the download
- Download fails: `CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.`
- Also when the file is a PDF the preview won't open: `404 (File not found)`
**Issue:**
Mix of multiple issues:
- The download is triggered using a POST request instead of a GET request
(see similar issue for the file viewer [1])
- The file route does not provide the required CORS headers, so requests
originating from the external website are blocked by the browser
- PDF files are rooted to the related path of the `pdfjs` fileviewer
(e.g. `http://0.0.0.0:8000/web/static/lib/pdfjs/web/viewer.html?file=...`)
```xml
<!--
Template rendering all the scripts required to execute the Livechat from an external page (which not contain Odoo)
-->
<template id="external_loader" name="Livechat : external_script field of livechat channel">
<!-- the loader -->
<script defer="defer" t-attf-src="{{url}}/im_livechat/loader/{{channel_id}}" type="text/javascript"/>
<!-- js of all the required lib (internal and external) -->
<script defer="defer" t-attf-src="{{url}}/im_livechat/assets_embed.js" type="text/javascript" />
</template>
```
**Fix:**
Make the `downloadFile` helper handle cross-origin URLs by falling back to a native `<a download>` click (like before) when the target route has the same origin as the embedded script. Could use `session.origin` or `new URL(document.currentScript.src).origin` for this. This is done to avoid allowing CORS on the file content route.
The file viewer issue is handled separately by [1].
For the PDF issue we could manually add the origin to the full url everywhere (but we get some `SecurityError` error from the library due to the cross-origin iframe), add the libjs library in the `assets_embed` (not sure it's possible in `im_livechat.assets_embed_external`), or block external PDF preview for now.
[1] https://github.com/odoo/odoo/pull/281330
opw-6444167
Forward-Port-Of: odoo/odoo#286180The POS customer list now calculates outstanding balances more efficiently, avoiding repeated work for each customer row. This makes opening large customer lists faster and also reduces the chance of showing the wrong balance when customers have similar names.
Original PR description
Opening the customer list with a few hundred partners is slow; part of the time is spent in `getPartnerCredit`. The `PartnerLine` template reads `this.partnerInfos` eight times per row, and each call runs `getPartnerCredit` again. For a contact, that method resolves the partner carrying the due by scanning every loaded partner for one named like `parent_name`, so the cost grows with the square of the number of partners. Cache the getter in a template variable so it is evaluated once per row, and resolve the due partner through the loaded `commercial_partner_id` instead of the name scan. This is also what the server sums the dues by, and it no longer picks a wrong homonym. `refreshTotalDueOfPartner` used the same lookup and now shares it. opw-6453848 Forward-Port-Of: odoo/enterprise#130015
Fixes a website builder issue where applying text animation across multiple text blocks could disrupt centered layouts. This keeps animated headings and paragraphs visually aligned, reducing unexpected page design changes for editors.
Original PR description
### Problem: Text animation used a single span around the full selection range. When a selection crossed block elements, this placed headings and paragraphs inside a span, producing invalid HTML and changing their layout. ### Steps to reproduce: 1. Drag & drop a snippet (like the "Cover" block) that contains page centered text 2. Select a range of text spanning multiple block elements within the added snippet 3. Add an animation to the selected text. <img width="800" height="200" alt="image" src="https://github.com/user-attachments/assets/45074927-4d60-4517-b65b-7ba6d667e060" /> ### Solution: This PR splits the selection by block and creates one inline animation wrapper per block instead. The builder applies animation options to the resulting elements as one group, without changing the document's block structure. task-5155887 Forward-Port-Of: odoo/odoo#283176
The Turkish e-Ledger export now fills line numbers automatically and keeps them continuous across monthly filings within the same fiscal period. Entries are also ordered from oldest to newest, helping exports match GIB expectations and reducing manual correction work.
Original PR description
Before: the `LineNumber` column of the e-Ledger CSV was always empty, left to be filled after the export. Since the ledger is filed monthly, whatever filled it restarted at 1 every month, while GİB expects the numbering to start once, at the beginning of the fiscal period, and to run unbroken until its end. Now: the column is written by the export. An export starting after the first day of the fiscal period is offset by the number of rows that period already counts, so February continues where January stopped, and a full-year export numbers the same rows identically. The lines are also read in ascending date order. They were sorted by the default order of `account.move.line`, the most recent first, so the first row of the file was the last entry of the period and could not be numbered 1. This reverses `EntryNumberCounter` as well, which now counts from the oldest entry. task-6424730 Forward-Port-Of: odoo/enterprise#130923 Forward-Port-Of: odoo/enterprise#127518
Users with Invoicing & Banks access can now set partners and reconcile bank statement lines without being blocked by an access error. The change prevents an internal review-state update from incorrectly requiring Bookkeeper permissions during normal bank reconciliation work.
Original PR description
Problem: Users with "Invoicing & Banks" access encounter an "AccessError" when setting a partner on a bank statement line or reconciling it with an invoice. Cause: During `set_line_bank_statement_line()`, the linked journal entry's `review_state` is reset to `False`. This internal update triggers `_check_review_state_access()`, which requires the "Bookkeeper" role to modify the review state. Although the user is only performing a bank reconciliation action, the review state access check incorrectly blocks the operation. Solution: Use the `skip_account_review_check` context when resetting `review_state` as part of `set_line_bank_statement_line()`. This bypasses the review state access check for this internal update while allowing users with "Invoicing & Banks" access to set a partner and reconcile bank statement lines successfully. opw-6409220
The accounting automatic entry wizard now properly clears and matches related accrual and destination entries when changing periods. This prevents leftover non-balanced accounting lines from cluttering records and helps keep financial data accurate.
Original PR description
The previous code wasn't reconciling the destination and accrual moves, leaving potentially non-neutral journal items and their counterpart polluting the DB. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279766
This fix ensures orders shared between trusted Point of Sale locations keep the correct session information when the restaurant app is installed. It prevents valid payments from being incorrectly blocked in another trusted shop due to stale session data.
Original PR description
**TL;DR** - in certain cases, Session is not updated on order shared on trusted pos Steps to reproduce: - Install pos_restaurant with demo data. - Have two configs: Cloth Shop and Furniture Shop. -…
**TL;DR** - in certain cases, Session is not updated on order shared on trusted pos Steps to reproduce: - Install pos_restaurant with demo data. - Have two configs: Cloth Shop and Furniture Shop. - Ensure both configs have their own individual payment method (e.g., CASH). - In Cloth Shop, add Furniture Shop as a trusted PoS. - In Cloth Shop, enable "Log in with Employee". - Open Cloth Shop and Furniture Shop in separate browsers (different users). - Refresh Cloth Shop once. - In Cloth Shop, create and save an order. - In Furniture Shop, open that order and try to pay with "CASH". Observation: * A validation error is raised: "The payment method selected is not allowed in the config of the POS session." <img width="320" height="201" alt="image" src="https://github.com/user-attachments/assets/8ca80575-76bf-4ecf-a739-08b03d543ed6" /> - although we can pay the order by a shared payment method Cause: - Refreshing Cloth Shop triggers `notify_synchronisation` due to `setCashierUpdateSession` , which pushes Cloth Shop's `pos.session` record into Furniture Shop's IndexedDB (because Cloth Shop trusts Furniture Shop). https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/pos_hr/static/src/app/services/pos_store.js#L61-L63 - When Cloth Shop saves an order, sync also pushes a copy of that order into Furniture Shop, and passed through `processDynamicRecords` - `processDynamicRecords` ensures that the Record created is in sync with server data, as Furniture Shop now has a local record of session of Cloth Shop, the record keeps `session_id` pointing to Cloth Shop's session, else it would have been left `undefined` - from the `res` we get, we set the session_id on `pos.order ` https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/utils/devices_synchronisation.js#L127-L139 - However with pos_restaurant installed we get its orveride which stores the result of super() and only returns result early when there are no` pos.order ` records in dynamicRecords. When pos.order records are present (our case), the method proceeds with its own logic but never returns result (or its own output) at the end https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/pos_restaurant/static/src/app/utils/devices_synchronisation.js#L5-L9 - so the corrected data from the super call is silently dropped. - we do not get a change to update the session id - The order keeps Cloth Shop's session ID - Furniture Shop's payment validation checks the order against its session's allowed payment methods, but since the session is still Cloth Shop's, the check fails for methods not shared between Cloth Shop and Furniture Shop (e.g., CASH). Why this is hidden in other cases: - without pos_restaurant, or if Furniture Shop had no prior knowledge of Cloth Shop's session (we made is possible by `Log in with Employee` feature, session_id would stay `undefined` and later get correctly set toFurniture Shop's session in PosOrder.setup(). https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/models/pos_order.js#L27-L30 or from here https://github.com/odoo/odoo/blob/6a3655c8efd2de68754ace38bd1ab5eb6499faca/addons/point_of_sale/static/src/app/utils/devices_synchronisation.js#L127-L139 - Both safety nets happen to be bypassed here. Fix: * Tighten the early return condition so that data is only discarded when the current configuration is not a restaurant configuration. * Also, A trusted PoS configuration cannot be a restaurant, so not returning later makes sense. opw-6465228 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282962
German Intrastat dispatch reports now correctly use region code 99 when goods originate outside Germany, aligning exports with official reporting rules. The change also improves German-locale exports by handling decimal formatting reliably and rounding item weights consistently, reducing filing errors.
Original PR description
### Issue: In Germany, the intrastat report requires region code `99` for dispatch moves where the product origin country is not DE Per the official specification (section 5.8 — Region of origin):…
### Issue: In Germany, the intrastat report requires region code `99` for dispatch moves where the product origin country is not DE Per the official specification (section 5.8 — Region of origin): "As for goods with foreign origin, code '99' should be entered" https://erhebungsportal.estatistik.de/Erhebungsportal/api/assets/files?downloadId=0c5422f111104705b021b41616ad1ecc But `99` was not being used in those cases ### Cause: `99` was already the default fallback when no `region_code` is set but `_fill_missing_values` had no condition to override the region code for dispatch moves with a non-DE origin country ### Notes: While fixing this, two additional issues were found when exporting with the German locale (`de_DE`): - `weight` and `supplementary_units` are formatted with a comma as decimal separator by the German locale, causing `float()` to raise a `ValueError` — fixed by normalizing to dot before conversion, as done in other localizations - The dispatch/arrival check was comparing against the translated label (e.g. `'Versand'`) instead of a stable identifier A new `intrastat_type_code` field with static values `arrival` and `dispatch` is added based on the existing `id` values from `default_type`, avoiding locale-dependent comparisons This improvement could be extended to other localizations - Net mass is now rounded to full kilograms per item (see §5.14 of the specification linked above) A weight rounding down to 0 kg is reported as `0` instead of being silently dropped (QWeb `t-out` omits the element when the value is `None`) Totals are computed as the sum of already-rounded per-item values to stay internally consistent ### Steps to reproduce: - Install `sale_management`, `l10n_de_account` and `accountant` - Switch to the DE company - In Settings, configure the Intrastat values: -- Default invoice transaction code: 11 -- Default refund transaction code: 21 -- Intrastat region: 07 - Create 3 products with a commodity code set and country of origin: one DE, one empty, one other country - Create and confirm a Sale Order for all products with a European partner, deliver all, create and send the invoice - Open the Intrastat report (Accounting > Reporting > Taxes & Fiscal > Intrastat) - Set the month to the current month Before the fix, all regions show 07 Expected: non-DE origin products should show 99 opw-6455585 Forward-Port-Of: odoo/enterprise#128747
The shop floor now disables the gear menu while opening a manufacturing order, preventing users from launching another dialog during the page transition. This avoids an error that could appear on slower connections and makes navigation from work orders more reliable.
Original PR description
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. *…
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. * On a work order card, click the **gear** icon to open the menu dialog. * Click **Open Manufacturing Order** on a slow network connection. * Before the MO form view finishes loading, quickly click the **gear** icon again and open another dialog (e.g. Log Note). * The MO form view loads, destroying the shop floor component. * Close the Log Note dialog. **Observed behavior:** * An `UncaughtPromiseError: Component is destroyed` error is thrown because the dialog tries to interact with the shop floor component that has already been destroyed by the navigation to the MO form view. **Cause:** * When the user clicks "Open Manufacturing Order", `doAction` is called to navigate to the MO form view, and `props.close()` immediately closes the menu dialog. However, the shop floor component is still visible while the new view is loading. * During this gap, the gear button remains clickable. If the user opens another dialog (e.g. Log Note), that dialog holds a reference to the shop floor component. When the MO form view finishes mounting, the shop floor is destroyed, and closing the stale dialog triggers operations on the destroyed component. **Fix:** * Add an `actionPending` state flag to `MrpDisplayRecord`. When the user selects "Open Manufacturing Order" from the menu dialog, an `onSelect` callback sets `actionPending` to `true`, which disables the gear button and prevents any new dialog from being opened. * The flag is only set for `openMO` (which navigates away and destroys the component), not for other menu actions like Scrap, Add Component, or Log Note which open wizard dialogs and return to the shop floor. opw-6107579 Forward-Port-Of: odoo/enterprise#130921 Forward-Port-Of: odoo/enterprise#123490
This fix prevents Argentine electronic export invoices from crashing when printed for foreign customers using a generic identification type without an ARCA code. Businesses can now reliably print posted invoices in this scenario, avoiding disruption to invoicing workflows.
Original PR description
## Description Printing any posted electronic invoice whose commercial partner has an identification type **without** ARCA code (typically the generic `VAT` type from `l10n_latam_base`, common on…
## Description
Printing any posted electronic invoice whose commercial partner has an identification type **without** ARCA code (typically the generic `VAT` type from `l10n_latam_base`, common on foreign partners of export invoices) crashes:
```
File ".../l10n_ar_edi/models/account_move.py", line 161, in _compute_l10n_ar_afip_qr_code
data.update({'tipoDocRec': int(rec._get_partner_code_id(commercial_partner_id))})
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
```
## Steps to reproduce
1. Install `l10n_ar_edi`.
2. Create a customer: Country **Spain**, Identification Type **VAT** (no ARCA code), Identification Number `ESA12345674`, ARCA Responsibility Type **Cliente / Proveedor del Exterior**.
3. Create and validate an invoice for this customer on an export electronic journal (document type 19).
4. Print the invoice → traceback above.
## Root cause
Since bb8e6fda72ae6364cf7806acb400b071f4108fc9 ([FIX] l10n_ar_edi: return the correct ARCA code when final consumer, odoo/enterprise#106881), `_get_partner_code_id()` lost its final `return partner_id_code` fallback: when the identification type has no ARCA code and the partner is not a Final Consumer, the method now returns an implicit `None`. The QR code compute casts the result with `int()`, which accepted the previous falsy return (`int(False) == 0`, rendering `tipoDocRec: 0` as in 17.0/18.0) but raises on `None` — making every such posted invoice impossible to print.
## Fix
Restore the fallback return so the method always returns the identification type code (possibly falsy) instead of an implicit `None`. The intent of bb8e6fda72ae is preserved: a Final Consumer with an identification number still gets its real code, and the other callers already handle falsy values (`partner_id_code or 0`).
Forward-Port-Of: odoo/enterprise#126714