Monday, March 9, 2026
16 changes · saas-19.2
Enhancements to existing features
This update restricts the ‘Working Schedule Change’ wizard to only Belgian companies, improving the accuracy of payroll calculations. It also removes a redundant field and enhances the user interface with improved spacing, resulting in a cleaner and more intuitive experience for users managing Belgian employee schedules.
Original PR description
- Show the “Working Schedule Change” wizard only for employees belonging to Belgian companies. - Remove the “Post Change Contract Creation” field from the working schedule change wizard. - Add extra right padding to the warning alert in the time-off section for improved UI spacing. task-5367812 Forward-Port-Of: odoo/enterprise#109378 Forward-Port-Of: odoo/enterprise#101013
Resolved issues and error corrections
This update resolves an issue where AVCO valuations were incorrectly defaulting to a product's initial price when stock move dates were earlier than the product's creation date. The fix ensures that actual stock movements always take precedence in AVCO valuation calculations, providing more accurate inventory reporting.
Original PR description
**Issue**: If the date of some stock moves is anterior to the creation date of the product in the database, the associated valuation is replaced by the initial standard price of the product. **Steps…
**Issue**: If the date of some stock moves is anterior to the creation date of the product in the database, the associated valuation is replaced by the initial standard price of the product. **Steps to reproduce**: - Create a new product with a standard price of 0 and AVCO cost method - Create a PO for that product with a unit cost of 1,000,000, confirm it and validate the receipt - Go to Accounting > Review > Inventory > Inventory Valuation -> Observe that the valuation correctly takes the purchase into account - Go back to the receipt, unlock it and change the effective date to one week in the past - Go back to Inventory Valuation -> Observe that the valuation no longer takes the purchase into account - Change the valuation date to yesterday -> Observe that the valuation takes it into account again **Cause**: When a product is created, a `product.value` record is instantiated with today’s date: https://github.com/odoo/odoo/blob/bbaf38aa99143be4679cf951c5c0f1a1c8ecf716/addons/stock_account/models/product.py#L174 https://github.com/odoo/odoo/blob/bbaf38aa99143be4679cf951c5c0f1a1c8ecf716/addons/stock_account/models/product.py#L202 In the AVCO computation, a manually set product value (`product.value`) takes precedence over move values when it is anterior, either here: https://github.com/odoo/odoo/blob/bbaf38aa99143be4679cf951c5c0f1a1c8ecf716/addons/stock_account/models/product.py#L309-L312 or here: https://github.com/odoo/odoo/blob/bbaf38aa99143be4679cf951c5c0f1a1c8ecf716/addons/stock_account/models/product.py#L334-L338 Since the stock move date is set one week in the past, the initial product value (0.0) takes precedence over the move valuation. When the valuation date is moved forward to yesterday, this initial product value is ignored and the move value is correctly applied again. **Solution**: Setting the initial `product.value` date to the product creation date is arbitrary, as it makes inventory valuation depend on when the product was encoded rather than on real stock history. Instead, set the date of the first `product.value` to the earliest possible epoch, ensuring that any real stock move always takes precedence in AVCO valuation. opw-5882080 Forward-Port-Of: odoo/odoo#247407
This update fixes a problem where self-order prices weren't accurately calculated when taxes and fiscal position mappings were involved. The change ensures prices are correctly recomputed using accounting methods, leading to more accurate order totals and financial reporting. This improves the reliability of self-order transactions.
Original PR description
Before this commit, the price of order lines from self was recomputed in the backend but for orders with price included taxes and a fiscal position mapping, the recomputation was not correct. This commit fixes the issue by recomputing the prices using compute_all method from accounting on taxes after fiscal position. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252487 Forward-Port-Of: odoo/odoo#251945
This update fixes an issue where miscellaneous entries within overdue reports weren't being included in the printed reports sent to partners. Now, when users mark a miscellaneous entry for inclusion in the follow-up report, the full entry details (including amount and description) will appear in the printed report. This ensures partners receive complete information about overdue items.
Original PR description
…port Currently, even if users mark a miscellaneous entry to be included in the follow-up report, only its amount is counted in the total overdue; the entry itself is excluded from the printed report sent to the partner. Steps to reproduce: - Have a journal item with partner, receivable account and due date in the past - Open followup report for the partner, uncheck 'No followup' for the aml - Go back to the partner, in the followup section, hit 'Send' and send the manual followup (or wait/trigger the scheduled action) Issue: Printed followup report is missing any info on the misc entry opw-5405657 Forward-Port-Of: odoo/enterprise#109581 Forward-Port-Of: odoo/enterprise#106725
This update fixes an issue where sick leave days weren't accurately counted across months and the basic salary was incorrectly calculated when there were no work entries on payslips. The changes ensure accurate tracking of sick leave and prevent incorrect salary calculations, improving payroll accuracy.
Original PR description
### Issue: - Sick leaves were calculated using the leave record dates, so leaves that started in one month and continued into another month were not counted correctly. - The Basic salary rule was applied even when there were no `WORK100` work entries on the payslip. ### Fix: - Updated the leave filtering logic to consider leaves whose `request_date_from` or `request_date_to` overlaps with the payslip period year, instead of relying solely on the leave start date. - Adjusted the Basic salary computation to execute only when `WORK100` exists in `worked_days_line_ids`, preventing calculation when no effective worked entries are present. ### Impact: - Ensures sick leave days are correctly accounted for in the relevant payslip period, even when the leave spans across months. - Prevents incorrect Basic salary computation on payslips with no `WORK100` work entries, resulting in accurate payroll calculations. --- task-5462380 Forward-Port-Of: odoo/enterprise#104401
This update resolves an issue where the Documents app would crash after deleting a payslip run. The fix ensures that related documents are also removed when a payslip run is deleted, preventing data inconsistencies and improving application stability. This improves the user experience and avoids potential errors.
Original PR description
### Issue: When deleting a payslip run, the documents from the payslips of the run are not deleted. This results in a traceboack when opening the document app. ### Steps to reproduce: - Have a…
### Issue: When deleting a payslip run, the documents from the payslips of the run are not deleted. This results in a traceboack when opening the document app. ### Steps to reproduce: - Have a payslip run with payslips - Go to a payslip, validate and generate the document - Then cancel and reset to draft - Reset the Payslip Run to draft - Delete it - Open the Documents app ### Cause: The payslips are linked to the run with a `ondelete='cascade'` relation. https://github.com/odoo/enterprise/blob/03b2a7dae0e5c5ad3142ec2da8f3de5c9b1957f4/hr_payroll/models/hr_payslip.py#L110-L113 This means that deleting the run also deletes its payslips on a database level, bypassing the ORM. As the document is not directly linked by a relational field but instead by `res_model` and `res_id`, these fields are not updated and therefore are still pointing to a record that is no longer in DB. ### Solution: Extend the `unlink()` method in `hr.payslip.run` and unlink the documents there. opw-5501061 Forward-Port-Of: odoo/enterprise#109510 Forward-Port-Of: odoo/enterprise#105969
This update resolves an issue causing the floor screen to repeatedly re-render, impacting performance. The problem stemmed from a bug where the system was incorrectly updating appointment start times, triggering an infinite loop of re-renders. This fix ensures the floor screen displays appointments accurately and efficiently.
Original PR description
Infinite re-rendering in floor_screen.
Root cause: `getFirstAppointment` mutates reactive model state
(appointment.start) during rendering:
```
appointments.map((appointment) => {
if (appointment.start < startOfToday) {
appointment.start = startOfToday; // <= mutates reactive state!
}
});
```
And `startOfToday` is set by
`DateTime.now().set({ hours: 0, minutes: 0, seconds: 0 })`
Which doesn't zero milliseconds, so each render creates a new
`startOfToday` with a later millisecond value.
The comparison `appointment.start < startOfToday` keeps being true
triggers another write => another re-render => infinite loop.
Forward-Port-Of: odoo/enterprise#109915This update fixes an issue where confirming multiple quotes could result in a negative loyalty point balance. The system now checks for sufficient points before calculating changes, preventing this error and ensuring accurate loyalty point tracking. This improves data integrity and user confidence in the loyalty program.
Original PR description
### Steps to reproduce: - Download Sales app - Then, tick Configuration -> Settings -> Promotions, Loyalty & Gift Card - From the sales app top bar, Products -> Discount and Loyalty -> New - Rule =…
### Steps to reproduce: - Download Sales app - Then, tick Configuration -> Settings -> Promotions, Loyalty & Gift Card - From the sales app top bar, Products -> Discount and Loyalty -> New - Rule = Default & Reward = any discount for 100 points - From the 'Loyalty Cards' smart button, create a new loyalty card for a test customer and set its balance to 100 points - Create 2 "Quotations" with product below 50$ and claim reward. Don't confirm the quotes - Select the previous quotes and click "Confirm Orders" smart button - Verify that the created loyalty card has a balance of -100 ### Cause of Issue: When multiple quotations are confirmed in bulk, the system processes their eligibility for rewards one by one. https://github.com/odoo/odoo/blob/3656171994450d11151565efdb4b9dd0468cefa8/addons/sale_loyalty/models/sale_order.py#L150-L153 Hence, each quote will pass the check because the check since they individually require a number of points less than or equal the current loyalty card balance. Then https://github.com/odoo/odoo/blob/3656171994450d11151565efdb4b9dd0468cefa8/addons/sale_loyalty/models/sale_order.py#L166-L167 The change is caluclated collectively, which lowers the balance to a negative amount. ### Fix: Since the `change` is calculated before any change is done in the database, it is suitable to raise an error to the user at this point if the change is going to turn the balance negative. opw-5929187
This update resolves an issue where users without project access rights would encounter errors when modifying work orders linked to private projects. The fix ensures that workers can successfully update these work orders, improving workflow efficiency and preventing disruptions.
Original PR description
When working on a MO that is linked to a project in private, it will trigger a access error if the worker is does not have project access right Steps to reproduce: ------------------- * Install Project, MRP, Accouting * Create a private project * Create a MO and link it to this project * confirm this MO with a user that has no project access right Observation: ------------- When modifying the MO, we will pass through the write that has been overwritten: https://github.com/odoo/enterprise/blob/b332af45a46b2295797a5096f68b7953554a495b/project_mrp_workorder_account/models/mrp_production.py#L6-L10 we will call _get_analytic_distribution on project.project and since _get_analytic_distribution will [read fields from self](https://github.com/odoo/odoo/blob/436921c24a531eba6bf57ffe3f7c3b4978139d83/addons/analytic/models/analytic_line.py#L59-L64) we need project.project read rights. opw-4919576 Forward-Port-Of: odoo/enterprise#108148
This update fixes an issue where the system incorrectly treated re-deliveries as returns, resulting in a single shipping label being generated. Now, when returning multiple packages, the system accurately identifies and processes each package as a separate return, ensuring proper delivery label creation and improving the efficiency of the return process.
Original PR description
Issue ----- When doing delivery -> return -> re-delivery, only one label is received even when there are mutliple packages to be "re-delivered". Steps to reproduce ----- - Create a UPS delivery -…
Issue ----- When doing delivery -> return -> re-delivery, only one label is received even when there are mutliple packages to be "re-delivered". Steps to reproduce ----- - Create a UPS delivery - Multiple packages - Validate transfer - Return - Validate IN - Return again - Add the UPS under the "additional info" tab - Ensure still multiple packages - Validate OUT Cause ----- When preparing the shipping data, we go through https://github.com/odoo/enterprise/blob/913e55abc4a9aa58509aa2a60d378fb552de554d/delivery_ups_rest/models/delivery_ups.py#L120-L121 which leads us to do https://github.com/odoo/odoo/blob/89733b0e4d1e9a57dd25f552db4e6330a6b14cdf/addons/stock_delivery/models/delivery_carrier.py#L142-L155 so we end up with a single package to send to the delivery service. The reason `is_return_picking` is true is because the compute method only checks for an existing move with an `origin_returned_move_id`. https://github.com/odoo/odoo/blob/89733b0e4d1e9a57dd25f552db4e6330a6b14cdf/addons/stock_delivery/models/stock_picking.py#L53-L58 From a delivery flow perspective, it doesn't make much sense to consider outgoing shipments as returns. ----- Ticket: opw-5866100 Forward-Port-Of: odoo/odoo#251789 Forward-Port-Of: odoo/odoo#246946
This update resolves a bug where hidden popups were causing extra dropzones during website editing. The fix ensures popup visibility is consistently tracked, preventing these unexpected dropzones and improving the overall drag-and-drop experience. This improves usability for users adding content to the website.
Original PR description
## Description There was a desync issue with popup states between normal mode and edit mode. That caused: - Hidden popups contributed extra dropzones during drag-and-drop - Hidden popups lost…
## Description There was a desync issue with popup states between normal mode and edit mode. That caused: - Hidden popups contributed extra dropzones during drag-and-drop - Hidden popups lost `d-none` class after dropping unrelated snippets ## How to reproduce ### Bug 1: extra dropzones from hidden popup desync 1. Enter website edit mode. 2. Drop popup in the page 3. Drag another snippet as you were adding it to the page 4. An additional dropzone appears below the invisible popup snippet ### Bug 2: hidden popup loses `d-none` class 1. Enter edit mode. 2. Drop a popup. 3. Close it so `.s_popup` gets `d-none`. 4. Drop any other snippet on the page arbitrarily. 5. Popup loses `d-none` class. ## Expected behavior after fix - Popup hidden/shown state remains stable across editor refreshes and snippet drops. - Drag-and-drop no longer creates extra dropzones from hidden popups. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251517 Forward-Port-Of: odoo/odoo#250625
This update fixes errors preventing users from searching for job titles within the employee module. Previously, access restrictions on a related database table caused issues for certain user groups. The changes remove these restrictions, allowing all users to perform job title searches and address a separate issue related to resume searches.
Original PR description
[FIX] hr: fix job title search access error Bug reproduction: Select marc demo -> employee app -> try to search something for job title -> Access error appears for no hr ones Bug cause: Only…
[FIX] hr: fix job title search access error Bug reproduction: Select marc demo -> employee app -> try to search something for job title -> Access error appears for no hr ones Bug cause: Only users/managers can access to hr_version model and since marc demo has not, it receives this error. Bug solution: I put store=True and compute_sudo for job_title and by that way everyone can search for job_title without access. In the task [MOHF] showed another traceback about job title search. I fixed that in this commit as well. Bug 2 reproduction: employee app -> try to search something for resume -> it will give error (there is no version_ids) Bug 2 cause: There is no version_ids in the employee.public model, in the search version_ids.job_title is used but job_title can be used directly. Bug 2 solution: I used job_title in the search instead of using version_ids.job_title. task - 6000488 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#251949
This update ensures that One Stop Shop (OSS) invoices for intra-EU B2C sales in Italy are correctly formatted for the Italian Revenue Agency (Agenzia delle Entrate). Previously, the system rejected these invoices due to a specific formatting requirement. This change adds the necessary lines and summaries to ensure compliance with FatturaPA standards.
Original PR description
This commit aligns the Italian e-invoicing (FatturaPA) generation for One Stop Shop (OSS) transactions with the requirements of the Italian Revenue Agency ( Agenzia delle Entrate). Current behavior:…
This commit aligns the Italian e-invoicing (FatturaPA) generation for One Stop Shop (OSS) transactions with the requirements of the Italian Revenue Agency ( Agenzia delle Entrate). Current behavior: Invoices for intra-EU B2C sales (OSS) are generated with a single line containing the foreign VAT rate. This is rejected or considered non-compliant by the SDI because foreign VAT cannot be typically exposed in the standard way for Italian electronic invoices. New behavior: The XML generation logic has been updated to follow the specific codification required for OSS operations: 1. Invoice Lines (`DettaglioLinee`): - The product line is reported with 0% VAT and Nature 'N7' (VAT paid in another EU member state). - A new, separate line is injected to represent the VAT amount, classified with Nature 'N2.2' (Non-taxable/Other). 2. Tax Summary (`DatiRiepilogo`): - The original foreign tax lines are excluded from the summary. - Synthetic summary lines are added for the 'N7' (Taxable Base) and 'N2.2' (VAT Amount) categories. Implementation details: - Added `_l10n_it_is_oss_tax` helper to identify OSS taxes. - Modified `_l10n_it_edi_get_line_values` to split OSS lines. - Modified `_l10n_it_edi_get_tax_values` to adjust the tax summary. task-4711509 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#252368 Forward-Port-Of: odoo/odoo#243740
This update fixes an issue where error messages from the IAP (Internet Access Point) were not being displayed correctly when the French reports module was adapted for the new ASPone API. The fix ensures that errors are now properly presented, improving the user experience and troubleshooting capabilities for French-language reporting.
Original PR description
When adapting the code to ASPone new rest api, errors were no more well handled, this fix aims to correctly display the errors we get from IAP task-5955980
This update fixes an issue where formatting was lost when restoring content from the full composer to the basic composer. Now, users are prompted to choose between restoring formatting in the full composer or using the simpler composer without formatting, providing a more flexible and user-friendly experience.
Original PR description
Before this commit, when using the full composer and accidentally closing it with some content, the composer content was recovered on the basic composer and formatting was lost. This happens because…
Before this commit, when using the full composer and accidentally closing it with some content, the composer content was recovered on the basic composer and formatting was lost. This happens because restore of content only works in the basic composer, and basic composer does not support rich HTML like the full composer. This commit adds a new UX/UI to restore formatting when accidentally leaving the full composer: When some content has been restored from full composer, opening the chatter composer momentarily disables everything but the full composer button, in addition to show a popover suggesting the user to decide to either continue with Full Composer and restore formatting, or restore content in the small composer without the formatting. Most of the time people want to restore formatting from the full composer, but at the same time the full composer can be a frustrating experience that may incite to just continue with the more reliable small composer. This new popover support both use-cases. Task-5910961 <img width="1219" height="175" alt="Screenshot 2026-02-26 at 17 28 06" src="https://github.com/user-attachments/assets/13d8e1ca-4186-445e-8422-a14c31f8570f" /> Forward-Port-Of: odoo/odoo#252318 Forward-Port-Of: odoo/odoo#247245
This update resolves an issue where the delivery partner wasn't correctly set on sales orders when using MTSO pull rules for stock movements. The fix ensures that the correct contact information is passed through the delivery process, particularly in multi-step routes and subcontractor scenarios, improving order fulfillment accuracy.
Original PR description
*:{sale_,}stock, mrp_subcontracting ### Sate of the art: Since the refactoring of 19.0 removing the procurement groups and introducing stock references 2713876dbc70d3984e584a9037a2206dcda4e84a, the…
*:{sale_,}stock, mrp_subcontracting
### Sate of the art:
Since the refactoring of 19.0 removing the procurement groups and introducing stock references 2713876dbc70d3984e584a9037a2206dcda4e84a, the `partner_id` is not propagated in pull flows. While the following fix 3bd213c24536fa6d40a7d7a44d4c553947f82c84 addresses some of these propagation issues, it only propagates the partner in case of a move chain for mto moves generated by mto rule. The current PR addresses some of the mtso use cases such as the mtso multi-step pull delivery and the mtso resupply subcontractor on order.
## 1. mtso multi-step pull delivery
### Steps to reproduce:
- In the settings enable: Multi-Step Routes
- Inventory > Configuration > Warehouse Management > Warehouses
- Put your warehouse in deliveries in 3 steps
- Inventory > Configuration > Warehouse Management > Routes
- Modify you 3 steps Delivery (pick, pack, ship) route:
- Change the rules to be in pull Stock -> Pack -> Out -> Cust
- Change the rules: Pack -> Out -> Cust to be in mtso and not mto
- Create and confirm a sale order for a partner A
- The pick, pack and ship should be created
#### > The delivery partner (contact) is only set on the ship
### Cause of the issue:
As the route has been modified to be handled by pull rules, it is generated from end to start by subsequent move confirmations. However, as, the pull rules Pack -> Out -> Cust are in mtso, the associated moves will be created with a `make_to_stock` `procure_method`.
https://github.com/odoo/odoo/blob/5143840911e1f05be3f5f5c7fa786f05e4966312/addons/stock/models/stock_rule.py#L304-L305
Hence, when a procurement is created because of the `mts_else_mto` rule in the `_action_confirm`, the procurement will not set any `move_dest_ids` nor `partner_id`:
https://github.com/odoo/odoo/blob/5143840911e1f05be3f5f5c7fa786f05e4966312/addons/stock/models/stock_move.py#L1549-L1552
https://github.com/odoo/odoo/blob/5143840911e1f05be3f5f5c7fa786f05e4966312/addons/stock/models/stock_move.py#L1688-L1690
https://github.com/odoo/odoo/blob/5143840911e1f05be3f5f5c7fa786f05e4966312/addons/stock/models/stock_move.py#L1699
In other words, the pick and pack moves will not be part of a move chain (with `move_dest_ids`), and the `partner_id` is not propagated.
While the move chain `move_dest_ids` propagation is indeed only intended for mto moves (created by mto rules) since the mtso refactoring: a72382063ee662010729d983fbf6fb6305b8adf2 the `partner_id` should be propagated for pull rule in `mts_else_mto` to avoid losing the delivery partner that used to be propagated by procurement groups which were removed in 19.0 by 2713876dbc70d3984e584a9037a2206dcda4e84a Since the associated fix: 3bd213c24536fa6d40a7d7a44d4c553947f82c84 the `partner_id` can now be propagated via the `procurement_values` but is currently only propagated in case of mto moves:
https://github.com/odoo/odoo/blob/5143840911e1f05be3f5f5c7fa786f05e4966312/addons/stock/models/stock_move.py#L1699
## 2. Resupply subcontractor on order
### Steps to reproduce:
- In the settings enable: Multi-Step Routes, Subcontracting
- Inventory > Configuration > Warehouse Management > Routes
- Set the rule of the "Resupply Subcontractor on order" route to mtso
- Create a subcontracting bom for a finished product (FP) with a storable
component (comp) for subcontractor: Bob
- Create and confirm a PO for 1 unit of FP with Bob as vendor
#### > Bob is not set as delivery contact on the resupply delivery for comp
### Cause of the issue:
When the rule is in MTO, so is procure method of the move raw for comp in the subcontracted MO. As such, the procurement generated at its confirmation will provide a `move_dest_ids`:
https://github.com/odoo/odoo/blob/c2cb705c078015bff0bc673e83a205d7657918e0/addons/stock/models/stock_move.py#L1688-L1698
which allows to propagate the subcontractor once the procurement is run because of these lines:
https://github.com/odoo/odoo/blob/c2cb705c078015bff0bc673e83a205d7657918e0/addons/stock/models/stock_rule.py#L307
https://github.com/odoo/odoo/blob/37c787ed7ca129bbccd02a073b1e03729b22c2b8/addons/mrp_subcontracting/models/stock_rule.py#L15-L20
In the present case, since the rule is in mtso, the `procure_method` of the raw move will be mts and the `move_dest_ids` will not be propagated. So that `partner_id` is never set as the subcontractor.
### Note about the fix:
When the rule `procure_method` is `mts_else_mto`, at the time we enter override of the `_get_stock_move_values` of `mrp_subcontracting`:
https://github.com/odoo/odoo/blob/37c787ed7ca129bbccd02a073b1e03729b22c2b8/addons/mrp_subcontracting/models/stock_rule.py#L15-L20
the only reference to the subcontractor is the one contained in the `production_ids` of the `reference_ids` of the procurement values which does not look like a reliable link as:
- Multiple `reference_ids` could be set in the values of the procurement
- Multiple `productions_ids` could be linked to the `reference_ids`
- Without the link to the subcontracted move raw nothing indicates that we trigger the creation of a move destined for a subcontractor
By contrast, the current proposition rely on the move that should have been set as `move_dest_ids`in the mto flow and mitigate these uncertainties.
opw-5402407
opw-5883477
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#251564
Forward-Port-Of: odoo/odoo#250307