Wednesday, September 2, 2026
40 changes · 19.0
Resolved issues and error corrections
Fixes an issue where the website builder showed an inaccurate preview for the header width setting on boxed header layouts. This helps users make design changes with confidence because the applied setting now matches the selected header type.
Original PR description
The header width option is not previewed properly on the header template `template_header_boxed`. This happens because this template is not compatible with the action `previewableWebsiteConfig` (its width can't be previewed by adding a single class). This commit fixes the problem by using the action `websiteConfig` instead of `previewableWebsiteConfig` when this template is set. task-6420611 Forward-Port-Of: odoo/odoo#282311
The website editor’s block search field now shows a pointer cursor when users hover over the clear icon in browsers that display it. This small usability fix makes it clearer that the icon can be clicked to clear the search text.
Original PR description
Steps to reproduce: - Open the website editor. - Open the "Insert a block" dialog. - Enter text in the search bar. - Hover over the clear icon. => The cursor does not indicate that the icon is clickable. Before this commit, the search clear icon kept the default cursor. After this commit, the clear icon uses a pointer cursor to indicate that it is clickable. Note that Firefox does not natively add this clear icon to search inputs, unlike Chrome. This fix only affects browsers that render it. task-6259086
This fixes online point-of-sale payments so they are not incorrectly treated as adjustable when restaurant features are enabled. It helps prevent tips or payment adjustments from being applied to online payment lines by mistake.
Original PR description
In commit ea56e09c1adb, the `canBeAdjusted` override on `PosPayment` was accidentally replaced with `cancelPayment`. However, `canBeAdjusted` is required when `pos_restaurant` is installed to prevent online payment lines from being treated as adjustable (for tips/adjustments). This commit restores `canBeAdjusted` returning `false` for online payments and removes the unused `cancelPayment` method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The appointment bookings calendar now opens on the next upcoming booking instead of jumping to the most distant future booking. This helps staff quickly see the most relevant schedule when managing appointment types, while preserving existing booking list behavior.
Original PR description
Problem: The bookings calendar of an appointment type opens on the week of the most distant booking instead of the next one, even when a booking exists later the same day. Cause:…
Problem: The bookings calendar of an appointment type opens on the week of the most distant booking instead of the next one, even when a booking exists later the same day. Cause: `action_calendar_meetings` sets the landing date from `appointments[0].start`, where `appointments` is `self.meeting_ids.filtered_domain(domain)`. `calendar.event` is ordered on `start desc` and a one2many is read in the order of its comodel, so the first record is the furthest booking rather than the next one. The original `search([...], order='start')` was replaced by the one2many in 14b5caccc325 (odoo/enterprise#23191). Solution: Sort the filtered bookings on `start` in `action_calendar_meetings`. That method is the only place the initial date is built, and `action_calendar_event_view_request` reuses it for the gantt start date, so both entry points are covered. `calendar.event` keeps its `start desc` order, which the booking list views rely on. Steps to reproduce: - Go to Appointments. - Open the appointment type "Schedule a Demo" and click Appointments. - Click New, set the date to later today, save and go back. - Click New, set the date to one year from now, save and go back. - Go back to Appointments, reopen "Schedule a Demo" and click Appointments. - Switch to the calendar view. - Observe that the calendar opens on the week of the booking one year from now. Ticket [link](https://www.odoo.com/odoo/project.task/6480029) opw-6480029
This fixes an eCommerce product page issue where multi-checkbox attribute options could become selected automatically after refreshing the page. Shoppers now see the intended default state, reducing confusion and preventing unintended product option choices.
Original PR description
**Steps to reproduce:** 1. Create a product. 2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio). 3. Publish the product and open its page on eCommerce. 4. Verify that no…
**Steps to reproduce:**
1. Create a product.
2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio).
3. Publish the product and open its page on eCommerce.
4. Verify that no multi-checkbox option is selected by default.
5. Refresh the page twice.
**Issue:**
On the second page refresh, the first option of the multi-checkbox attribute is automatically selected, and the URL is updated with its parameter.
**Cause:**
- `_prepare_product_values` construct attribute combinations by mapping requested `attribute_values` query parameters line by line.
- When URL query parameters were present (e.g., set after the first refresh), the fallback logic `or ptal.product_template_value_ids.filtered('ptav_active')[:1]` treated unselected `multi_checkbox` attribute lines as missing required selections rather than empty selections, forcing them to default to their first active option.
**Fix:**
If no selection is provided for `multi_checkbox` line, return an empty recordset instead of falling back to the first active option.
opw-6494697This fixes Mexican payroll calculations so minimum wage employees remain protected from IMSS deductions even when they receive extra pay such as commissions. It also prevents payroll discrepancies from adjusted schedule days and ensures employment subsidy eligibility is not incorrectly reduced by unpaid absences.
Original PR description
According to LSS Art. 36, minimum wage workers are exempt from IMSS deductions. Previously, the system evaluated the period's total gross wage instead of the daily wage, which caused incorrect…
According to LSS Art. 36, minimum wage workers are exempt from IMSS deductions. Previously, the system evaluated the period's total gross wage instead of the daily wage, which caused incorrect withholdings when a minimum wage employee received extra pay (like commissions). We now evaluate the `l10n_mx_daily_salary` directly to protect minimum wage workers while ensuring correct deductions for higher earners with unpaid leaves. Since calculations rely on `schedule_days` retrieved from the schedule table, users commonly adjust these values (e.g., from 15 to 15.2, or 30 to 30.4). To prevent discrepancies caused by this practice, we now round the `schedule_days`. Finally, this commit fixes the employment subsidy eligibility threshold. Previously, the limit was incorrectly reduced by unpaid absences. This caused a double-counting effect (since absences already lower the actual gross wage) and wrongly disqualified employees. The subsidy limit is now based strictly on the full payroll schedule length, while the ISR minimum wage exemption correctly continues to consider actual worked days. target: 19.0 task-6370959
This fixes how event ticket purchase limits are calculated when a ticket or slot is sold out. Sold-out options now correctly show zero availability instead of being treated as if the normal maximum order limit still applies, reducing the risk of incorrect booking behavior for future sales flows.
Original PR description
### Steps to reproduce: event = env['event.event'].create({ 'name': 'Repro Event', 'date_begin': '2026-09-01 08:00:00', 'date_end': '2026-09-01 18:00:00', }) ticket =…
### Steps to reproduce:
event = env['event.event'].create({
'name': 'Repro Event',
'date_begin': '2026-09-01 08:00:00',
'date_end': '2026-09-01 18:00:00',
})
ticket = env['event.event.ticket'].create({
'event_id': event.id,
'name': 'VIP',
'seats_limited': True,
'seats_max': 1,
})
env['event.registration'].create({
'event_id': event.id,
'event_ticket_id': ticket.id,
'name': 'Attendee 1',
'state': 'open',
})
ticket.seats_available -> 0
ticket.is_sold_out -> True
result = ticket._get_current_limit_per_order(event=event) print(result) # {ticket.id: 30} -- expected {ticket.id: 0}
### Issue and Expected
`_get_current_limit_per_order()` used `if not seats_available:` to detect the "no limit" case returned by `_get_seats_availability()`. That check is truthy for both `None` (genuinely no limit) and the integer `0` (fully booked), so a sold-out ticket/slot combination was incorrectly treated as unlimited and returned `limit_max_per_order or EVENT_MAX_TICKETS` (e.g. 30) instead of `0`.
### Fix
`_get_seats_availability()` explicitly documents `None` as the "no limit" sentinel, with `0` meaning "constrained, zero seats left". Use `seats_available is None` to preserve that distinction instead of a falsy check.
No functional regression was found in the current website_event flow: sold-out slots/tickets are filtered or re-derived independently before reaching this value in every existing UI path. This fixes the underlying contract of the method itself, so future or additional callers don't inherit the wrong value.
https://github.com/odoo/odoo/issues/284098
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix ensures restaurant table orders edited on one point-of-sale device are still saved even after another device synchronizes the same table. It prevents newly added order lines from disappearing, reducing the risk of missed sales and service mistakes in multi-device environments.
Original PR description
Steps to reproduce: - Device A opens table 10 and adds a product - Device B opens table 10, then goes back to the floor plan - Device A goes back to the floor plan => The lines added on A are lost, they are never synced to the database, nor to the other device When B triggers a synchronisation, A reads the open orders from the server. The local lines of A are kept, but `setup`, which is also called when a record is updated, resets the dirty flag of the order. Going back to the floor plan calls `syncAllOrders`, which filters the order out because it is not dirty anymore, so the lines are never sent. The dirty flag is now kept when the record is updated with server data, since that data does not contain the changes made locally and must be synced in the next synchronization call task-id: 6486258 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Product image thumbnails now remain evenly sized and centered when auto-cropping is disabled. This keeps product pages looking consistent and makes thumbnail selection easier for shoppers, even when images have very different shapes.
Original PR description
Steps to reproduce: =================== 1. Add several images to a product, one of them much wider than tall. 2. On the product page, set the image ratio to "Disabled". 3. Move the thumbnails below…
Steps to reproduce: =================== 1. Add several images to a product, one of them much wider than tall. 2. On the product page, set the image ratio to "Disabled". 3. Move the thumbnails below the image. => The wide thumbnail sits at the top of its slot, with blank space under it. Root cause: =========== Thumbnails are given a fixed width of 64px and take their height from `aspect-ratio: var(--o-wsale-product-image-ratio)` [1]. With cropping disabled that variable is `auto`, so each thumbnail keeps the shape of its own image and they no longer share a height. They sit in a flex row, which stretches every slot to the height of the tallest one. The image inside keeps its own height and stays at the top of the slot, so a wide image leaves the rest of its slot empty. The slots are only stretched when the images differ in height, which is why the problem needs cropping to be disabled, and why it does not appear when every image is a landscape one. - [1] sized the thumbnails from the image ratio. Fix: ==== Center the thumbnails in the row so each one keeps the height of its own image instead of being stretched to the tallest. Their width stays at 64px, so a row of wide images still takes the same space as before and none of them is pushed out of the container. [1]: 670b1daa2254 opw-6472484 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes several cases where Odoo showed incorrect information or failed to refresh data, including accounting report matching, POS customer details, shipping carrier selection, timesheet status colors, and appointment contact names. It improves reliability across affected business processes so users see the right data and avoid avoidable errors.
This fix ensures that data loss prevention activity is recorded when a spreadsheet is frozen. It improves auditability and helps businesses track sensitive document actions more reliably.
Original PR description
Task: 6389096 Forward-Port-Of: odoo/enterprise#128749 Forward-Port-Of: odoo/enterprise#126461
The helpdesk team card now displays the email alias aligned with the team name. This small visual fix makes the interface cleaner and easier to read for users managing helpdesk teams.
Original PR description
In this commit, we remove the margin before the mail alias, ensuring aligment within the helpdesk team card. task-6416578 Forward-Port-Of: odoo/enterprise#129865
The Romanian tax return previously shown as "Tax" is now labeled "D300". This makes it easier for users to identify the correct declaration when selecting or generating tax returns.
Original PR description
Before this commit: When generating a Romanian tax return, one of the return types in the list was labeled "Tax", which was too generic to know which specific tax declaration it referred to. After this commit: The tax return is now renamed to "D300", making it easy to identify this return in the list instead of seeing a generic "Tax" label. task - 6388087
This fix ensures cost of goods sold stays accurate when a sale is delivered and invoiced in multiple steps under average cost valuation. Businesses avoid incorrect negative cost entries and get financial reports that reflect the actual value of delivered stock.
Original PR description
## HOW TO REPRODUCE: - Create a product AVCO Perpetual - Receive 10 units with a unit price of $10 => Product average price is now $10 - Create a Sale Order for 10 units, confirm, deliver and invoice…
## HOW TO REPRODUCE:
- Create a product AVCO Perpetual
- Receive 10 units with a unit price of $10 => Product average price is now $10
- Create a Sale Order for 10 units, confirm, deliver and invoice => COGS are at $100
- Receive 1 unit with a price of $5 => Product average price is now $5
- Update SO and add 1 unit, deliver and invoice this new unit => New invoice COGS is $-45
This is because Odoo computes the COGS for the whole SO, and decided that the value of the deliveries is the `quantity * standard_price`, which would means `11 units * $5 = $55`. Because the 1st invoice has a COGS balance of $ 100, the 2nd invoice is set to $ -45.
This behavior is inconsistent with how it was done in previous versions. Furthermore, if we added the +1 unit in a new invoice, the COGS would have been $ 5, for a total products COGS of $ 105.
- - -
With this fix, the COGS are computed using the average of the move value. So if the first move value is $100, and the second is $5, then the global COGS for the sale order should be $105. Because the first invoice COGS are already at $100, the second invoice COGS must be $5.
OPW-6442049
---
## TEST RESULT WITHOUT FIX:
```
2026-08-21 08:00:11,722 28203 INFO oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: Starting TestAngloSaxonValuation.test_cogs_average_multiple_invoices_and_deliveries ...
2026-08-21 08:00:13,055 28203 INFO oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: ======================================================================
2026-08-21 08:00:13,055 28203 ERROR oes_test_19.0 odoo.addons.sale_stock.tests.test_anglo_saxon_valuation: FAIL: TestAngloSaxonValuation.test_cogs_average_multiple_invoices_and_deliveries
Traceback (most recent call last):
File "/home/odoo/Odoo/src/19.0/odoo/addons/sale_stock/tests/test_anglo_saxon_valuation.py", line 1935, in test_cogs_average_multiple_invoices_and_deliveries
self.assertRecordValues((cogs_line_1 | cogs_line_2), [
File "/home/odoo/Odoo/src/19.0/odoo/odoo/tests/common.py", line 727, in assertRecordValues
self.assertSequenceEqual(expected_reformatted, record_reformatted, seq_type=list)
AssertionError: Lists differ: [{'ac[142 chars]it': 5.0}, {'account_id': 3566, 'debit': 5.0, 'credit': 0.0}] != [{'ac[142 chars]it': 45.0}, {'account_id': 3566, 'debit': 45.0, 'credit': 0.0}]
First differing element 2:
{'account_id': 3536, 'debit': 0.0, 'credit': 5.0}
{'account_id': 3536, 'debit': 0.0, 'credit': 45.0}
[{'account_id': 3536, 'credit': 100.0, 'debit': 0.0},
{'account_id': 3566, 'credit': 0.0, 'debit': 100.0},
- {'account_id': 3536, 'credit': 5.0, 'debit': 0.0},
+ {'account_id': 3536, 'credit': 45.0, 'debit': 0.0},
? +
- {'account_id': 3566, 'credit': 0.0, 'debit': 5.0}]
+ {'account_id': 3566, 'credit': 0.0, 'debit': 45.0}]
? +
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prAttendance managers can now access attendance records without errors when overtime rules trigger regeneration. Editing overtime rule settings is also limited to HR Officers, helping keep payroll-related configurations under the right control.
Original PR description
Issue ===== The overtime rules searches the model `hr.version` for versions eligible for attendance regeneration. However, an attendance manager does not have access to `hr.version`, hence an access error is raised. The attendance manager is also able to create and edit overtime rulesets and rules, which should only be done by an HR Officer. Fix ===== - Use `sudo()` to search versions in the attendances regeneration method. - Prevent non-HR-Officers to create or edit overtime rulesets or rule records by making them readonly and fixing the `boolean_radio` widget. TaskID-6128198
This fixes an issue where choosing a website theme could leave the site's header and footer unchanged. The update ensures theme setup runs at the right time and reliably identifies the active website during installation, so business users see the selected design applied as expected.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283174
This fixes a timing issue in the Mail app where the suggestion list could reopen after being dismissed, causing the Escape key to close the wrong item. Users should see more reliable reply dismissal behavior, and automated checks should be less prone to false failures.
Original PR description
Two independent causes made "reply: discard on pressing escape" red, one commit each. "[FIX] mail: wait for the mention suggestions before Escape" is the one that fixes the reported failure, and it holds on every branch: the test presses Escape while the mention fetch is in flight, and the suggestions arriving from the server re-open the list that Escape closed, so the re-opened list takes the second Escape and the reply is never discarded. The test now waits for the fetched suggestions before pressing Escape. "[FIX] mail: keep the suggestion list closed on a re-render" backports "[FIX] mail: keep composer suggestion list closed on unrelated re-render", which entered at 19.0 and never came down. Here NavigableList is re-opened on every patch, so opening the emoji picker after Escape brings the dismissed list back, and it then steals the Escape meant for the picker. https://runbot.odoo.com/odoo/error/946314 Forward-Port-Of: odoo/odoo#285927 Forward-Port-Of: odoo/odoo#284725
Fixes a Sales Timesheet billing issue where manually increasing the quantity on an earlier invoice could prevent later timesheet entries from being invoiced. Businesses can now invoice future periods correctly even if a prior invoice was adjusted, while keeping refund-related behavior intact.
Original PR description
## Issue When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent…
## Issue
When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent logged hours are already covered by the previously over-invoiced amount, blocking the billing of the most recent timesheet entries.
## Steps to reproduce
1. Install *Sales Timesheet* (`sale_timesheet`)
2. Create a Product P
- Product Type: Service
- Invoicing Policy: Based on Timesheets
- Create on Order: (Project &) Task
3. Create an SO:
- Customer: Any
- Product: P (any quantity)
- Confirm
4. Record hours on the task created:
- 06/01/2026 (June 1st): 1 hour
- 07/01/2026 (July 1st): 1 hour
5. Create the invoice for the June timesheet entry (by setting a timesheets period when creating the invoice), then **change the quantity to any value strictly greater than 2** and confirm.
6. Create the invoice for July
7. **An "Invalid Operation" error appears, stating that there's nothing to invoice, even though the timesheet entry from July was never invoiced.**
## Cause
Since https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20, the computation of the quantity to invoice changed to include the difference between the quantity delivered and the quantity already invoiced. In the flow described by the steps to reproduce above, the quantity to invoice is larger than the quantity delivered, making the `qty_to_invoice` equal to `0.0`.
https://github.com/odoo/odoo/blob/626d31fa0191bfe7ca8e1fcf177357eeeb60f2c7/addons/sale_timesheet/models/sale_order.py#L331-L334
The reason for the fix above being the partial refunding of timesheet-related invoices, we can keep that solution when working with refunded invoices, and keep the previous behavior for other cases.
This solution solves the issue in the steps to reproduce above, but was also manually tested on the issues from https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20 and https://github.com/odoo/odoo/commit/64cf4afabd0c5ef040cf87fc6f3125fe0bb81bbb.
opw-6485674
Forward-Port-Of: odoo/odoo#286043
Forward-Port-Of: odoo/odoo#284470French e-invoicing now ignores PDP responses that do not include a tracking ID. This prevents scheduled status updates from crashing and helps invoices and vendor bills continue processing reliably.
Original PR description
Steps to reproduce: - Install `l10n_fr_pdp` and `l10n_be` module - Activate `French e-invoicing` (you need to put your DB in test mode) (i.e: `account_peppol.edi.mode = 'test'` in system parameter)…
Steps to reproduce:
- Install `l10n_fr_pdp` and `l10n_be` module
- Activate `French e-invoicing` (you need to put your DB in test mode)
(i.e: `account_peppol.edi.mode = 'test'` in system parameter) Refer this Documentation https://www.odoo.com/documentation/19.0/applications/finance/fiscal_localizations/france.html?highlight=e%20invoicing#localizations-france-e-invoicing-fac-elec-config
- Create a Invoice and Sent with `E-invoicing`
- Run `PEPPOL: retrieve new documents` Cron
- In Invoice Other Info > `E-Invoicing Status` should be in `Done` state
- Now Vendor Bill is created for that invoice > Cancel that bill with reason > Check `E-Invoicing Status` response for bill(one response will be without UUID)
- Go to schedule actions > `PEPPOL: update message status`
- Run it and get the traceback: `KeyError: 'false'`
Issue:
When sending a lifecycle response to the French PDP, `_pdp_send_response` calls the `/api/pdp/1/send_response` endpoint and expects IAP to return a `message_uuid` for each response.
However, IAP return a response without a message UUID, for example: ` {'messages': [{'message_uuid': False}]}` `_pdp_send_response` currently assumes that every returned message has a valid UUID and creates an `account.peppol.response` with:
```
'peppol_message_uuid': False
'peppol_state': 'processing'
```
This leaves an `account.peppol.response` in `processing` state without a UUID that can be used to track it.
During the next execution of `_cron_peppol_get_message_status`, `_peppol_get_message_status` retrieves this response through `_peppol_get_documents_for_status` and builds `uuid_to_record` using `peppol_message_uuid` as the key. The resulting mapping contains the Python value `False` as a key.
The cron then calls the PDP `1/get_document` endpoint with this invalid UUID. IAP returns it as the string `'false'`, which is passed to `_peppol_process_messages_status`. The French PDP implementation tries to retrieve the corresponding record with: `uuid_to_record[uid]`
Since the mapping contains `False` while `uid` is `'false'`, this raises: `KeyError: 'false'`
This failure prevents the status cron from completing the processing of the messages.
Solution:
Avoid creating the `account.peppol.response` when IAP does not return a `message_uuid`. A response without a UUID cannot be tracked through the PDP status flow, so creating it in `processing` state only leaves an
invalid record that will later cause the status processing to fail.
opw-6453133
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281691This fixes a crash that could happen when creating a repair from a helpdesk ticket after the returned product was changed. The system now handles cases where the return item no longer matches the ticket product, allowing users to continue the repair workflow without an error.
Original PR description
## Steps to Reproduce: - Install the `helpdesk_repair` module. (with demo data) - Open the ticket titled **"Cabinet Colour and Lock aren't proper"**. - Go to Returns and change the product in Operations. - Click the "**Repair**" button on the ticket. ## Error: `IndexError - tuple index out of range` ## Cause: When the product on the picking does not match the ticket's product, the filtered picking recordset is empty. Accessing `[-1]` on an empty recordset raises an _IndexError_. ## Fix: Use `[-1:]` instead of `[-1]` when retrieving the matching picking, so an empty recordset is handled. sentry-7692929099
This fixes a manufacturing issue where entering the produced quantity before picking components could incorrectly show zero component consumption and block completion with a warning. Manufacturing orders now correctly consume reserved components, including partial quantities, so production can be completed accurately.
Original PR description
Steps to reproduce --- 1. Set the warehouse Manufacture route to 2 steps (Pick Components). 2. Create a product to manufacture whose bill of materials has a lot-tracked component, and keep that…
Steps to reproduce --- 1. Set the warehouse Manufacture route to 2 steps (Pick Components). 2. Create a product to manufacture whose bill of materials has a lot-tracked component, and keep that component in stock. 3. Create and confirm a manufacturing order for it; a Pick Components transfer is generated. 4. Set the produced quantity (`qty_producing`) on the order before validating the Pick Components transfer. 5. Validate the Pick Components transfer, then Produce All. A consumption warning shows the components as Consumed 0 instead of producing the order. Issue --- Entering `qty_producing` before the Pick Components transfer is validated runs `_set_qty_producing` while the components are not reserved yet (they have not reached pre-production), so the tracked component stock moves stay at a zero quantity and unpicked; validating the transfer afterwards reserves them to the full quantity but never sets `picked`. At `button_mark_done`, `_set_quantities` only recomputes and picks the component stock moves when `qty_producing` is zero, so with the quantity already set `_set_qty_producing` is skipped and the mark-done fallback picks only `manual_consumption` stock moves, leaving the auto-consumption component stock moves unpicked. https://github.com/odoo/odoo/blob/0d44f26d9b0fb1c1a5db463cf1f8dd0d3c72ba26/addons/mrp/models/mrp_production.py#L2933-L2943 Since `_get_consumption_issues` counts consumption from picked stock moves only, it reads 0 consumed and raises the warning even though the components are fully reserved. https://github.com/odoo/odoo/blob/0d44f26d9b0fb1c1a5db463cf1f8dd0d3c72ba26/addons/mrp/models/mrp_production.py#L1784-L1791 The zero-quantity gate comes from https://github.com/odoo-dev/odoo/commit/ab432cf77311ba852c59ae8675ad4c2dab3bfdf4, which wrapped `_set_qty_producing` in `_set_quantities` to preserve a hand-entered quantity and, as a side effect, stopped picking the component stock moves in that path. When the quantity is already set, the auto-consumption component stock moves are now marked `picked`: a move reserved above what the run consumes (`should_consume_qty`) is trimmed down to it so producing part of the order consumes only its share and backorders the rest, while a move reserved at or below it is picked as reserved so an under-supplied component is consumed at what is available. opw-6415931
Users adding a certificate key file will no longer see a misleading error when they leave the password field empty. The warning now appears only when a password was entered but is incorrect, reducing confusion during certificate setup.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283589
This fixes a setup omission so the Greek e-invoicing module is included in Odoo's translation workflow. It helps ensure users can receive translated text for this module in supported languages.
Original PR description
Commit https://github.com/odoo/odoo/commit/45bd522dde7a67194e14a40d66944a2e34d1f79d introudced a new module without it's related `weblate.json` entry. This commit fixes this omission. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285570
Italian withholding tax returns submitted in quarter-ending months no longer incorrectly open the quarterly VAT export. This prevents failed exports or LIPE files being attached to the wrong return, helping users file the correct Italian tax reports.
Original PR description
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the…
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the kind of return, so every Italian return locked on a quarter month was treated as a LIPE. Submitting the withholding tax return therefore opened the LIPE export wizard. Depending on the record the wizard receives, it either crashes while reading the VP lines missing from the withholding report, or silently generates a LIPE file and attaches it to another return. Add an `is_lipe_return` field telling whether the return actually produces the LIPE. Steps to reproduce: - Install `l10n_it_xml_export` and `l10n_it_edi_withholding_reports` on an Italian company with monthly returns - Open Accounting > Reporting > Tax Return - Review and submit the withholding returns up to February - Review then submit the March withholding return --> The LIPE export wizard opens, and the export fails on the withholding report. opw-6255016 Forward-Port-Of: odoo/enterprise#125263
This update ensures the Indian stock localization installs the accounting-stock dependency it already relies on. It prevents test and setup failures when related e-waybill stock screens need country information from stock accounting.
Original PR description
The view 'l10n_in_ewaybill_stock.view_picking_form_inherit_ewaybill' is broken in single-app tests because it depends on stock.picking:country_code. That field is provided by module 'stock_account' through auto_install relationship. 'stock_account' auto_installs with 'stock' and 'account' installed. This condition exists on stable so it's safe to add this dependency. The dependency is added to l10n_in_stock because it seemed like the logical place where 'account' and 'stock' functionality comes together. [l10n_in_ewaybill_stock] ──[depends]──> [l10n_in_stock] [l10n_in_stock] ──[depends]──> [stock] [l10n_in_stock] ──[depends]──> [l10n_in] ──[depends]──> [account_tax_python] ──[depends]──> [account] REF Runbot: https://runbot.odoo.com/odoo/error/945482 Forward-Port-Of: odoo/odoo#284990
Fixed an issue that could prevent shoppers from opening the website homepage after adding a product to their cart when the site header was disabled. This helps businesses using simplified or single-page storefront layouts avoid a visible error for customers.
Original PR description
Currently an exception is generated when the user tries to visit the website home page after adding a product to the cart as follows: - Install the `website_sale` module with demo data - Go to view and disable `template_header_default` view - In another incognito browser, add any product to the cart - Go to main page > Error occurs This issue occurs when a user tries to create a website like a single-page application (no need for a header) because `cache_quantity` is `None` as the `my_cart_quantity_re` regex is not found in html page as user hide the header which include cart. This commit fixes the above issue by returning early from the method when `cache_quantity` is `None`, preventing an error caused by calling the `update` method on a `None` value. Sentry-7505670739
This fix makes Odoo’s PDF tools expose a needed PDF page component consistently across supported PDF library versions. It reduces version-related test failures and helps keep PDF-related maintenance more reliable without changing user-facing behavior.
Original PR description
Prior to this commit, `PageObject` was not re-exported by `odoo.tools.pdf`, forcing tests to patch internal module paths like `PyPDF2._page.PageObject`. This resulted in test failures depending on the installed PDF library version: - `pypdf` (>= 3.0.0): `PyPDF2` submodules no longer exist. - `PyPDF2` 1.x: `PageObject` resides in `PyPDF2.pdf` rather than `PyPDF2._page`. To resolve this, this commit re-exports `PageObject` through `odoo.tools.pdf` across all backend wrappers. runbot-946795
This fix reverts a recent point-of-sale restaurant change that caused already-sent items to print again in the kitchen when new items were added to the same table. It prevents restaurants from preparing duplicate food or drinks by mistake, reducing waste and confusion during service.
Original PR description
Revert of the PR (https://github.com/odoo/odoo/pull/266070) which is causing issues with the reprint order. Keep fix of PR (https://github.com/odoo/odoo/pull/281676) which was merged after the one causing issue. POS with: - preparation printer for food categ - preparation printer for drinks categ - open table 1 - add water - sent to preparation (print water OK) - go to floor plan - open table 1 again - add burger - sent to preparation (print burger OK) (print water again NOT OK) Some restaurants are preparing the food twice in the kitchen and throwing it away since it was not ordered again, so we revert this change for now. task-id: 6230594 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes internal Sign module tests so they work consistently with different supported PDF library versions. It helps prevent avoidable test failures during maintenance and upgrades, without changing the user-facing signing experience.
Original PR description
Prior to this commit, `PageObject` was not re-exported by `odoo.tools.pdf`, forcing tests (such as `test_origin_offset_translation` in `sign`) to patch internal module paths like `PyPDF2._page.PageObject`. This resulted in test failures depending on the installed PDF library version: - `pypdf` (>= 3.0.0): `PyPDF2` submodules no longer exist. - `PyPDF2` 1.x: `PageObject` resides in `PyPDF2.pdf` rather than `PyPDF2._page`. To resolve this: - `PageObject` has been re-exported through `odoo.tools.pdf`. - Update `test_origin_offset_translation` to import `PageObject` via `odoo.tools.pdf` and use `patch.object` with standard attribute names (`cropbox`, `add_transformation`). runbot-946795
Consolidated invoices for Malaysian PoS orders now avoid showing misleading receipt ranges when orders are held, completed out of order, cancelled, or invoiced separately. This helps businesses ensure invoice lines accurately reflect the receipts included, reducing confusion for customers and reporting teams.
Original PR description
Steps to reproduce: - In a PoS session, ring up orders 16, 17, 18, 19, 20 back to back. - Hold order 17 before finishing it, letting 18, 19 and 20 complete (and so get recorded) first, then confirm…
Steps to reproduce: - In a PoS session, ring up orders 16, 17, 18, 19, 20 back to back. - Hold order 17 before finishing it, letting 18, 19 and 20 complete (and so get recorded) first, then confirm order 17 last. - Cancel order 19 (or otherwise exclude it, e.g. invoice it individually). - Generate a consolidated invoice covering these orders. Issue: A consolidated invoice line grouping several PoS orders is named as a "first-last" receipt range (e.g. "18-20"). Grouping itself relies on `sequence_number`, a gapless counter assigned when the order is recorded in the database - the only field that reliably proves no order was skipped. The receipt reference shown to the customer is reserved earlier, client-side, the instant the ticket is opened, and does not move together with `sequence_number` whenever an order is held (or otherwise finishes) later than orders opened after it. The resulting line can then be named with a range that visually overlaps with, or omits, receipts that are actually reported on a different line, misrepresenting what the consolidated invoice covers. Root Cause: `sequence_number` (point_of_sale/models/pos_order.py) is only assigned once an order's row is created in the database, in recording order. The receipt reference (`pos_reference`/`name`) is assigned client-side the moment the ticket is opened (`setNextOrderRefs` in pos_store.js) and is unaffected by how long the order later takes to complete. `_split_pos_orders_in_lines` only checked `sequence_number` continuity to decide which orders share a line, while the line name (built from the first/last receipt reference, sorted) implicitly assumed the two would always move together. Fix: - l10n_my_edi_pos: `_split_pos_orders_in_lines` now also requires the receipt reference to be continuous - same device, and the number incrementing by one, via the new `pos.order._get_myinvois_reference_key()` - before merging two orders into the same line, on top of the existing `sequence_number` check. An order recorded out of ticket order now gets its own line instead of being merged into one with a misleading name. - l10n_my_edi: extracted the line-naming logic into an overridable `_get_consolidated_line_name`, which only compresses to a "first-last" range when the names are genuinely sequential, and lists every reference individually otherwise, as a safety net for any other flow relying on this base method. [task-6166533](https://www.odoo.com/odoo/my-tasks/6166533)
Users can now safely discard changes after reordering long multi-page line-item lists, such as quotation order lines. This prevents an error that could interrupt sales document editing when many lines are present.
Original PR description
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to…
**Steps to reproduce:** - Create a quotation - Add order lines until reaching 200 (duplicating helps), save and ensure that the pager appeared (1-200/201) - Drag one of the lines with the handle to reorder them - Discard all changes (X shaped button) You will have an evaluation error **Behavior:** When loading a list of records exceeding the limit, only parts of the records are saved in `_cache`. When triggering a reordering of said list, all records need to be loaded including the ones on other pages: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/static_list.js#L1139-L1149 `_getResIdsToLoad()` gets all Ids missing from the cache, these are then passed through `._createRecordDatapoint` and will then be stored in `_cache`. The issue is that the Datapoints are getting created with only `activeFields` as data, which in our case are `id` and `sequence` When discarding the changes `._checkValidity()`is called on each Datapoint: https://github.com/odoo/odoo/blob/d4eff7b14d37a9b59c95d304542a5a12629bc90b/addons/web/static/src/model/relational_model/record.js#L423-L429 And then `._isInvisible()` is called. This is where the issue happens, since only `sequence` and `id` are stored, when we try evaluate `combo_item_id`, which is the condition to see if sequence is invisible, `combo_item_id` is not found and we get an Evaluation Error. This commit prevents going into `._checkValidity()` by adding `this.isInEdition` to the check leading to it, requiring that the record is in 'edit' mode which is not the case for records created with `_createRecordDatapoint()` opw-6399024
French PDP invoice responses are now sent through a single response channel instead of both PDP and classic Peppol. This avoids duplicate messages in invoice discussions while keeping the response flow clearer for users.
Original PR description
When responding to an invoice received through PDP, 2 responses were actually sent: one through PDP and the other through the 'classic' Peppol. This was done to allow more reliability, in case one channel is down when trying to respond, but this mainly creates cluttah' in the chattah' (call me busta rhymes yo) task-6522652 Forward-Port-Of: odoo/odoo#285596
The editor now removes truly empty columns when users reduce or remove a column layout, preventing unwanted blank paragraphs from appearing. Meaningful content is still preserved, and the menu wording is clearer for users converting columns back to regular content.
Original PR description
#### Description of the issue this PR addresses: - When reducing the number of columns or removing a column layout, empty columns were previously unwrapped like any other column. - As a result, columns containing only placeholder paragraphs contributed empty paragraphs to the resulting content, even though they did not contain any meaningful user content. #### Desired behavior after PR is merged: - Fully empty columns are discarded when they are removed. - Non-empty columns continue to be merged as-is, preserving their content. - A single empty paragraph is still kept when all columns are empty to ensure the editor remains editable. - Rename `Remove columns` to `Remove column layout` and update its description to `Convert columns to regular content` to better reflect the operation. task-6296536 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283558 Forward-Port-Of: odoo/odoo#270220
Customer-facing invoice pages no longer show the salesperson's city or phone number. This makes invoice information consistent with sales orders and helps avoid exposing personal employee details to customers.
Original PR description
This change aligns the salesperson's information shown to customers on the invoice view with those shown on the sales order view. Now city and phone number are not shown and both views are consistent. This information can be personal information not supposed to be leaked to customers especially the salesperson's city in case of home office. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278497
This fix ensures Italian POS refunds navigate to the payment page for the refund order, not the product screen or the original order. This helps cashiers complete refund flows correctly when using an Italian fiscal printer.
Original PR description
**Issue**: 1. From versions 18.4 to 19.1 inclusive, the system redirects to the product screen; 2. From version 19.2 onward, the redirection targets the payment page of the original order instead of the refund order. **Expected behavior**: The system navigates to the payment page for the refund order. **Steps to reproduce**: - Set up an Italian fiscal printer; - Open a POS session and process an order; - Create a refund for the order. [Ticket link](https://www.odoo.com/odoo/project/49/tasks/6499079) opw-6499079 Forward-Port-Of: odoo/enterprise#129758
Fixes the DIN5008 invoice layout so addresses and information blocks line up correctly when documents are sent by post. This ensures German customer invoices generated for snailmail fit the expected postal layout without changing the normal invoice appearance.
Original PR description
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer…
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer invoice using the DIN5008 report layout. - Select Send by Post. - Enable Developer Mode and navigate to Settings → Technical → Email → Snailmail Letters. - Open the generated letter and send it. **Observed behavior:** The address blocks are incorrectly aligned when the DIN5008 report is rendered for snailmail. The information block and recipient address do not follow the expected vertical positioning. **Cause:** The DIN5008 layout previously applied vertical alignment rules to its table cells. These rules were removed while adapting the layout to the invoice table structure and its customizations, such as the position column and line numbering. While this alignment is no longer required for the regular DIN5008 invoice layout, the snailmail layout relies on it to correctly position the sender/invoice information and recipient address blocks. **Fix:** Add a `snailmail` class to the DIN5008 invoice section when `snailmail_layout` is present in the rendering context. Restore the required vertical alignment rules scoped to this class so they only affect snailmail reports, without changing the regular DIN5008 layout. **References** * **PR:** [#201225 – DIN5008 layout improvements](https://github.com/odoo/odoo/pull/201225) * **Ticket:** [6387869](https://www.odoo.com/odoo/project/49/tasks/6387869) opw-6387869 Forward-Port-Of: odoo/odoo#285891
The Polish bank account verification process now handles partner records that are missing a VAT number or bank account without crashing. This helps users verify groups of partners more reliably, even when some records still need more information.
Original PR description
When we check for multiple partners with some valid and some being incomplete (no vat or no bank account), a traceback is raised This was due to a bracket accessor, changed into a get in this commit. no-task Forward-Port-Of: odoo/odoo#285631
Weekly overtime in Timesheets is now calculated from the employee's actual scheduled total hours, including flexible schedules, instead of a full-time equivalent value. This makes the overtime shown in My Timesheets consistent with Planning and All Timesheets, reducing confusion for employees and managers.
Original PR description
# How to reproduce - Set the current employee's schedule to one with : - Schedule Type : Flexible - Total : a different amount than "Full Time Equivalent" - Go to My Timesheets - Add a new line with…
# How to reproduce
- Set the current employee's schedule to one with :
- Schedule Type : Flexible
- Total : a different amount than "Full Time Equivalent"
- Go to My Timesheets
- Add a new line with some Time Spent > 0
- Hover the bottom right cell of the grid (this is the total overtime for the week)
# The issue
The computation of the overtime for the week is based on "Full Time Equivalent" instead of "Total". This is inconsistent with the Planning app and the All Timesheets view.
# Cause
This [PR] introduced the usage of `full_time_required_hours` to compute the total overtime. This field was used because `hours_per_week` ("Total") was thought to be computed using `resource.calendar.attendance`. However, that is not the case when the schedule is flexible : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/resource/models/resource_calendar.py#L220 https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/resource/models/resource_calendar.py#L163-L166
[PR]: https://github.com/odoo/enterprise/pull/81057
opw-6303520Mobile invoice line cards now display the line description when no product is selected. This prevents blank cards and makes invoices easier to review and edit on mobile devices.
Original PR description
Invoice lines can be created without a product. However, the mobile kanban view does not handle such lines properly and displays an empty card without a name or image. This commit adapts mobile kanban view to show invoice line's name when `product_id` is not set. Before | After -- | -- <img width="469" height="277" alt="image" src="https://github.com/user-attachments/assets/3b367581-b73d-4b12-a487-1a54c3b88470" /> | <img width="406" height="300" alt="image" src="https://github.com/user-attachments/assets/107d7294-90e8-49c6-826a-9be75c6b799f" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285608 Forward-Port-Of: odoo/odoo#284755
The Guatemala electronic invoicing setup now reflects the new tax treatment for regular gasoline containing 10% alcohol. New customer accounting templates will tax only 90% of the gallons, matching the government exemption for the alcohol portion from August 22.
Original PR description
Starting August 22nd Regular Gasoline is changing to a version that contains 10% alcohol. Because of this, the government is only taxing 90% of the gallons since the 10% alcohol portion is exempt. This will update COA for new customers, any current dbs who need to use the new formula can manually update theirs to include the * 0.9 portion. task-6483303 Forward-Port-Of: odoo/enterprise#129483 Forward-Port-Of: odoo/enterprise#129412