Tuesday, July 14, 2026
25 changes · saas-19.4
Enhancements to existing features
Mexican payroll reporting is updated to match CFDI version 1.2e requirements. The change strengthens validation of taxable and exempt payroll amounts and subsidy limits, helping reduce rejected payroll XML submissions and compliance issues.
Original PR description
**. Perceptions – ImporteGravado / ImporteExento (XML Nodes)** For each Perception node, validate that: If ImporteExento = 0, then ImporteGravado > 0. If ImporteGravado = 0, then ImporteExento > 0. Both values cannot be 0 at the same time. These validations must be applied per Perception node, not at an aggregated level. **. TipoPercepcion = "038" (Other Salary Income) (XML Nodes)** When TipoPercepcion = "038": ImporteExento must always be 0. The amount must be recorded only in ImporteGravado. **. SubsidioCausado (XML Nodes)** Update the validation logic for the SubsidioCausado attribute based on NumDiasPagados: If NumDiasPagados ≤ 31, SubsidioCausado ≤ 628.00 If NumDiasPagados > 31, SubsidioCausado ≤ NumDiasPagados × 0.206 task-5412728 Forward-Port-Of: odoo/enterprise#121304
This update improves how manufacturing work orders handle continuous production, making the process cleaner and more reliable for operational teams. It helps reduce friction in production tracking and supports smoother shop floor execution.
This update brings the Owl library, a key component of our website's image zooming functionality, to version 2.8.4. This includes a fix to prevent lost image renders and support for running the library with Node.js, enhancing our website's performance and flexibility.
Original PR description
- [FIX] runtime: don't lose coalesced renders - [IMP] loadable with nodejs See https://github.com/odoo/owl/commits/owl-2.x/ for more details 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#275568
This update enhances the error message displayed when issues arise with leave validity calculations. Previously, troubleshooting required manual investigation, but now customers and support teams can quickly identify the root cause of leave allocation problems. This improves user experience and reduces support time.
Original PR description
The current message is pretty useless as of now when a lot of leaves are being written to, notably when creating a public holiday, which sets the state of all the leaves overlapping the public holiday's day to be reevaluated, and if an error occurs, you have to go through every employee's leave allocation and leaves taken to hopefully find one who might have to many days taken/not enough allocated. This extra information will be a huge QOL improvement, for the customer who will be able to troubleshoot his issue himself more easily, but also for our support team as the only way to debug those kind of issues now is to put a breakpoint there and see what employee has an issue. opw-4411999 Forward-Port-Of: odoo/odoo#272412 Forward-Port-Of: odoo/odoo#200376
Resolved issues and error corrections
This fix prevents errors when calculating CP200 seniority for multiple employees at once in Belgian payroll. It helps payroll batches run reliably and avoids interruptions caused by multi-employee processing.
Original PR description
The CP200 loop in _compute_l10n_be_computed_seniority read from `self` instead of the `version` loop variable, raising "Expected singleton" whenever the batch spanned more than one employee. opw-6349286
Canadian EFT export files now include a nonzero unique trace number for each payment, using the payment's own ID. This helps ensure CPA-005 payment files meet banking standards and avoids rejection caused by zero-filled trace numbers.
Original PR description
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as…
Issue: The Item Trace Number according to CPA-005 standard should be a nonzero sequence that serves as unique reference ID for payments. Currently, Odoo sets the Item Trace Number of all payments as a zero-filled sequence According to CPA-005 standards on the Item Trace Number: "The data elements (b), (c) and (d) each must be greater than zero or the TRANSACTION WILL BE REJECTED" (page 36). https://www.payments.ca/sites/default/files/standard005eng.pdf Steps to reproduce: 1. Install the module l10n_ca_payment_cpa005 2. Go into "CA Company" 3. In the configuration for "CA Company", add something to the fields "Short Name used in Canadian EFT" and "Company ID" i.e. "CCC" 4. Set all the fields in the "Canadian EFT/CPA Configuration" section of the bank journal 5. Set the bank record on the bank journal. Set the field "Financial Institution ID Number" field of the "Account Number" record of the bank journal to any numerical sequence 6. Create a bank account on "Azure Interior" and make sure to check the field to trust the bank account that you created (otherwise there will be an error) 7. Create two payments with the vendor of "Azure Interior" using the payment method of "Canadian EFT" 8. Create a batch payment for both payments created 9. Validate the batch payment and the export file should show up in the chatter 10. Note that in the export file, the Item Trace Number for each payment is set to be all zeros, whereas it should be a nonzero identification sequence Solution: Set the Item Trace Number to be the payment's id opw-6323432 Forward-Port-Of: odoo/enterprise#124016 Forward-Port-Of: odoo/enterprise#123633
This fix restores support for portal users to archive or unarchive documents when the action is performed through trusted system-controlled flows. It also prevents unnecessary errors when no documents are involved, improving reliability for document-related processes.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows did rely on it and we were lacking a way of supporting it. Task-6205627 Forward-Port-Of: odoo/enterprise#123015
The Belgian salary package now calculates the maximum mobility budget using the legally correct pay basis, excluding holiday allowance and handling 13th month rules more accurately. It also includes recent commissions, helping employers offer mobility budgets that better match Belgian compliance requirements.
Original PR description
https://lebudgetmobilite.be/fr/6-quel-est-le-montant-du-budget-mobilite#remunerationtotalebrute Simple and double holiday allowance should not be not accounted in the total brut remuneration for the cap of 20% for the mobility budget. 13th month should not be included if it is paid in warrants. This commit fixes the max mobility budget amount computation by multipling the wage by 12.08 instead of 13, as we remove the simple holiday allowance. Ratio = 12 months + 13th month - Simple holiday allowance (0.92 month) Also, Commissions should included: Sum the commissions on payslips of the last 12 months for this employee. MB_Budget = monthly_wage * ratio / 5 + commissions Task-5948733 Forward-Port-Of: odoo/enterprise#109845
The barcode app now fills in the stock owner automatically when scanning eligible products for delivery orders, even when the product is not lot-tracked. This prevents Odoo from creating or updating the wrong stock record and helps ensure consigned inventory is consumed from the correct existing stock.
Original PR description
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations >…
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations > Delivery Orders > New - Scan your product and validate #### > The owner was not set on the stock move line so that a new quant was created and updated in stock rather than using the available unit. ### Cause of the issue: The mechanism of prefilling an owner or a package in the barcode app is currently gate-kept behind the existence of a lot name: https://github.com/odoo/enterprise/blob/0be4f71de3420fb9b72fd4e70d48c6cbbbc0ecb4/stock_barcode/static/src/models/barcode_model.js#L1382-L1407 However, the option also make sense for none tracked products. ### Note: Performing the flow form the backend and adding quantity will generate the move line by setting the owner if possible since the quantity of a move is set via the back end, move lines are generated by looking at the existing quant data's: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2364 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2328-L2330 Setting the same owner on the new move line as on the quant we are going to reserve: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2337 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L1715 Additional subtelties appearing when prefilling for non tracked product: 1. Currently the available quantity is not taken into account to determine if the the value provided to the prefilled is actually relevant, in particular if there is a quant with an available quantity of 0, it will be used as a valid value to prefill and it will parasit the prefill that could be done by other quants. 2. The location source used to determine the quants taken into account is not set on the first scan since the scan is performed without any existing line: https://github.com/odoo/enterprise/blob/4f0d25f9fe4ca8ff1b0ecd7900899a2a246ba888/stock_barcode/static/src/models/barcode_model.js#L1387 > This was not problematic with respect to tracked product since the product needs to be scanned prior to the lot, hence there is always a current line when the the lot is scanned. opw-6050657 Forward-Port-Of: odoo/enterprise#124017 Forward-Port-Of: odoo/enterprise#115021
Fixes invoice status handling for Field Service sales orders that include zero-priced lines. Existing free items on a quotation can now still be invoiced normally, while free materials added during field work are treated correctly so orders can reach fully invoiced status.
Original PR description
## [FIX] industry_fsm_sale: fix invoice status for zero price lines ### Issue: Without Anglo-Saxon accounting, the system incorrectly sets the invoice status of all zero price sales order lines…
## [FIX] industry_fsm_sale: fix invoice status for zero price lines
### Issue:
Without Anglo-Saxon accounting, the system incorrectly sets the invoice status of all zero price sales order lines linked to an FSM task to 'no'
This includes pre-existing lines that were already present on the quotation before confirmation. If a zero price line is pre-existing, it should follow the standard flow and be marked as 'to invoice'
Only lines added as materials from the field service task at a zero price should be considered included in the price and marked as 'no'
### Cause:
In `SaleOrderLine._compute_invoice_status`, the system forced `invoice_status = 'no'` for all zero price lines when Anglo-Saxon accounting was disabled
It failed to check if the lines were actually materials added via the FSM task or original quotation lines
### Fix:
A new `material_sale_lines` compute field is added to `project.task` to distinctly isolate and track lines added specifically as materials during the task execution
In `SaleOrderLine._compute_invoice_status`, the logic is updated to ensure that only zero price lines identified as FSM materials are set to 'no' when Anglo-Saxon accounting is disabled
Other pre-existing zero price lines properly remain as 'to invoice'
### Steps to reproduce:
- Install `industry_fsm_sale`
- In Settings > Users & Companies > Companies > Any company, add the field Anglo-Saxon using Studio (In 19.0+)
- Disable Anglo-Saxon on the current company
- Create a product Service (Fixed Price, that create a task in a Field Service Project)
- Create and confirm a Sale Order with the Service and one product with unit price 0
Before the fix, the pre-existing SO line with price 0 is
incorrectly considered as not to invoice ('no')
opw-6169802
------------------------------
## [FIX] industry_fsm_sale: sync sale order invoice status
### Issue:
When a sale order contains FSM material lines with a price of zero and Anglo-Saxon accounting is disabled, the overall sale order invoice status remains stuck on 'to invoice' even after all other invoiceable lines are fully invoiced
### Cause:
The standard `SaleOrder._compute_invoice_status` does not handle FSM business rules regarding zero price material lines that are marked as `invoice_status = 'no'`
Because these lines are never technically invoiced, the global order status fails to transition to 'invoiced'
### Fix:
Override `SaleOrder._compute_invoice_status` to recompute the status of confirmed orders linked to FSM tasks
We use the task's `material_sale_lines` to filter out material components
If all lines on the order are either 'invoiced' or are zero price FSM material lines with Anglo-Saxon disabled, the global sale order status is forced to 'invoiced'
### Steps to reproduce:
- Install `industry_fsm_sale`
- In Settings > Users & Companies > Companies > Any company, add the field Anglo-Saxon using Studio (In 19.0+)
- Disable Anglo-Saxon on the current company
- Create a product Service (Fixed Price, that create a task in a Field Service Project)
- Create and confirm a Sale Order with the Service and one product with unit price 0
- Add a Product from the Task (Use a price 0 product, or set the unit price to 0 on the SO)
- Create the invoice for the Sale Order
Before the fix, the Service and Pre-existing product are invoiced, but in the Other Info Tab of the SO, the status stays on 'To Invoice' instead of 'Fully Invoiced'
opw-6169802
Forward-Port-Of: odoo/enterprise#123151
Forward-Port-Of: odoo/enterprise#119238Payslip creation now includes employees assigned to Belgian branch companies when payroll is managed from the parent company. This prevents missing employee records and helps payroll teams process branch employees consistently.
Original PR description
Bug: employees registered on branch companies don't appear in the
employee_id field when creating a payslip from the parent company.
Reason: the domain used ('company_id', '=', company_id) which only
matches the exact company, not its children.
Solution: replaced '=' with 'child_of' to include all descendant
companies in the hierarchy.
task - 6299634
Forward-Port-Of: odoo/enterprise#122381
Forward-Port-Of: odoo/enterprise#120974Users with the Invoicing & Banks accounting access level can now open the Accounting app without encountering an access error. The change restores a missing permission needed to load accounting views, bringing behavior back in line with previous versions.
Original PR description
**Description of the issue/feature this PR addresses:** Users in the 'Accounting / Invoicing & Banks' group were encountering an access error when attempting to open the Accounting app. This was…
**Description of the issue/feature this PR addresses:** Users in the 'Accounting / Invoicing & Banks' group were encountering an access error when attempting to open the Accounting app. This was caused by a missing read access right for the `account.return.type` model that is present in previous versions (e.g. saas-19.3). Without this permission, the basic accounting group (`account.group_account_basic`) is blocked from loading the necessary accounting views. This commit restores the `access_account_return_type_basic` rule, granting read access to the basic accounting group so they can access the app without errors. opw-6377912 **Steps to reproduce:** - Sign in as Mitchell Admin - Settings > Users & Companies > Users > Mitchell Admin > Access Rights > Accounting > Accounting > change to ‘Invoicing & Banks’ - Attempt to access the Accounting app > observe Access Error **Current behavior before PR:** - Users in the 'Accounting / Invoicing & Banks' group are unable to access the Accounting app due to Access Error **Desired behavior after PR is merged:** - Users in the 'Accounting / Invoicing & Banks' are able to access the Accounting app
This fixes an issue where invoice line pre-tax amounts could stay outdated after recalculating taxes with Avatax. The system now refreshes both tax and pre-tax values from the latest Avatax response, helping keep invoice totals accurate.
Original PR description
Previously, when recomputing taxes via Avatax, `manual_tax_amounts` was cleared and repopulated from the fresh API response, but `manual_total_excluded_currency` was only set if it was None. This meant that after the first Avatax call, the pre-tax base amount was never refreshed from subsequent API responses, even though the tax amounts were. This inconsistency could cause stale pre-tax base amounts to persist on invoice lines across recomputations, even when Avatax returned a different base amount. By resetting `manual_total_excluded_currency` to `None` at the start of each recomputation, mirroring what is already done for `manual_tax_amounts`, we ensure that the pre-tax base is always taken from the current Avatax response rather than a previously cached value. opw-6235597 Forward-Port-Of: odoo/enterprise#124152 Forward-Port-Of: odoo/enterprise#123802
Fixed a conflict that could stop Obox quality-control cameras from being detected after the IoT module was installed. This keeps photo-based quality checks working reliably and avoids confusing camera errors for warehouse users.
Original PR description
Steps to reproduce: - Install `obox_quality_control` but do not install `iot`. - Configure a quality check to take a picture with an Obox camera. - Validate a receipt an confirm the camera works as expected. - Now install the `iot` module, and try to take a picture again. **Expected behaviour:** The camera still works as expected. **Actual behaviour:** There is a 'Camera not found' error. This issue is caused by both the Obox and IoT quality modules adding an `identifier` field to the quality control wizard. The fix is simply to use a different name for the Obox field. In addition, we now hide the IoT button in the wizard if the IoT device is not set. task-6329066
Luxembourg payroll now uses the latest official salary index values for contracts starting in 2025 and 2026. This ensures contract signature indexes and related payroll calculations reflect current legal figures instead of outdated 2023 values.
Original PR description
## Issue When creating or browsing an existing contract in a Luxembourgish company, the current index shown is the one from September 2023 (which was up-to-date until Mai 2025). If the contract is…
## Issue
When creating or browsing an existing contract in a Luxembourgish company, the current index shown is the one from September 2023 (which was up-to-date until Mai 2025). If the contract is created after Mai 2025, the "Index on Contract Signature" field is also wrong.
## Steps to reproduce
1. Install *Luxembourg - Payroll* (`l10n_lu_hr_payroll`)
2. Using a Luxembourgish company, create a new contract for an employee
- *Contract Start Date*: Any date after 05/01/2025 (Mai 1st 2025)
3. __The *Index on Contract Signature* shows `944.43`, which is the index from September 2023. It does not match with the most recent indices.__
## Cause
The two most recent indices are missing from the [`rule_parameter_lu_index`](https://github.com/odoo/enterprise/blob/885edbc270a86ab76e0a6eff4acb5767c0fe29d1/l10n_lu_hr_payroll/data/rule_parameters/general_rules_data.xml#L4-L58). These indices are:
- `968.04` from 2025-05-01 (Mai 1st 2025)
- `992.24` from 2026-06-01 (June 1st 2026)
These values were taken from [here](https://salary.lu/en/tools/social-parameters/indexation-of-salaries) and double-checked [here](https://lustat.statec.lu/?lc=en&tm=DF_C1201&pg=0&snb=1).
## Tests modification
Updating the latest index had an impact on the tests from the `l10n_lu_hr_payroll_account` (testing the salary rules). In fact, the current index (`l10n_lu_current_index`) is [used to compute the indexed wage](https://github.com/odoo/enterprise/blob/7892d035ddb968d67a3e8da0daf91292bd8fb499/l10n_lu_hr_payroll/models/hr_contract.py#L24-L33) (`l10n_lu_indexed_wage`), which is then used to compute most lines in the payslip (e.g., the `WAGE_SUPPLEMENT_70`).
https://github.com/odoo/enterprise/blob/7892d035ddb968d67a3e8da0daf91292bd8fb499/l10n_lu_hr_payroll/data/salary_rules/hr_salary_rule_data.xml#L70-L74
Since the latest index is not the same as when those tests were written, the values are not correct anymore. To prevent this, time was frozen to 01/01/2024 to use the expected index (944.43, from September 2023).
opw-6330790
Forward-Port-Of: odoo/enterprise#122147POS users can now access the Kitchen Display app directly from the main dashboard without being blocked by an access error. This removes an inconsistent entry point issue and helps restaurant staff reach preparation displays more reliably.
Original PR description
**Description of the issue/feature this PR addresses:** When a POS user attempts to open the Kitchen Display app from the main dashboard, they are blocked by an Access Error, despite being able to…
**Description of the issue/feature this PR addresses:**
When a POS user attempts to open the Kitchen Display app from the main dashboard, they are blocked by an Access Error, despite being able to access the interface from within the POS app's sub-menu.
This occurs because the dashboard menu triggers a server action (`action_pos_preparation_display_kitchen_display`) to route the user. When a server action has no explicitly defined `group_ids`, Odoo's `_can_execute_action_on_records` method falls back to requiring `write` access on the underlying model (`pos.prep.display`) to execute the code. Since standard POS users do not have 'write' access to this model, the execution engine blocks the routing attempt.
This commit resolves the issue by explicitly appending the POS User group to the server action's `group_ids`.
opw-6305014
**Steps to reproduce:**
- As Mitchell Admin:
- Settings > Users & Companies > Users > Marc Demo > Access Rights > Sales > set POS to User
- As Marc Demo:
- Attempt to access Kitchen Display app > observe Access Error
- POS > Orders > Preparation Display > observe no error
**Current behavior before PR:**
- POS Users receive an Access Error when attempting to access the Kitchen Display app from the main dashboard
**Desired behavior after PR is merged:**
- No Access Error when POS Users access the Kitchen Display app
Forward-Port-Of: odoo/enterprise#122531
Forward-Port-Of: odoo/enterprise#121419This update ensures that all invoices sent via Peppol are regularly checked for validity, regardless of whether they are sent in batches or individually. Previously, this check was only performed manually, leading to potential issues with Peppol compliance. This change improves the reliability and accuracy of our Peppol invoice processing.
Original PR description
If you have a partner that wasn't on Peppol. If you only do batch sending, we never re-check its validity. You need to do it by hand, or open explicitely the send&print for an invoice for this customer. We should simply do that check in every case, in batch or in manual sending. task-6296017 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273121
This update resolves an issue preventing guests in video calls from receiving notifications via the Odoo bus. Previously, a proxy system incorrectly handled subscriptions, leading to dropped notifications. Now, the system correctly identifies and delivers notifications to guests, ensuring seamless participation in video calls.
Original PR description
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the…
Guests never receive any bus notification when the websocket is not handled by Odoo itself but by a proxy that forwards subscriptions through `/websocket/peek_notifications` and dispatches the notifications on its own (which is how Odoo.sh serves databases).
The peek controller calls `ir.websocket._prepare_subscribe_data()` directly, bypassing `_subscribe()`, the only method decorated with `@add_guest_to_context`. The guest cookie is present on the request but never read, so the returned channel list only contains the anonymous channels (broadcast, res.groups) and lacks the guest's personal ones: ("mail.guest", id), ("discuss.channel", id) and presence. The proxy therefore never registers those channels, and every notification targeted at the guest is silently dropped.
Before this commit, discuss calls with a guest are broken: a 2-person call never connects (p2p offers/answers/ICE are delivered over the bus); in a 3+ person call, any guest who joined before the SFU threshold stays stuck in dead p2p (they never receive the `sfu_hot_swap` notification) while a guest joining as 3rd+ participant works, since the join RPC returns the SFU credentials synchronously.
We override `peek_notifications` with `add_guest_to_context` so the route is aware of guests.
opw-5490739
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275184
Forward-Port-Of: odoo/odoo#274743A recent update introduced an access error for users with Attendance app administrator rights but lacking access to employee records when viewing overtime rulesets. This fix restricts the visibility of a new 'Stat' button to authorized users, preventing the error and ensuring the feature remains available to those with the necessary permissions. This resolves a potential disruption for users managing overtime.
Original PR description
**Steps to reproduce:** 1. Install the **Attendance** app in saas-19.2 with demo data. 2. Log in as a user who has **Administrator** rights in the Attendance app but no access rights in the Employees…
**Steps to reproduce:**
1. Install the **Attendance** app in saas-19.2 with demo data.
2. Log in as a user who has **Administrator** rights in the Attendance app but no access rights in the Employees app.
3. Go to **Attendance → Configuration → Overtime Rulesets**.
4. Open any overtime ruleset.
An `AccessError` is raised:
```
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 3373,
in check_access
raise result[1]()
odoo.exceptions.AccessError: You are not allowed to access
'Employee Record' (hr.version) records.
This operation is allowed for the following groups:
- Employees/Administrator
- Employees/Officer: Manage all employees
Contact your administrator to request access if necessary.
```
**Issue:**
A new feature introduced an employee count stat button on `hr.attendance.overtime.ruleset` in [v19.2](https://github.com/odoo/odoo/pull/236555/changes).
Users who have administer right in Attendance app but do not have access to Employee records trigger an access error when opening the ruleset.
**Solution:**
The fix restricts the visibility of the [Stat button ](https://github.com/odoo/odoo/blob/7c6f31d730304bca3f6c996800e76d1e40ce4adf/addons/hr_attendance/views/hr_attendance_overtime_rule_views.xml#L114)to users with the required Employee groups, preventing the access error while keeping the feature available for authorized users.
opw- 6358550
upg- 4449776
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275320This update fixes an issue where discount lines in the TBAI XML file generated for electronic invoicing were incorrectly showing negative import values. The fix ensures that all monetary amounts, including discounts, are accurately represented as positive values, resolving a potential discrepancy in financial reporting. This ensures data integrity for tax compliance.
Original PR description
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from…
Step to reproduce: - install pos_discount and l10n_es_edi_tbai_pos with demo data - start pos, add a product and a discount of 10% - fulfill the order - go to backend and open that order - from "TicketBai" page, open the "TicketBAI Post File" xml file Observation: - `ImporteUnitario` and `ImporteTotal` were exported as positive values for discount lines. cause: - Commit [1] assumed tax details are always positive. - This is not generally true, in case we have price_unit < 0 - The logic relied on `is_refund`, which depends on `qty * price`. - `_l10n_es_tbai_get_values` then multiplied values by `-1` again for refunds. https://github.com/odoo/odoo/blob/e751fa1e010dbda63903d598048ef415709b4af4/addons/l10n_es_edi_tbai_pos/models/pos_order.py#L177-L181 - For discount lines, `is_refund = True` and `price = -10`, resulting in `-10 * -1 = 10`. Fix: - Ensure tax detail values are always returned as positive values, matching the assumption introduced in commit [1] [1] https://github.com/odoo/odoo/commit/03d55104e49aa65aa4c6475e199747fe9132e754 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275451 Forward-Port-Of: odoo/odoo#265777
This update corrects a bug where reverting an inventory adjustment with a package resulted in negative quantities appearing within the package. The fix ensures that quantities are accurately restored to their original state after a revert, preventing inconsistencies in inventory tracking. This improves data reliability and avoids potential errors in stock management.
Original PR description
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product. ## Steps to produce: - Install Inventory…
Currently when the user reverts an inventory adjustment move line with a package the package contains extra line showing negative quantity of the product.
## Steps to produce:
- Install Inventory without demo data
- Settings Enable 'Packages'
- Create a product:
- Cheese burger
- On hand > Create a new quant
- Package: 'Burgerbox' and 'On Hand Quantity`: 1 and save
- Set the On Hand quantity to zero and save
- History > Revert the Inventory adjustment line from WH/stock to Inventory adjustment by selecting it and reverting via actions.
- Products > Packages > BurgerBox
## Observed Behaviour:
After reverting an inventory adjustment that set the product's physical quantity to 0, the package contains two lines for the same product with quantities 1 and -1.
This is inconsistent because a package should not contain a product with a negative quantity.
The package should be restored to its original state and contain only the expected positive quantity.
## Root cause:
When the user reverts the move line, `action_revert_inventory` is called. This method creates the revert move and then marks that move as done at [1].
Marking the move as done subsequently marks all related move lines as done at [2]. During this process, the system first unreserves the quantity from the virtual location / inventory adjustment and then removes the quantity from that location (resulting in a -1 quantity move line at that location). This is performed through `_synchronize_quant`, which is responsible for synchronizing the physical inventory with the move line at [3].
The `_synchronize_quant` method uses the move line's `package_id` when updating the corresponding quant at [4]. As a result, `_update_available_quantity` creates a new quant with the following values at [5]:
```
{
'product_id': 1,
'location_id': 14,
'lot_id': stock.lot(),
'package_id': 1,
'owner_id': res.partner(),
'in_date': datetime.datetime(2026, 6, 22, 12, 42, 11),
'quantity': -1.0,
}
```
This creates a quant with a negative quantity that is linked to the package because `package_id` is set on the newly created quant. Consequently, the move line with the negative quantity becomes associated with the package.
[1]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L1016-L1035
[2]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move.py#L1956 [3]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L662-L666
[4]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_move_line.py#L678-L687
[5]-
https://github.com/odoo/odoo/blob/333c279be7cba9fda17d2818be36f4d96d8cd0f6/addons/stock/models/stock_quant.py#L1130-L1143
## Solution:
Remove the source `package_id` when creating revert moves for inventory adjustment locations.
When an inventory adjustment sets a product's quantity to 0, the adjustment is completed without a destination package, meaning the product is effectively removed from the package. Therefore, the corresponding revert move should not retain the package as its source. Keeping the package as the source is inconsistent because package information should not exist on a virtual inventory adjustment location, and the original inventory adjustment removes the product from the package (there is no destination package).
By removing the source `package_id` from the revert move, the system avoids creating negative quants associated with the package during quant synchronization. This also ensures that, after the inventory adjustment is reverted, the quantities of products inside the package are restored correctly and match their state prior to the adjustment.
opw-6285739
Forward-Port-Of: odoo/odoo#274663
Forward-Port-Of: odoo/odoo#271440This update resolves an issue where Odoo was incorrectly sending duplicate capture requests to Stripe for EFTPOS payments in Australia. By adjusting how the system handles these payments, the fix ensures that orders are completed successfully and avoids errors related to duplicate capture attempts, improving the reliability of POS transactions.
Original PR description
In Australia, Terminal payments using `payment_method_options.card_present.capture_method=manual_preferred` are not always captured later. When a payment is processed on the `eftpos_au` network, Stripe authorizes and captures it in a single step. However, the POS Stripe flow only skipped the extra capture based on the card brand instead of the processed network. As a result, payments such as `brand = visa` and `card_present.network = eftpos_au` were treated as capturable, and Odoo sent a second capture request. Stripe then rejected it with `payment_intent_unexpected_state` because the PaymentIntent had already been captured, leaving the POS order unfinished. This patch skips the extra capture call when the payment was processed on `card_present.network = eftpos_au`. opw-6228977 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271609 Forward-Port-Of: odoo/odoo#270293
This update fixes an issue where cash rounding records were incorrectly shared across all Indian companies. Previously, new companies would inherit records from the last created company, leading to errors. The change ensures each new Indian company has its own unique cash rounding record, resolving this conflict and improving data accuracy.
Original PR description
### Issue: When creating a new Indian company, the `Half Up` cash rounding is reassigned to the new company instead of being duplicated Previous Indian companies lose access to it, causing errors…
### Issue: When creating a new Indian company, the `Half Up` cash rounding is reassigned to the new company instead of being duplicated Previous Indian companies lose access to it, causing errors when opening invoices that reference the cash rounding if the user doesn't have access to that company ### Cause: `cash_rounding_in_half_up` was defined as a `data` record with a fixed XML ID (`l10n_in.cash_rounding_in_half_up`) `_get_in_account_cash_rounding` referenced that XML ID directly and set `company_id` to the current company on each chart of accounts installation This reassigned the single shared record to the new company instead of creating a new one Moving the definition to the `@template` decorator without a module-prefixed XML ID lets the chart of accounts system create one record per company, as intended ### Steps to reproduce: - Install `l10n_in` and switch to `IN Company` - Check the Cash Rounding records grouped by company - Create a new Indian company - Enable both `IN Company` and the new company - Check the Cash Rounding records grouped by company again Before the fix, only the last created Indian company has the Cash Rounding record opw-6318857 Forward-Port-Of: odoo/odoo#272866
This update ensures that loyalty rewards are only applied when a customer's order contains the specific products defined in the reward rule. Previously, a rule with no product restrictions would incorrectly grant rewards even with other products in the order. This fix aligns the POS frontend with the backend's behavior, improving the accuracy and reliability of the loyalty program.
Original PR description
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 -…
Steps to reproduce: - Create a promotion program (e.g. "10% discount on your order", reward_point_mode "per order") and restrict its rule to a specific product A; leave the minimum quantity at 0 - Open a PoS session and add any other product B to the order Issue: The discount was applied even though the order contained none of the rule's valid products. Cause: In `pointsForPrograms`, a rule was only gated on its quantity and amount thresholds (`totalProductQty < rule.minimum_qty`), never on the actual presence of a valid product in the order. Program templates (promotion, promo_code, next_order_coupons) create rules with minimum_qty = 0, so a product-restricted rule passed with zero matching items and, in "order" point mode, granted its points unconditionally. The same hole existed in `_canGenerateRewards` for scanned coupon programs, where rules act as conditions. The backend does not have this issue: `_program_check_compute_points` in sale_loyalty skips any rule whose valid products are not present in the order. Fix: Mirror the backend behavior in the PoS frontend: skip a product-restricted rule in `pointsForPrograms` when no (non-reward) order line matches its valid products, and make `_canGenerateRewards` return false in the same situation. Gift card and eWallet flows are unaffected since their "money"/"unit" point modes already gave 0 points when the trigger product was absent. opw-6357241 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275073
The barcode scanner check-in process in kiosk mode was previously inaccurate, with location data off by several kilometers. This update now uses the browser's geolocation to provide more precise location data, resolving this issue and improving the accuracy of check-in times.
Original PR description
**Issue** Check-in and check-out performed in kiosk mode via the barcode scanner were less accurate than those made via the manual selection. The reported inacurracy between the actual and real locations was several kilometers. **Cause** `attendance_barcode_scanned` was called without a location coming from the browser's geolocation API. In that case, the location was determined by the geoip database https://github.com/odoo/odoo/blob/51f59a293de1e86f66f30257f8fc0c419463d18c/addons/hr_attendance/controllers/main.py#L69-L70 which is generally not as accurate as the location provided by the browser. opw-5889102 Forward-Port-Of: odoo/odoo#273044 Forward-Port-Of: odoo/odoo#251478