Daily updates from Odoo
Friday, June 12, 2026
167 changes
20 changes
Enhancements to existing features
This update introduces a new 'PINT' layer within the account_edi_ubl_cii module, streamlining the processing of UBL invoices for BIS3 compliance. This enhancement aligns with European regulations and standards, ensuring accurate and efficient exchange of invoice data, particularly for international transactions.
Original PR description
Add the layer PINT between UBL and BIS3. task: 5890887 Forward-Port-Of: odoo/odoo#260058
This update introduces a new rule for calculating superannuation contributions in Australia, aligning with Australian Taxation Office (ATO) requirements. Specifically, it now separates 'Qualifying Earnings' (QE) from regular earnings, tracked per pay run, starting July 1st, 2026. This ensures accurate and compliant superannuation reporting.
Original PR description
Added new salary rule for Qualifying earnings. Super Streams now per payrun. task-6012509 Forward-Port-Of: odoo/enterprise#117367
Resolved issues and error corrections
This update resolves an issue preventing monthly companies from generating inventory valuation journal entries. The cron job's domain was incorrectly excluding monthly companies, leading to missed valuations. Now, both daily and monthly companies are processed correctly at the end of each month, ensuring accurate inventory accounting.
Original PR description
#### Description of the issue/feature this PR addresses: The "Stock Account: Inventory Valuation Closing" cron is meant to post valuation journal entries for companies configured with periodic…
#### Description of the issue/feature this PR addresses: The "Stock Account: Inventory Valuation Closing" cron is meant to post valuation journal entries for companies configured with periodic inventory valuation. Due to a faulty domain in ResCompany._cron_post_stock_valuation, monthly companies are never processed, and on the last day of the month daily companies are also skipped. As a result, no inventory valuation journal entries are ever generated by this cron for periodic-valuation companies. #### Current behavior before PR: The cron's domain requires inventory_period = 'daily', which excludes monthly companies on every non-last day of the month. On the last day of the month, an extra AND clause is added requiring inventory_period = 'monthly'. Combined with the existing 'daily' clause, this produces a contradiction (period = 'daily' AND period = 'monthly') that matches no records, so daily companies are dropped on that day as well. Net effect: monthly companies are never processed, and daily companies are skipped on month-end. #### Desired behavior after PR is merged: On a non-last day of the month, the cron processes companies with inventory_period = 'daily'. On the last day of the month, the cron processes both 'daily' and 'monthly' companies, so monthly valuation entries are posted at month-end without dropping daily companies. opw-6115649 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266465 Forward-Port-Of: odoo/odoo#264298
This update resolves an issue where delivery orders for serial-tracked products could be completed without recording the necessary serial numbers. The change ensures that when a delivery order is created without serial numbers, the picking status is correctly set to 'done' and the quantity is accurately reflected, preventing discrepancies. This improves data accuracy and traceability for inventory management.
Original PR description
Writing both `quantity` and `lot_ids` on a tracked move in the same form save leaves `move.quantity` stored at the user value while `_set_lot_ids` unlinks the remaining move line; the picking can then be validated to 'done' with no serial recorded. Force `_compute_quantity` at the end of `_set_lot_ids` so the stored value stays in sync with the move lines. Steps to reproduce: - Serial-tracked product, 6 in stock - Create a delivery order for 6 units of that product - In the delivery form, on the move row: type "1" in Quantity and remove all 6 lots from the Serial Numbers widget. - Save, Validate Before: picking goes to Done with quantity=1 and no serial. After: clear UserError, quantity stays in sync with mls. opw-6192841 Forward-Port-Of: odoo/odoo#266786 Forward-Port-Of: odoo/odoo#266394
This update ensures that prices displayed in the self-order mobile app always match the prices shown on product pages, regardless of the selected fiscal position (like 'takeout'). Previously, prices varied, causing confusion for customers. This fix aligns self-order pricing with the correct tax calculations and pricelists, improving the overall ordering experience.
Original PR description
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and…
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and sometimes skipped fiscal position on tax computation. Steps to reproduce: ------------------- * Create a fiscal Position (e.g. takeout) * Create a Taxe for that Fiscal Positions replacing the default Taxe (e.g. 0%) * Create a pricelist with a formula increasing the price by the same % as default Taxe (e.g. 15%) * Enable Self-Ordering for a Restaurant * In the takeout Presets, set our Pricelist and Fiscal Positions * Open the Mobile Menu of the Restaurant and add a product that has variants (e.g Pizza VG) > Observation: Price on product selection is different from price in cart Why the fix: ------------ We now make self-order use the same rules as an actual order: default variant for template-only display, pricelist from pos.order first (what setPreset and the session already maintain), fiscal position from the order or the preset everywhere taxes are derived, and correct tax inputs on the product page (price, pricelist, fiscalPosition, variant). Order line tax preparation now uses that same order-or-preset fiscal position, so remapped taxes apply to lines the same way they apply to the prices shown while browsing. opw-6120097 Forward-Port-Of: odoo/odoo#261535
This update resolves a problem where payments with tips after payment were incorrectly marked as 'cancelled' in Stripe. The fix ensures that payment capture happens correctly after the tips are processed, preventing disruptions in the payment flow. This improves the reliability of tip processing during restaurant transactions.
Original PR description
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce:…
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce: ------------------- * Set up terminal payment (using SIMULATOR works) * Enable tips after payment feature * Open restaurant * Make an order * Go to payment screen, select stripe * Scan card (with simulator everything is automatic) > Payment line is marked as cancelled Why the fix: ------------ After this commit https://github.com/odoo/odoo/commit/c27deda808660dde89305d574b6d662157d99d16 if `captureAfterPayment` does not return true the status of the payment line will be set to `retry`. However when pos_restaurant_stripe is also installed `captureAfterPayment` can return `undefined` when tips after payment is enabled. https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/pos_restaurant_stripe/static/src/overrides/models/payment_stripe.js#L5-L11 In this case we want to capture later and we expect the pethod to not return anything. In this case we don't want to change the status of the payment line. opw-6223838 Forward-Port-Of: odoo/odoo#268802
This update prevents the deletion of Peppol invoices and bills, ensuring a complete and accurate history for all transactions. Previously, deleting these documents created traceability issues. Now, documents are marked as 'cancelled' to maintain a full audit trail, complying with regulatory requirements.
Original PR description
Before this commit, invoices and bills sent via Peppol could be deleted, making traceability difficult. Deletion is now forbidden. Documents are instead kept and marked as cancelled to preserve their history. Task-6107420 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269352 Forward-Port-Of: odoo/odoo#258897
This update corrects a problem where test products in the Peruvian POS system were incorrectly converting prices due to a missing company setting. By assigning the correct test company, the system now displays the accurate 5.10 PEN price, resolving a failure in the refund process. This ensures accurate pricing and functionality for Peruvian users.
Original PR description
Description of the issue this commit addresses: The POS frontend converts prices using the product's currency_id. Test products created without a company_id had their currency_id fall back to the main company, causing the 5.10 PEN price to be converted unexpectedly and the l10n_pe_edi_pos refund tour to fail its orderline check. --- Desired behavior after this commit is merged: This commit sets the test product's company_id to the PE test company so its currency_id resolves to PEN. This prevents unintended currency conversion in the POS UI and restores the expected displayed price (5.10) in the refund tour. --- runbot-[242597](https://runbot.odoo.com/odoo/error/242597) Forward-Port-Of: odoo/enterprise#119834
This update corrects a bug that prevented French public entities in DROM regions (like Martinique) from correctly sending invoices through Chorus Pro. Previously, the system incorrectly used VAT numbers instead of SIRETs, leading to routing errors. This fix ensures invoices are properly formatted and transmitted.
Original PR description
When invoicing a French public entity through Chorus Pro, the SIRET of the recipient was written in the UBL PartyIdentification only when the partner country was France (country_code == 'FR'). Partners located in a DROM (overseas department/region) have a real French SIRET too, but their ISO country code failed the check, so the SIRET was dropped and replaced by the VAT number. This cause the invoice to not be routed correctly in Chorus Pro. Steps to reproduce: - Setup a french company and connect it to Peppol - Create a customer for a public entity located in Martinique, with its SIRET, Peppol address 0009:11000201100044 (Chorus Pro SIRET) and BIS Billing 3.0 format. - Issue and send an invoice to this customer via Peppol. - Open the generated *_ubl_bis3.xml: AccountingCustomerParty PartyIdentification/ID holds the VAT instead of the SIRET, and Chorus Pro never receives the invoice. opw-6153868 Forward-Port-Of: odoo/odoo#269364 Forward-Port-Of: odoo/odoo#268519
This update resolves an issue preventing authenticated users from completing donations on the donation page. The fix skips Turnstile integration when a donation form is detected, ensuring a smooth user experience for existing database configurations. This addresses a technical error related to form structure and prevents form submission failures.
Original PR description
Steps to reproduce: =================== 1. Configure a Cloudflare Turnstile site key on a 19.2 database. 2. Open `/donation/pay`. => Traceback. Cause: ====== On `/donation/pay` (and any page…
Steps to reproduce: =================== 1. Configure a Cloudflare Turnstile site key on a 19.2 database. 2. Open `/donation/pay`. => Traceback. Cause: ====== On `/donation/pay` (and any page embedding the donation snippet), the page crashes with `TypeError: Cannot read properties of null (reading 'classList')` in `TurnStile.disableSubmit`, breaking the form for authenticated visitors on databases with a Turnstile site key configured. The donation page wraps its editor-only custom-fields form in a `<section class="s_website_form">` (introduced by [1]) That inner form has no submit button of its own the actual donation submit happens in the surrounding `payment.form`. The `Form` interaction's selector (`.s_website_form form, form.s_website_form`) nevertheless matches it, so the cf_turnstile patch on `Form.start` runs, queries `.s_website_form_send` / `.o_website_form_send`, gets `null`, and crashes when reading `submitButton.classList`. Solution: ========== On master, we fixed this by adding `s_website_form_no_recaptcha`` to the donation section. For stable versions, since the view is noupdate, we used a JS workaround: if there is no submit button, simply skip attaching Turnstile. [1]: https://github.com/odoo/odoo/commit/dc0618014deace4757f35ee432629a2aa7ebe998 opw-6208466 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267404
This update streamlines the ordering process in our Point of Sale system by ensuring order submissions don't block the user interface. The system now handles background syncing of orders, preventing delays and improving table management. This change enhances the overall efficiency and responsiveness of the POS experience.
Original PR description
### Before this commit: - Clicking the Order button waited for preparation-related RPC calls, delaying the transition back to the floor screen. - Tables could still be selected while their orders were syncing. - syncingOrders used order.id, which caused inconsistent tracking. ### After this commit: - Order submission no longer blocks the UI; sync runs in the background. - syncingOrders now uses order.uuid for consistent tracking. - Tables being synced are marked and cannot be selected. - Fixed course deselection to use the correct order instance. - Updated tests to ignore syncing tables. Task:6030427 Forward-Port-Of: odoo/odoo#268520 Forward-Port-Of: odoo/odoo#256883
This update resolves an issue that occurred when creating payslips for employees with contracts exceeding 35 years. The fix adjusts a key calculation parameter to correctly account for Mexican labor law rules regarding holiday accrual for employees with significant tenure (over 60 years).
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-6090590
Forward-Port-Of: odoo/enterprise#113536This update resolves a critical issue preventing correct receipt printing in Austria, ensuring accurate financial records. It also addresses a potential deadlock during authentication with Fiskaly and FON, improving system stability and reliability. The changes focus on ensuring proper accounting processes and secure authentication flows.
Original PR description
In this task: -------------- - Fixed Austria closing receipt printing by calculating the offset from the last closed month instead of the current month. Closing records are returned in ascending order and exist only for completed months, so the latest month must use offset 0. - Prevent a deadlock during Fiskaly and FON authentication by checking for open sessions before starting any authentication flow, instead of after the first step of authentication. - The resp was used to show error which was not in the scope. task: 5420256 Forward-Port-Of: odoo/enterprise#120033 Forward-Port-Of: odoo/enterprise#102313
This update ensures that tax details are now included in test orders sent to UrbanPiper. Previously, test orders lacked this crucial information, leading to potential issues with order processing. This change improves the accuracy of test data and ensures smoother integration with the UrbanPiper system.
Original PR description
Commit 1: ======== Before this commit: =================== - Test orders sent to UrbanPiper did not include tax details for order items. After this commit: ================== - Tax details are now included in the order item payload of test orders. Task-6013007 --- Commit 2: ======== Cause: ====== In the `without demo` environment, the discount product does not have any `taxes_id`, causing the test assertion to fail. Fix: ==== Set a tax on the discount product in the test to ensure the same behavior in both `with demo` and `without demo` environments. Error-241138 Forward-Port-Of: odoo/enterprise#120126 Forward-Port-Of: odoo/enterprise#109958
This update resolves an issue where both failed and passed quality check units were incorrectly moved to the failure location. The fix ensures that the destination of moved goods is accurately determined based on remaining demand, preventing unintended misplacement of inventory. This improves the reliability of the quality control process.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- 1. Install *quality_control* module. 2. Go to *Settings* and enable *Storage Locations*. 3. Open Quality module go to the Quality…
Version:
----------
- 18.0+
Steps to reproduce:
-------------------
1. Install *quality_control* module.
2. Go to *Settings* and enable *Storage Locations*.
3. Open Quality module go to the Quality control -> Quality points
4. Create a *Quality Point* with:
* *Product* set.
* *Control per* set to *Quantity*.
* *Operation* set to *Receipts*.
* *Failure Location* set to *WH/Stock/Shelf1*.
5. Create a *Receipt* with demand of *2 units* for the product used in QP.
6. Mark the quality check as *To Do*.
7. Update the *Done Quantity* to *1*.
8. Open the quality check and click *Fail*.
9. Update the *Done Quantity* back to *2* and save.
10. Open the quality check again, click *Pass*, and validate the receipt.
11. Open the *Detailed Operations* to inspect move lines.
Issue:
------
* Both units (failed and passed) are moved to the *failure location*.
Cause:
------
When a user fails a move line via the QC wizard, the flow is:
do_fail() → show_failure_message() → confirm_fail()
→ check._move_to_failure_location(failure_location_id, failed_qty)
Inside `_move_to_failure_location`, when `failed_qty == move_line.quantity`,
the condition:
https://github.com/odoo/enterprise/blob/a33f580455a54a81d89a848f7b493d9dcc9ba2b2/quality_control/models/quality.py#L458
e.g. 1 == 1
was True even when `move.product_uom_qty = 2` (demand still 2). It only
compared the done quantities, ignoring that unfulfilled demand remained.
As a result, `move.location_dest_id` was set to the failure location.
Later, when the user increases the quantity from 1 to 2 on the move form,
the flow is:
_set_quantity → process_increase → _set_quantity_done → _prepare_move_line_vals
In `_prepare_move_line_vals` :
'location_dest_id': self.location_dest_id.id,
https://github.com/odoo/odoo/blob/47bf284e1e9d8be0d4255418e0a3f67c74fa5114/addons/stock/models/stock_move.py#L1688
The new move line inherits `move.location_dest_id` directly, which at this
point is already the failure location.
When the user then calls `do_pass()` on the second unit, `do_pass()` only
writes `quality_state = 'pass'` and never touches `location_dest_id`. So
the second (passed) move line silently retains the failure location.
Solution:
---------
Add the guard `move.product_uom_qty <= move_line.quantity` to the condition
so the entire move's destination is only redirected when there is genuinely
no remaining unfulfilled demand:
When demand > done qty, the else-branch runs instead: it reduces the
original move's demand and creates a new separate move pointing to the
failure location, leaving the original move's `location_dest_id` pointing
to stock. Any subsequent move lines created on the original move therefore
correctly inherit the stock destination.
---
opw-6080871
Forward-Port-Of: odoo/enterprise#120322
Forward-Port-Of: odoo/enterprise#112859This change prevents guest contact archiving during order validation from disrupting email notifications for related shipments. Previously, archiving removed the contact from key systems, leading to missing shipment confirmation emails. This reversion restores the original behavior to ensure reliable shipment notifications.
Original PR description
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search…
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/odoo/orm/fields_relational.py#L673-L677 As a result, the partner is silently dropped from the `partner_ids` Many2Many on the mail composer even though we do write it https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/addons/mail/wizard/mail_compose_message.py#L538-L539 and the picking confirmation email is never sent. A potential fix would have been to disable this filtering at the ORM level but that would have impacted any flow that relies on archived partners being excluded. This reverts commit 3a20ff382d164f05d3d6b66e94318ed80aaa41cc. This reverts commit 64d9ded9637286ef0cfd9e65ba7c60d4f48d6c16. This reverts commit ef10f93b77263836815034e15bae6cddbd38c4f9. opw-6232937 Forward-Port-Of: odoo/odoo#269570 Forward-Port-Of: odoo/odoo#268568
This change prevents guest contact archiving from disrupting picking confirmation emails. When a guest contact is archived, it previously caused emails to fail to send. This fix reverts a previous change to avoid impacting other processes that rely on archived contacts.
Original PR description
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/odoo/orm/fields_relational.py#L673-L677 As a result, the partner is silently dropped from the `partner_ids` Many2Many on the mail composer even though we do write it https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/addons/mail/wizard/mail_compose_message.py#L538-L539 and the picking confirmation email is never sent. A potential fix would have been to disable this filtering at the ORM level but that would have impacted any flow that relies on archived partners being excluded. This reverts commit 5616a5bbf78c4a50b412a57609c5ff50b80b854d. opw-6232937 Forward-Port-Of: odoo/enterprise#120269 Forward-Port-Of: odoo/enterprise#119563
This fix resolves an issue preventing users from sending PEPPOL invoices through a branch company without direct access. The code has been updated to remove a check that was incorrectly blocking this functionality, allowing invoices to be sent as intended. This ensures branch companies can fully utilize PEPPOL invoicing.
Original PR description
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch…
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch company - Go to Settings and Enable PEPPOL, then save - Still in Settings, click on "Activate Electronic Invoicing" > Activate Peppol (demo) - Now use the branch company - In Settings, click on "Activate Electronic Invoicing", select "Send from parent company" > Activate Peppol (demo) - Go to Settings > Users & Companies > Users > any user (can be the current one) - Remove the user's access to "BE Company CoA" - Log in as that user if it is not the current one - Create a partner that can receive PEPPOL invoices : - Country : Belgium - Invoice sending : by Peppol - eInvoice format : EU Standard (Peppol Bis 3.0) - VAT : BE0477472701 - Peppol id : Belgian Company Registry - Create an invoice for that partner - Click on Confirm, then Send # The problem You cannot select the "by Peppol" sending method. It has the "(no access)" error attached to it. # Cause The sending method's enable state is computed by : https://github.com/odoo/odoo/blob/c7f05ae216de64d1f8e76e332bc6dd9cf11ce657/addons/account_peppol/wizard/account_move_send_wizard.py#L13 This method runs multiple check to see if the invoice can be send via peppol and one of them calls `_have_unauthorized_peppol_parent_company()` : https://github.com/odoo/odoo/blame/686a0cf67bb1e818baf43309fc94f3f0462097ed/addons/account_peppol/models/res_company.py#L136-L143 This checks that the current user has access to the parent company, which is our exact use case. This specific flow was indeed blocked by the task that introduced branch company PEPPOL invoicing : https://github.com/odoo/odoo/commit/6dd8bc34ba79c14408dc271c19ca7afb0f85fa44 The reason behind this block is in part explained by this comment : https://github.com/odoo/odoo/pull/216864#discussion_r2205047170 But after talking with the Peppol PO, this flow should be allowed # Proposed solution Entirely remove the `_have_unauthorized_peppol_parent_company()` check. After testing, it does not seem we have any access issues to worry about. opw-6080867 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262523
This update fixes an issue where barcode scanning incorrectly displayed and managed sale order quantities. The root cause was a flaw in how the system selected delivery lines, leading to inaccurate fulfillment. The fix ensures correct quantity updates when using barcode lots, preventing backorders and ensuring accurate order fulfillment.
Original PR description
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities. ## Steps to replicate: - Install Sales and Barcode (no demo data). - Enable Lots & Serial…
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities.
## Steps to replicate:
- Install Sales and Barcode (no demo data).
- Enable Lots & Serial Numbers in settings.
- Create Test Product with Tracking by Lots.
- Go to Inventory > Products>Lots & Serial Numbers and create 3 lots for the product.
- Update each lot’s on-hand quantity to 10 from the product page.
- Create and confirm a Sales Order for the product (lines: qty 3 and 2 units).
- Open the delivery in the Barcode app:
- Scan lot 2 > increase qty to 3 using +1 button
- Scan lot 3 > increase qty to 2 using +1 button
- Validate and go to the sale order.
## Observed Behavior:
The sale order delivered quantities are flipped and a backorder is created even though the quantity for the product is satisfied.
## Root cause:
The issue occurs because when a sales order is confirmed, the system defaults to
using lot 1 on the delivery receipt. When a user scans lot 2, the `_processBarcode` function is triggered, which calls `_findLine` at [1] to select the appropriate line on the receipt.
As the loop in `_findLine` iterates through `pageLines` with values like:
```
[{display_name: "Test product", quantity: 3, lot_id: { name: 'lot1' }},
{display_name: "Test product", quantity: 2, lot_id: { name: 'lot1' }}]
```
During the first iteration, `foundLine` is set at [2] for the line with quantity 3 . Since the subsequent if condition is not satisfied, the loop hits the continue block at [3].
On the next iteration, the line with quantity 2 causes `foundLine` to be overwritten at [2], and the continue block is executed again at [3].
This results in the line with quantity 2 being selected as the line to update at the end of the function.
When the user manually increases the quantity to 3, the line that originally required quantity 2 is updated and fulfilled.
Later, when lot 3 is scanned, the line that required quantity 3 is selected for update, and manually increasing the quantity to 2 before validating the order leads to a backorder and causes the delivered quantities to be flipped.
[1]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1335-L1337 [2]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1690-L1699 [3]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1727-L1729
## Solution:
Avoid grouping lines from different moves unless using batch transfers. This ensures that backorders are not created when the barcode lines are fulfilled.
opw-5423943
Forward-Port-Of: odoo/enterprise#120098
Forward-Port-Of: odoo/enterprise#109032This update corrects a bug where timesheets were incorrectly added to invoices after a partial refund was issued. The fix ensures that timesheets associated with fully invoiced orders are no longer re-added during invoice generation, preventing duplicate invoicing and maintaining accurate financial records. This improves the reliability of the invoicing process.
Original PR description
### Steps to reproduce: - Download 'Sales' and 'Timesheets' apps - Create 2 lines for the services product in the SO, invoicing policy = based on timesheets - Create 2 timesheets for both SO items - Invoice the SO - Create a credit note for line 1 => only line 2 is invoiced and line 1 is now released - Back to the SO > create invoice again > Line 2 is added to the invoice again. ### Cause of Issue: When generating the new invoice, `_recompute_qty_to_invoice` identifies timesheets linked to refunded invoices. Because the original invoice was partially refunded, all timesheets attached to that invoice match the domain used to locate timesheets—even the timesheets for line 2, which wasn't refunded. ### Fix: Ensures that lines that have already been completely invoiced are safely ignored and not inadvertently re-added to subsequent invoices. opw-6217684 Forward-Port-Of: odoo/odoo#268972 Forward-Port-Of: odoo/odoo#265840
23 changes
Enhancements to existing features
This update introduces a new 'PINT' layer between UBL and BIS3 invoices, aligning with European regulations for electronic invoicing. This enhancement improves the accuracy and compliance of our system when handling invoices, particularly for international transactions and PEPPOL networks. It ensures adherence to industry standards for data exchange.
Original PR description
Add the layer PINT between UBL and BIS3. task: 5890887 Forward-Port-Of: odoo/odoo#260058
This update introduces a new rule for calculating superannuation contributions in Australia, aligning with Australian Taxation Office (ATO) requirements. Specifically, it now separates ‘Qualifying Earnings’ (QE) from regular earnings, impacting how superannuation is calculated from July 1st, 2026. This ensures compliance and accurate reporting of superannuation obligations.
Original PR description
Added new salary rule for Qualifying earnings. Super Streams now per payrun. task-6012509 Forward-Port-Of: odoo/enterprise#117367
This update automatically refreshes KYC status information for French PDP users by receiving notifications from IAP. Previously, users had to manually update this status. This change streamlines the process and ensures accurate, real-time data.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596 Forward-Port-Of: odoo/odoo#268528
Resolved issues and error corrections
This change reverts a recent update that caused picking confirmation emails to fail when guest contacts were archived. Archiving guest contacts automatically filters them from order systems, preventing related email notifications. This reversion ensures that picking confirmation emails are sent correctly, maintaining accurate order tracking.
Original PR description
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search…
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/odoo/orm/fields_relational.py#L673-L677 As a result, the partner is silently dropped from the `partner_ids` Many2Many on the mail composer even though we do write it https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/addons/mail/wizard/mail_compose_message.py#L538-L539 and the picking confirmation email is never sent. A potential fix would have been to disable this filtering at the ORM level but that would have impacted any flow that relies on archived partners being excluded. This reverts commit 3a20ff382d164f05d3d6b66e94318ed80aaa41cc. This reverts commit 64d9ded9637286ef0cfd9e65ba7c60d4f48d6c16. This reverts commit ef10f93b77263836815034e15bae6cddbd38c4f9. opw-6232937 Forward-Port-Of: odoo/odoo#268568
This change prevents email confirmations for related pickings when guest contacts are archived during sales order validation. The system silently removes archived guest contacts, disrupting the email notification process. We've reverted a previous change to ensure pickings are correctly notified, maintaining reliable order fulfillment communication.
Original PR description
Archiving guest contacts upon SO validation breaks mail confirmations for related pickings. When a guest contact is archived, the ORM automatically filters it out from any search https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/odoo/orm/fields_relational.py#L673-L677 As a result, the partner is silently dropped from the `partner_ids` Many2Many on the mail composer even though we do write it https://github.com/odoo/odoo/blob/e8a372b71dc91a3e3649e572380f59ee648c5bdc/addons/mail/wizard/mail_compose_message.py#L538-L539 and the picking confirmation email is never sent. A potential fix would have been to disable this filtering at the ORM level but that would have impacted any flow that relies on archived partners being excluded. This reverts commit 5616a5bbf78c4a50b412a57609c5ff50b80b854d. opw-6232937 Forward-Port-Of: odoo/enterprise#119563
This update optimizes how the standard price of products is calculated in stock moves. Previously, a complex and slow process was used, but now a faster, more accurate method is implemented. This improves overall system performance and ensures more reliable product valuation.
Original PR description
When validating a stock move, we recompute the product's `standard_price` using a strategy that depends on the costing method: - Standard: no update - AVCO: replay the full history of `stock.move` since the last `product.value` - FIFO: fetch remaining `stock.move` records to find the stack and recompute the average from their remaining value and quantity For both FIFO and especially AVCO, this is costly and in most cases unnecessary. Instead, we can compute the new `standard_price` incrementally by adding the incoming value and quantity to the current ones. This is fast because `standard_price` is stored and `qty_available` is based on `stock.quant`. The new price is computed as: new_price = (previous_qty * std_price + added_value) / new_qty_available Forward-Port-Of: odoo/odoo#267598 Forward-Port-Of: odoo/odoo#264165
This update resolves an issue where delivery orders for serial-tracked products could be completed without recording the necessary serial numbers. The change ensures that when a user removes all serial numbers from a move line, the delivery order must still include a quantity, preventing incomplete deliveries. This improves data accuracy and compliance.
Original PR description
Writing both `quantity` and `lot_ids` on a tracked move in the same form save leaves `move.quantity` stored at the user value while `_set_lot_ids` unlinks the remaining move line; the picking can then be validated to 'done' with no serial recorded. Force `_compute_quantity` at the end of `_set_lot_ids` so the stored value stays in sync with the move lines. Steps to reproduce: - Serial-tracked product, 6 in stock - Create a delivery order for 6 units of that product - In the delivery form, on the move row: type "1" in Quantity and remove all 6 lots from the Serial Numbers widget. - Save, Validate Before: picking goes to Done with quantity=1 and no serial. After: clear UserError, quantity stays in sync with mls. opw-6192841 Forward-Port-Of: odoo/odoo#266632 Forward-Port-Of: odoo/odoo#266394
This update fixes an issue where invoices for French public entities in overseas departments (DROM) like Martinique were incorrectly formatted for Chorus Pro. The system was defaulting to VAT numbers instead of the correct SIRET, preventing proper invoice routing. This ensures accurate data transmission and compliance with Chorus Pro requirements.
Original PR description
When invoicing a French public entity through Chorus Pro, the SIRET of the recipient was written in the UBL PartyIdentification only when the partner country was France (country_code == 'FR'). Partners located in a DROM (overseas department/region) have a real French SIRET too, but their ISO country code failed the check, so the SIRET was dropped and replaced by the VAT number. This cause the invoice to not be routed correctly in Chorus Pro. Steps to reproduce: - Setup a french company and connect it to Peppol - Create a customer for a public entity located in Martinique, with its SIRET, Peppol address 0009:11000201100044 (Chorus Pro SIRET) and BIS Billing 3.0 format. - Issue and send an invoice to this customer via Peppol. - Open the generated *_ubl_bis3.xml: AccountingCustomerParty PartyIdentification/ID holds the VAT instead of the SIRET, and Chorus Pro never receives the invoice. opw-6153868 Forward-Port-Of: odoo/odoo#269364 Forward-Port-Of: odoo/odoo#268519
This update fixes an issue where both failed and passed units were incorrectly moved to the same quality control location. The fix ensures that only the units with unmet demand are moved to the failure location, preventing unintended consequences and improving the accuracy of quality control processes. This resolves a discrepancy in how the system handled partial QC failures.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- 1. Install *quality_control* module. 2. Go to *Settings* and enable *Storage Locations*. 3. Open Quality module go to the Quality…
Version:
----------
- 18.0+
Steps to reproduce:
-------------------
1. Install *quality_control* module.
2. Go to *Settings* and enable *Storage Locations*.
3. Open Quality module go to the Quality control -> Quality points
4. Create a *Quality Point* with:
* *Product* set.
* *Control per* set to *Quantity*.
* *Operation* set to *Receipts*.
* *Failure Location* set to *WH/Stock/Shelf1*.
5. Create a *Receipt* with demand of *2 units* for the product used in QP.
6. Mark the quality check as *To Do*.
7. Update the *Done Quantity* to *1*.
8. Open the quality check and click *Fail*.
9. Update the *Done Quantity* back to *2* and save.
10. Open the quality check again, click *Pass*, and validate the receipt.
11. Open the *Detailed Operations* to inspect move lines.
Issue:
------
* Both units (failed and passed) are moved to the *failure location*.
Cause:
------
When a user fails a move line via the QC wizard, the flow is:
do_fail() → show_failure_message() → confirm_fail()
→ check._move_to_failure_location(failure_location_id, failed_qty)
Inside `_move_to_failure_location`, when `failed_qty == move_line.quantity`,
the condition:
https://github.com/odoo/enterprise/blob/a33f580455a54a81d89a848f7b493d9dcc9ba2b2/quality_control/models/quality.py#L458
e.g. 1 == 1
was True even when `move.product_uom_qty = 2` (demand still 2). It only
compared the done quantities, ignoring that unfulfilled demand remained.
As a result, `move.location_dest_id` was set to the failure location.
Later, when the user increases the quantity from 1 to 2 on the move form,
the flow is:
_set_quantity → process_increase → _set_quantity_done → _prepare_move_line_vals
In `_prepare_move_line_vals` :
'location_dest_id': self.location_dest_id.id,
https://github.com/odoo/odoo/blob/47bf284e1e9d8be0d4255418e0a3f67c74fa5114/addons/stock/models/stock_move.py#L1688
The new move line inherits `move.location_dest_id` directly, which at this
point is already the failure location.
When the user then calls `do_pass()` on the second unit, `do_pass()` only
writes `quality_state = 'pass'` and never touches `location_dest_id`. So
the second (passed) move line silently retains the failure location.
Solution:
---------
Add the guard `move.product_uom_qty <= move_line.quantity` to the condition
so the entire move's destination is only redirected when there is genuinely
no remaining unfulfilled demand:
When demand > done qty, the else-branch runs instead: it reduces the
original move's demand and creates a new separate move pointing to the
failure location, leaving the original move's `location_dest_id` pointing
to stock. Any subsequent move lines created on the original move therefore
correctly inherit the stock destination.
---
opw-6080871
Forward-Port-Of: odoo/enterprise#120175
Forward-Port-Of: odoo/enterprise#112859This update fixes an issue where the shop floor displayed component quantities with excessive decimal places, leading to inaccurate readings. The fix addresses a floating-point calculation error that occurred when processing multiple lot numbers, ensuring more precise and reliable quantity displays.
Original PR description
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be…
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be consumed in a work order operation - Create several lots for the component, per ex 2: - LOT01 with 16.528 units - LOT02 with 10,000.00 units - Create an MO for 220.800 units of the finished product - Click on the shopfloor icon - Click to register the component consumption for the component. - Choose the first lot - Then choose the remaining units from the second lot -> This will display the quantity consumed as 220.79999999999998, even if the decimal accuracy is set to only 2 digits. **Cause** Since, there are 2 `moveLines`, one for each lot, the getter `quantityDone` add 2 floating point together: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.js#L63-L69 inducing a floating-point precision error. The result is rendered directly in the XML template: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.xml#L8-L14 without rounding. opw-6243804 Forward-Port-Of: odoo/enterprise#118976
This update ensures that prices displayed in the self-order mobile interface match the prices shown on product pages, resolving a previous issue where prices varied based on the order's fiscal position. The fix aligns self-order pricing with standard order calculations, guaranteeing accurate pricing and tax calculations for takeout orders. This improves the customer experience and data consistency.
Original PR description
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and…
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and sometimes skipped fiscal position on tax computation. Steps to reproduce: ------------------- * Create a fiscal Position (e.g. takeout) * Create a Taxe for that Fiscal Positions replacing the default Taxe (e.g. 0%) * Create a pricelist with a formula increasing the price by the same % as default Taxe (e.g. 15%) * Enable Self-Ordering for a Restaurant * In the takeout Presets, set our Pricelist and Fiscal Positions * Open the Mobile Menu of the Restaurant and add a product that has variants (e.g Pizza VG) > Observation: Price on product selection is different from price in cart Why the fix: ------------ We now make self-order use the same rules as an actual order: default variant for template-only display, pricelist from pos.order first (what setPreset and the session already maintain), fiscal position from the order or the preset everywhere taxes are derived, and correct tax inputs on the product page (price, pricelist, fiscalPosition, variant). Order line tax preparation now uses that same order-or-preset fiscal position, so remapped taxes apply to lines the same way they apply to the prices shown while browsing. opw-6120097 Forward-Port-Of: odoo/odoo#261535
This update resolves an issue where payments with tips after payment were incorrectly marked as 'cancelled' in Stripe. The fix ensures that payment capture happens correctly after the tips are processed, preventing disruptions in the payment flow. This improves the reliability of tip processing during terminal payments.
Original PR description
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce:…
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce: ------------------- * Set up terminal payment (using SIMULATOR works) * Enable tips after payment feature * Open restaurant * Make an order * Go to payment screen, select stripe * Scan card (with simulator everything is automatic) > Payment line is marked as cancelled Why the fix: ------------ After this commit https://github.com/odoo/odoo/commit/c27deda808660dde89305d574b6d662157d99d16 if `captureAfterPayment` does not return true the status of the payment line will be set to `retry`. However when pos_restaurant_stripe is also installed `captureAfterPayment` can return `undefined` when tips after payment is enabled. https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/pos_restaurant_stripe/static/src/overrides/models/payment_stripe.js#L5-L11 In this case we want to capture later and we expect the pethod to not return anything. In this case we don't want to change the status of the payment line. opw-6223838 Forward-Port-Of: odoo/odoo#268802
This update prevents the deletion of Peppol invoices and bills, which previously caused traceability issues. Now, documents are marked as cancelled to maintain a complete history of transactions. This ensures compliance and accurate reporting for Peppol-related activities.
Original PR description
Before this commit, invoices and bills sent via Peppol could be deleted, making traceability difficult. Deletion is now forbidden. Documents are instead kept and marked as cancelled to preserve their history. Task-6107420 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269352 Forward-Port-Of: odoo/odoo#258897
This update corrects a bug in the POS system's price conversion for test products in Peru. Previously, test products lacked a company assignment, leading to incorrect currency conversions and failing refund checks. Now, the system correctly uses the Peru test company, ensuring accurate prices and proper refund tour functionality.
Original PR description
Description of the issue this commit addresses: The POS frontend converts prices using the product's currency_id. Test products created without a company_id had their currency_id fall back to the main company, causing the 5.10 PEN price to be converted unexpectedly and the l10n_pe_edi_pos refund tour to fail its orderline check. --- Desired behavior after this commit is merged: This commit sets the test product's company_id to the PE test company so its currency_id resolves to PEN. This prevents unintended currency conversion in the POS UI and restores the expected displayed price (5.10) in the refund tour. --- runbot-[242597](https://runbot.odoo.com/odoo/error/242597) Forward-Port-Of: odoo/enterprise#119834
This update resolves an issue preventing users from sending PEPPOL invoices through a branch company without direct access. The fix removes a check that was incorrectly blocking this functionality, allowing for streamlined invoice processing via the parent company. This change ensures branch companies can utilize PEPPOL invoicing as intended.
Original PR description
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch…
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch company - Go to Settings and Enable PEPPOL, then save - Still in Settings, click on "Activate Electronic Invoicing" > Activate Peppol (demo) - Now use the branch company - In Settings, click on "Activate Electronic Invoicing", select "Send from parent company" > Activate Peppol (demo) - Go to Settings > Users & Companies > Users > any user (can be the current one) - Remove the user's access to "BE Company CoA" - Log in as that user if it is not the current one - Create a partner that can receive PEPPOL invoices : - Country : Belgium - Invoice sending : by Peppol - eInvoice format : EU Standard (Peppol Bis 3.0) - VAT : BE0477472701 - Peppol id : Belgian Company Registry - Create an invoice for that partner - Click on Confirm, then Send # The problem You cannot select the "by Peppol" sending method. It has the "(no access)" error attached to it. # Cause The sending method's enable state is computed by : https://github.com/odoo/odoo/blob/c7f05ae216de64d1f8e76e332bc6dd9cf11ce657/addons/account_peppol/wizard/account_move_send_wizard.py#L13 This method runs multiple check to see if the invoice can be send via peppol and one of them calls `_have_unauthorized_peppol_parent_company()` : https://github.com/odoo/odoo/blame/686a0cf67bb1e818baf43309fc94f3f0462097ed/addons/account_peppol/models/res_company.py#L136-L143 This checks that the current user has access to the parent company, which is our exact use case. This specific flow was indeed blocked by the task that introduced branch company PEPPOL invoicing : https://github.com/odoo/odoo/commit/6dd8bc34ba79c14408dc271c19ca7afb0f85fa44 The reason behind this block is in part explained by this comment : https://github.com/odoo/odoo/pull/216864#discussion_r2205047170 But after talking with the Peppol PO, this flow should be allowed # Proposed solution Entirely remove the `_have_unauthorized_peppol_parent_company()` check. After testing, it does not seem we have any access issues to worry about. opw-6080867 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262523
This update fixes an issue where barcode scanning incorrectly displayed and managed sale order quantities. The fix ensures that quantities are accurately reflected when using lots, preventing backorders and ensuring correct order fulfillment. This improves the reliability of the barcode inventory process.
Original PR description
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities. ## Steps to replicate: - Install Sales and Barcode (no demo data). - Enable Lots & Serial…
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities.
## Steps to replicate:
- Install Sales and Barcode (no demo data).
- Enable Lots & Serial Numbers in settings.
- Create Test Product with Tracking by Lots.
- Go to Inventory > Products>Lots & Serial Numbers and create 3 lots for the product.
- Update each lot’s on-hand quantity to 10 from the product page.
- Create and confirm a Sales Order for the product (lines: qty 3 and 2 units).
- Open the delivery in the Barcode app:
- Scan lot 2 > increase qty to 3 using +1 button
- Scan lot 3 > increase qty to 2 using +1 button
- Validate and go to the sale order.
## Observed Behavior:
The sale order delivered quantities are flipped and a backorder is created even though the quantity for the product is satisfied.
## Root cause:
The issue occurs because when a sales order is confirmed, the system defaults to
using lot 1 on the delivery receipt. When a user scans lot 2, the `_processBarcode` function is triggered, which calls `_findLine` at [1] to select the appropriate line on the receipt.
As the loop in `_findLine` iterates through `pageLines` with values like:
```
[{display_name: "Test product", quantity: 3, lot_id: { name: 'lot1' }},
{display_name: "Test product", quantity: 2, lot_id: { name: 'lot1' }}]
```
During the first iteration, `foundLine` is set at [2] for the line with quantity 3 . Since the subsequent if condition is not satisfied, the loop hits the continue block at [3].
On the next iteration, the line with quantity 2 causes `foundLine` to be overwritten at [2], and the continue block is executed again at [3].
This results in the line with quantity 2 being selected as the line to update at the end of the function.
When the user manually increases the quantity to 3, the line that originally required quantity 2 is updated and fulfilled.
Later, when lot 3 is scanned, the line that required quantity 3 is selected for update, and manually increasing the quantity to 2 before validating the order leads to a backorder and causes the delivered quantities to be flipped.
[1]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1335-L1337 [2]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1690-L1699 [3]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1727-L1729
## Solution:
Avoid grouping lines from different moves unless using batch transfers. This ensures that backorders are not created when the barcode lines are fulfilled.
opw-5423943
Forward-Port-Of: odoo/enterprise#119164
Forward-Port-Of: odoo/enterprise#109032This update fixes an error in the VAT reports for Spanish companies (l10n_es_reports). Previously, withholding tax was incorrectly included in the total VAT calculation. The fix excludes 'retencion' taxes from the VAT total, ensuring accurate reporting and compliance.
Original PR description
Step to reproduce - install `l10n_es_reports` and switch to ES company - create a invoice, add a product, set price = 100 - add two taxes (one should be withholding tax) ex: 21%G and 19%whi - confirm it, total payable is now 100 + 21 - 19 = 102 - open vat Books report for ES, see line for this invoice Observation: - for this invoice, in total vat column, we get 102 value - it should be 100+ 21 i.e 121 as we do not include withholding taxes in total vat Cause: - the query for report used to sum up all the taxes for calculating vat Fix: - excluded tax of type "retencion" in tax summation opw-6082329 Forward-Port-Of: odoo/enterprise#120022 Forward-Port-Of: odoo/enterprise#114137
This update resolves a bug where the AI's search adjustments were incorrectly applied to multiple Odoo tabs. The fix ensures that AI-driven changes are scoped to the originating user session, preventing unintended behavior across different views. This improves the stability and reliability of the AI-powered features.
Original PR description
[FIX] ai: scope AI_ADJUST_SEARCH bus event to originating session The AI_ADJUST_SEARCH handler did not check aiSessionIdentifier, so any browser tab subscribed to the bus would apply the AI's…
[FIX] ai: scope AI_ADJUST_SEARCH bus event to originating session
The AI_ADJUST_SEARCH handler did not check aiSessionIdentifier, so any
browser tab subscribed to the bus would apply the AI's resulting search
to its current view. When the view's model lacked a field referenced in
the response (e.g. an "Active or Queue" filter on stage_id leaking from
a project.task chat into a timesheet view), the view raised a KeyError.
Align it with the four AI_OPEN_MENU_* handlers, which already drop events
from other sessions since https://github.com/odoo/enterprise/commit/d85e17d9ccf70f9cfd51c7d6b2a5b52510807484.
Steps to reproduce:
- Run Odoo with the crm and contacts modules installed
- Open two tabs:
- Tab 1: navigate to CRM and ensure you are in List view
- Tab 2: navigate to Contacts and ensure you are also in List view
- In Tab 1 (CRM), open the Ask AI chat and type "Switch to Kanban view"
- CRM switches to Kanban view as expected
- Bug: Tab 2 (Contacts) also switches to Kanban view along with Tab 1,
even though you did not interact with it
Forward-Port-Of: odoo/enterprise#119325
Forward-Port-Of: odoo/enterprise#118237This update fixes an error in the Colombian DIAN invoice processing flow. Previously, the system incorrectly flagged invoices due to a timezone mismatch, causing validation failures. The fix ensures invoices are validated using Bogota local time, resolving the issue and allowing proper DIAN document submission.
Original PR description
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from…
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from `Consumidor Final`. * Set the invoice date to 6 days in the past. * Select the DIAN Support Documents journal and a product with UNSPSC category. * Confirm the bill and click `Send Support Document to DIAN` after 5 PM Colombia time. **Observed behavior:** * An error is raised stating the issue date cannot be older than 6 days or more than 6 days in the future, even though the invoice date is within the allowed window in Colombia local time. **Cause:** * The date window validation in `_check_move_configuration` used `fields.Datetime.now()` which returns UTC time. Since Colombia is UTC-5, after 5 PM local time the UTC clock has already rolled over to the next calendar day, making a 6-day-old invoice appear 7 days old and failing the validation incorrectly. **Fix:** * Convert the current UTC datetime to the `America/Bogota` timezone and extract its local date before computing the allowed date window. * Compare directly against `move.invoice_date` (a `date` field) instead of using `fields.Datetime.to_datetime()`, keeping the comparison consistent as `date` vs `date`. opw-6011502 Forward-Port-Of: odoo/enterprise#120216 Forward-Port-Of: odoo/enterprise#115256
This update resolves an issue preventing valid vendor bills from being created in the GT accounting system. The system previously restricted document types based on company affiliation, which was incorrect for purchases. This change now allows all legally valid document types for purchase bills, ensuring accurate record-keeping.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#120363 Forward-Port-Of: odoo/enterprise#113133
This update fixes an issue where employee out-of-contract payments weren't being correctly deducted when multiple contract versions (amendments) existed for the same employee. The fix ensures that the system accurately calculates worked days across all contract versions, leading to correct payroll deductions.
Original PR description
…rsions on same contract **Steps to reproduce**: - Create a contract version from May 1 to May 14. - Create another contract version starting on May 15, then create an amendment version from May 20. - Generate a payslip for May using the May 20 version. - The employee receives the full monthly wage. The out of contract period (May 1 to May 14) is not deducted. **Reason**: - OUT worked days are linked to the first version of the contract starting on May 15. - When computing the OUT ratio, the system only considers worked days linked to the exact version being processed. - As a result, the May 20 amendment version does not see the OUT worked days and no deduction is applied. **Fix**: - Compute the OUT ratio using the contract start date instead of the current version, ensuring OUT worked days are correctly taken into account across all versions of the same contract. Task: 6259341
This update resolves a crash issue that occurred when users autofilled formulas in the spreadsheet edition. The fix ensures simple `=PIVOT(...)` formulas remain unchanged during autofill, preventing unexpected crashes and maintaining consistent behavior. This improves stability and reliability for users working with pivot tables.
Original PR description
Current behavior before PR: - Autofill on formulas like `=PIVOT(1)` could crash after the refactor in e34c0a3, the new logic tried to process all pivot formulas. - However, simple `=PIVOT(...)` cases do not require any change in formula during autofill. Desired behavior after PR is merged: - Add an early return for pivot formulas that are not `PIVOT.VALUE` or `PIVOT.HEADER`, avoiding unnecessary processing. - Ensure `=PIVOT(...)` formulas remain unchanged during autofill, preventing crashes and keeping behavior consistent. Task: [6158888](https://www.odoo.com/odoo/project/2328/tasks/6158888)
This update resolves an issue where errors occurred during the download of ETA invoices due to incorrect JSON decoding. A previous change introduced a new error type that wasn't being caught, and this fix adds a necessary catch block to ensure smooth invoice processing. This ensures invoices are correctly downloaded and processed.
Original PR description
When we download the ETA invoice PDF, a JSONDecoderError can happen when calling the json() method on the request. This error is properly caught by Odoo : https://github.com/odoo/odoo/blob/7a9a340e0dbac470c4bea3f8ce8a32e55f3e82e6/addons/l10n_eg_edi_eta/models/account_edi_format.py#L58-L60 However, the following commit introduced a monkeypatch to handle errors when the simplejson library is installed : 2435fe76eec1fc4320ef71726fc7f16ece653a32 If we meet the conditions, the original error is replaced by a json.JSONDecodeError which is not caught during the previous process. We propose to add this error to the catch block. This modification was inspired by the commit d483dac144a9caf84c44b9d8d394ea327ca87cfe. opw-6266862 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268309
18 changes
Enhancements to existing features
This update introduces a new 'PINT' layer to enhance the processing of UBL (Universal Business Language) invoices, aligning with European standards. This layer facilitates compliance with regulations like CEN-EN16931 and PEPPOL, ensuring accurate and reliable exchange of invoice data. It improves the handling of invoice data formats for international trade.
Original PR description
Add the layer PINT between UBL and BIS3. task: 5890887 Forward-Port-Of: odoo/odoo#260058
This update introduces a new rule for calculating superannuation guarantee, aligning with Australian Tax Office (ATO) requirements. Specifically, it now separates 'Qualifying Earnings' (QE) from regular time earnings, streamlining superannuation contributions from July 1st, 2026. This ensures accurate and compliant payroll processing for Australian businesses.
Original PR description
Added new salary rule for Qualifying earnings. Super Streams now per payrun. task-6012509 Forward-Port-Of: odoo/enterprise#117367
This update automatically refreshes KYC (Know Your Customer) status information for French PDP (Payment Distribution Platform) users. Previously, users had to manually update this status. Now, the system receives a notification from IAP and updates the status automatically, streamlining the process.
Original PR description
Before this commit, user needed to manually refresh de kyc status, with this commit, the status will be changed when receiving the notification from IAP task-6271596 Forward-Port-Of: odoo/odoo#268528
Resolved issues and error corrections
This update resolves an issue where report customizations made in Odoo's Studio were incorrectly applied to shared layouts, leading to unexpected behavior and potential rendering problems. The fix ensures that report edits are now stored within the specific report document view, preventing these issues and improving Studio's reliability.
Original PR description
Report edits could be applied on shared layouts such as web.basic_layout instead of the report-specific document view. This caused Studio customization diffs to affect unrelated reports and could…
Report edits could be applied on shared layouts such as web.basic_layout instead of the report-specific document view. This caused Studio customization diffs to affect unrelated reports and could also lead to rendering errors when report-specific fields were evaluated in a different report context. The issue occurred because content was inserted directly into the shared layout article section instead of the nested report document view. Steps to reproduce: 1. Open Studio on any module and create or edit a report. 2. Select any of the External, Minimal, or Blank report types. 3. Add content to the report body and save the report. 4. Open another module and create a report using the same report type. 5. Observe that the previous customization is already present. Before this fix, the generated diff could inherit from web.basic_layout. After this fix, body edits are kept inside the report-specific document view. Related Ticket: opw-6245485 Forward-Port-Of: odoo/enterprise#118880
This update resolves an issue where both units of a quality check would be incorrectly moved to the failure location after a partial failure. The fix ensures that the destination of move lines is accurately determined based on remaining demand, preventing unintended movement to the failure location. This improves the reliability of the quality control process.
Original PR description
Version: ---------- - 18.0+ Steps to reproduce: ------------------- 1. Install *quality_control* module. 2. Go to *Settings* and enable *Storage Locations*. 3. Open Quality module go to the Quality…
Version:
----------
- 18.0+
Steps to reproduce:
-------------------
1. Install *quality_control* module.
2. Go to *Settings* and enable *Storage Locations*.
3. Open Quality module go to the Quality control -> Quality points
4. Create a *Quality Point* with:
* *Product* set.
* *Control per* set to *Quantity*.
* *Operation* set to *Receipts*.
* *Failure Location* set to *WH/Stock/Shelf1*.
5. Create a *Receipt* with demand of *2 units* for the product used in QP.
6. Mark the quality check as *To Do*.
7. Update the *Done Quantity* to *1*.
8. Open the quality check and click *Fail*.
9. Update the *Done Quantity* back to *2* and save.
10. Open the quality check again, click *Pass*, and validate the receipt.
11. Open the *Detailed Operations* to inspect move lines.
Issue:
------
* Both units (failed and passed) are moved to the *failure location*.
Cause:
------
When a user fails a move line via the QC wizard, the flow is:
do_fail() → show_failure_message() → confirm_fail()
→ check._move_to_failure_location(failure_location_id, failed_qty)
Inside `_move_to_failure_location`, when `failed_qty == move_line.quantity`,
the condition:
https://github.com/odoo/enterprise/blob/a33f580455a54a81d89a848f7b493d9dcc9ba2b2/quality_control/models/quality.py#L458
e.g. 1 == 1
was True even when `move.product_uom_qty = 2` (demand still 2). It only
compared the done quantities, ignoring that unfulfilled demand remained.
As a result, `move.location_dest_id` was set to the failure location.
Later, when the user increases the quantity from 1 to 2 on the move form,
the flow is:
_set_quantity → process_increase → _set_quantity_done → _prepare_move_line_vals
In `_prepare_move_line_vals` :
'location_dest_id': self.location_dest_id.id,
https://github.com/odoo/odoo/blob/47bf284e1e9d8be0d4255418e0a3f67c74fa5114/addons/stock/models/stock_move.py#L1688
The new move line inherits `move.location_dest_id` directly, which at this
point is already the failure location.
When the user then calls `do_pass()` on the second unit, `do_pass()` only
writes `quality_state = 'pass'` and never touches `location_dest_id`. So
the second (passed) move line silently retains the failure location.
Solution:
---------
Add the guard `move.product_uom_qty <= move_line.quantity` to the condition
so the entire move's destination is only redirected when there is genuinely
no remaining unfulfilled demand:
When demand > done qty, the else-branch runs instead: it reduces the
original move's demand and creates a new separate move pointing to the
failure location, leaving the original move's `location_dest_id` pointing
to stock. Any subsequent move lines created on the original move therefore
correctly inherit the stock destination.
---
opw-6080871
Forward-Port-Of: odoo/enterprise#120175
Forward-Port-Of: odoo/enterprise#112859This update fixes an issue where invoices for French public entities in DROM regions (like Martinique) weren't correctly formatted for Chorus Pro. The system was incorrectly using VAT numbers instead of the required SIRET, preventing proper invoice routing. This ensures accurate data transmission to Chorus Pro for all French customers.
Original PR description
When invoicing a French public entity through Chorus Pro, the SIRET of the recipient was written in the UBL PartyIdentification only when the partner country was France (country_code == 'FR'). Partners located in a DROM (overseas department/region) have a real French SIRET too, but their ISO country code failed the check, so the SIRET was dropped and replaced by the VAT number. This cause the invoice to not be routed correctly in Chorus Pro. Steps to reproduce: - Setup a french company and connect it to Peppol - Create a customer for a public entity located in Martinique, with its SIRET, Peppol address 0009:11000201100044 (Chorus Pro SIRET) and BIS Billing 3.0 format. - Issue and send an invoice to this customer via Peppol. - Open the generated *_ubl_bis3.xml: AccountingCustomerParty PartyIdentification/ID holds the VAT instead of the SIRET, and Chorus Pro never receives the invoice. opw-6153868 Forward-Port-Of: odoo/odoo#269364 Forward-Port-Of: odoo/odoo#268519
This update fixes an error in the vehicle contract report that was incorrectly adding recurring costs. The issue stemmed from overlapping database queries, leading to inflated totals. The change replaces multiple joins with a single, more efficient query to ensure accurate cost calculations.
Original PR description
Steps to reproduce: ------------------- 1. Install Fleet with demo data. 2. Create a contract for a vehicle (A) with a recurring cost of 1000 and "Monthly" frequency. 3. Go to Reporting > Costs and…
Steps to reproduce: ------------------- 1. Install Fleet with demo data. 2. Create a contract for a vehicle (A) with a recurring cost of 1000 and "Monthly" frequency. 3. Go to Reporting > Costs and verify the monthly cost (it shows 1000). 4. Create another contract for the same vehicle (A) with a recurring cost of 50 and "Monthly" frequency. 5. Check the monthly cost again. Issue: ------ The reported cost is incorrect. Instead of 1050 (1000 + 50), it shows 2100. Cause: ------ The query uses multiple LEFT JOINs on the contract table, including: https://github.com/odoo/odoo/blob/9ca36dbe53692309bac84329de3b54a1c510cce0/addons/fleet/report/fleet_report.py#L103 These joins overlap and produce duplicate rows for the same vehicle and month, which results in inflated cost totals. Solution: --------- Replace the multiple LEFT JOINs with a single LATERAL join. This ensures the contract table is processed once per vehicle per month and avoids duplication, resulting in correct totals. **Before:** <img width="940" height="609" alt="image" src="https://github.com/user-attachments/assets/e5b3e747-1135-4674-97c9-4e4fd9986dfd" /> **After:** <img width="1053" height="590" alt="image" src="https://github.com/user-attachments/assets/f0df3819-07fb-4de5-aab3-5b4c6f10d213" /> opw-6024132 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an error in the Colombian DIAN invoice processing flow. Previously, the system incorrectly flagged invoices due to a mismatch between UTC time and Bogota's local time. The fix ensures invoices are validated correctly based on Colombia's local time zone, preventing processing issues.
Original PR description
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from…
**Steps to reproduce:** * Install `l10n_co_edi` module with DEMO DIAN mode enabled. * Go to Accounting > Vendor > Bills and create a new bill. * Select any Colombian partner different from `Consumidor Final`. * Set the invoice date to 6 days in the past. * Select the DIAN Support Documents journal and a product with UNSPSC category. * Confirm the bill and click `Send Support Document to DIAN` after 5 PM Colombia time. **Observed behavior:** * An error is raised stating the issue date cannot be older than 6 days or more than 6 days in the future, even though the invoice date is within the allowed window in Colombia local time. **Cause:** * The date window validation in `_check_move_configuration` used `fields.Datetime.now()` which returns UTC time. Since Colombia is UTC-5, after 5 PM local time the UTC clock has already rolled over to the next calendar day, making a 6-day-old invoice appear 7 days old and failing the validation incorrectly. **Fix:** * Convert the current UTC datetime to the `America/Bogota` timezone and extract its local date before computing the allowed date window. * Compare directly against `move.invoice_date` (a `date` field) instead of using `fields.Datetime.to_datetime()`, keeping the comparison consistent as `date` vs `date`. opw-6011502 Forward-Port-Of: odoo/enterprise#120011 Forward-Port-Of: odoo/enterprise#115256
This update fixes an issue where the shop floor displayed component quantities with excessive decimal places, leading to inaccurate readings. The fix addresses a floating-point calculation error that occurred when combining lot quantities, ensuring more precise and reliable data display for finished product tracking.
Original PR description
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be…
**Issue** In the shop floor, floating-point values may display excessive decimals. **Steps to reproduce** - Create a BoM for a product, with a component tracked by lots - Set the component to be consumed in a work order operation - Create several lots for the component, per ex 2: - LOT01 with 16.528 units - LOT02 with 10,000.00 units - Create an MO for 220.800 units of the finished product - Click on the shopfloor icon - Click to register the component consumption for the component. - Choose the first lot - Then choose the remaining units from the second lot -> This will display the quantity consumed as 220.79999999999998, even if the decimal accuracy is set to only 2 digits. **Cause** Since, there are 2 `moveLines`, one for each lot, the getter `quantityDone` add 2 floating point together: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.js#L63-L69 inducing a floating-point precision error. The result is rendered directly in the XML template: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.xml#L8-L14 without rounding. opw-6243804 Forward-Port-Of: odoo/enterprise#118976
This update fixes a discrepancy in pricing displayed for self-order items, ensuring prices align with tax calculations and pricelists. Previously, prices varied between the product selection and the order cart, especially when using takeout presets. Now, self-order prices accurately reflect tax rules and are consistent across the entire ordering process.
Original PR description
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and…
Self-order showed one price on product cards / product page and another after adding to the order, when a preset fiscal position (e.g. take-out) changed taxes. The UI used template-only pricing and sometimes skipped fiscal position on tax computation. Steps to reproduce: ------------------- * Create a fiscal Position (e.g. takeout) * Create a Taxe for that Fiscal Positions replacing the default Taxe (e.g. 0%) * Create a pricelist with a formula increasing the price by the same % as default Taxe (e.g. 15%) * Enable Self-Ordering for a Restaurant * In the takeout Presets, set our Pricelist and Fiscal Positions * Open the Mobile Menu of the Restaurant and add a product that has variants (e.g Pizza VG) > Observation: Price on product selection is different from price in cart Why the fix: ------------ We now make self-order use the same rules as an actual order: default variant for template-only display, pricelist from pos.order first (what setPreset and the session already maintain), fiscal position from the order or the preset everywhere taxes are derived, and correct tax inputs on the product page (price, pricelist, fiscalPosition, variant). Order line tax preparation now uses that same order-or-preset fiscal position, so remapped taxes apply to lines the same way they apply to the prices shown while browsing. opw-6120097 Forward-Port-Of: odoo/odoo#261535
This update resolves an issue preventing valid vendor bills from being created when using the GT company VAT affiliation. The system was incorrectly filtering document types based on company affiliation, impacting purchase workflows. This change ensures all legally valid document types can be used for purchase bills.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#113133
This update fixes an issue where barcode scanning incorrectly displayed and managed sale order quantities. The fix ensures that quantities are accurately reflected when using lots, preventing backorders and ensuring correct fulfillment. This improves the reliability of the barcode inventory process.
Original PR description
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities. ## Steps to replicate: - Install Sales and Barcode (no demo data). - Enable Lots & Serial…
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities.
## Steps to replicate:
- Install Sales and Barcode (no demo data).
- Enable Lots & Serial Numbers in settings.
- Create Test Product with Tracking by Lots.
- Go to Inventory > Products>Lots & Serial Numbers and create 3 lots for the product.
- Update each lot’s on-hand quantity to 10 from the product page.
- Create and confirm a Sales Order for the product (lines: qty 3 and 2 units).
- Open the delivery in the Barcode app:
- Scan lot 2 > increase qty to 3 using +1 button
- Scan lot 3 > increase qty to 2 using +1 button
- Validate and go to the sale order.
## Observed Behavior:
The sale order delivered quantities are flipped and a backorder is created even though the quantity for the product is satisfied.
## Root cause:
The issue occurs because when a sales order is confirmed, the system defaults to
using lot 1 on the delivery receipt. When a user scans lot 2, the `_processBarcode` function is triggered, which calls `_findLine` at [1] to select the appropriate line on the receipt.
As the loop in `_findLine` iterates through `pageLines` with values like:
```
[{display_name: "Test product", quantity: 3, lot_id: { name: 'lot1' }},
{display_name: "Test product", quantity: 2, lot_id: { name: 'lot1' }}]
```
During the first iteration, `foundLine` is set at [2] for the line with quantity 3 . Since the subsequent if condition is not satisfied, the loop hits the continue block at [3].
On the next iteration, the line with quantity 2 causes `foundLine` to be overwritten at [2], and the continue block is executed again at [3].
This results in the line with quantity 2 being selected as the line to update at the end of the function.
When the user manually increases the quantity to 3, the line that originally required quantity 2 is updated and fulfilled.
Later, when lot 3 is scanned, the line that required quantity 3 is selected for update, and manually increasing the quantity to 2 before validating the order leads to a backorder and causes the delivered quantities to be flipped.
[1]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1335-L1337 [2]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1690-L1699 [3]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1727-L1729
## Solution:
Avoid grouping lines from different moves unless using batch transfers. This ensures that backorders are not created when the barcode lines are fulfilled.
opw-5423943
Forward-Port-Of: odoo/enterprise#119164
Forward-Port-Of: odoo/enterprise#109032This update resolves an issue where payments with tips after payment were incorrectly marked as 'cancelled' in Stripe. The fix ensures that payment status remains consistent, preventing errors and improving the reliability of tip processing when using Stripe terminals. This improves the restaurant's payment processing experience.
Original PR description
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce:…
Currently when using a stripe terminal and the tips after payment feature the transaction is marked as cancelled while the transaction is marked as uncapured on stripe. Steps to reproduce: ------------------- * Set up terminal payment (using SIMULATOR works) * Enable tips after payment feature * Open restaurant * Make an order * Go to payment screen, select stripe * Scan card (with simulator everything is automatic) > Payment line is marked as cancelled Why the fix: ------------ After this commit https://github.com/odoo/odoo/commit/c27deda808660dde89305d574b6d662157d99d16 if `captureAfterPayment` does not return true the status of the payment line will be set to `retry`. However when pos_restaurant_stripe is also installed `captureAfterPayment` can return `undefined` when tips after payment is enabled. https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/pos_restaurant_stripe/static/src/overrides/models/payment_stripe.js#L5-L11 In this case we want to capture later and we expect the pethod to not return anything. In this case we don't want to change the status of the payment line. opw-6223838 Forward-Port-Of: odoo/odoo#268802
This update corrects a problem where test products in the POS system were incorrectly converting prices due to missing company information. By assigning the correct test company, the system now displays the accurate 5.10 PEN price, resolving a failure in the refund process. This ensures accurate pricing and functionality for the Peruvian E-commerce module.
Original PR description
Description of the issue this commit addresses: The POS frontend converts prices using the product's currency_id. Test products created without a company_id had their currency_id fall back to the main company, causing the 5.10 PEN price to be converted unexpectedly and the l10n_pe_edi_pos refund tour to fail its orderline check. --- Desired behavior after this commit is merged: This commit sets the test product's company_id to the PE test company so its currency_id resolves to PEN. This prevents unintended currency conversion in the POS UI and restores the expected displayed price (5.10) in the refund tour. --- runbot-[242597](https://runbot.odoo.com/odoo/error/242597) Forward-Port-Of: odoo/enterprise#119834
This update resolves an issue preventing users from sending PEPPOL invoices through a branch company without direct access. The fix removes a check that was incorrectly blocking this functionality, allowing invoices to be sent as intended. This ensures branch companies can fully utilize PEPPOL invoicing.
Original PR description
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch…
# How to reproduce - Activate Accounting & l10n_be modules with demo data - Use "BE Company CoA" - Go to Settings > Users & Companies > Companies > "BE Company CoA" > Branches - Create new branch company - Go to Settings and Enable PEPPOL, then save - Still in Settings, click on "Activate Electronic Invoicing" > Activate Peppol (demo) - Now use the branch company - In Settings, click on "Activate Electronic Invoicing", select "Send from parent company" > Activate Peppol (demo) - Go to Settings > Users & Companies > Users > any user (can be the current one) - Remove the user's access to "BE Company CoA" - Log in as that user if it is not the current one - Create a partner that can receive PEPPOL invoices : - Country : Belgium - Invoice sending : by Peppol - eInvoice format : EU Standard (Peppol Bis 3.0) - VAT : BE0477472701 - Peppol id : Belgian Company Registry - Create an invoice for that partner - Click on Confirm, then Send # The problem You cannot select the "by Peppol" sending method. It has the "(no access)" error attached to it. # Cause The sending method's enable state is computed by : https://github.com/odoo/odoo/blob/c7f05ae216de64d1f8e76e332bc6dd9cf11ce657/addons/account_peppol/wizard/account_move_send_wizard.py#L13 This method runs multiple check to see if the invoice can be send via peppol and one of them calls `_have_unauthorized_peppol_parent_company()` : https://github.com/odoo/odoo/blame/686a0cf67bb1e818baf43309fc94f3f0462097ed/addons/account_peppol/models/res_company.py#L136-L143 This checks that the current user has access to the parent company, which is our exact use case. This specific flow was indeed blocked by the task that introduced branch company PEPPOL invoicing : https://github.com/odoo/odoo/commit/6dd8bc34ba79c14408dc271c19ca7afb0f85fa44 The reason behind this block is in part explained by this comment : https://github.com/odoo/odoo/pull/216864#discussion_r2205047170 But after talking with the Peppol PO, this flow should be allowed # Proposed solution Entirely remove the `_have_unauthorized_peppol_parent_company()` check. After testing, it does not seem we have any access issues to worry about. opw-6080867 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262523
This update resolves an issue where reducing the PO quantity after a partial receipt in multi-step warehouses incorrectly calculated remaining receipt demands. The fix adjusts the calculation logic to accurately reflect the quantity of available stock when using a 'push' receipt flow, ensuring accurate picking demands.
Original PR description
**Issue** Reducing the PO quantity after performing a partial receipt, in multi-step receipts warehouse can incorrectly update the remaining receipt quantity. **Steps to reproduce** - Setup 2-route…
**Issue** Reducing the PO quantity after performing a partial receipt, in multi-step receipts warehouse can incorrectly update the remaining receipt quantity. **Steps to reproduce** - Setup 2-route receipt warehouse (Inventory > Configuration > Warehouse Management > Warehouses) - Create a PO for 35 units and confirm it - Click on receive products, set received quantity to 10 and create a backorder - Validate the next transfer - Go back to the PO and change the quantity to 20 - Check the receipt demand -> The backorder picking demand become 35 instead of 10 **Cause** Updating the quantity of a purchase order line, also updates the related picking: https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L120 It updates the picking associated to the backorder since the other one is done: https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L185-L187 https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L197 This ultimately calls: https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L228 To compute the new demand for the picking, it retrieves the `move_dest`: https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L240 To compute `qty_to_push`: https://github.com/odoo/odoo/blob/5fc1e34d174f7f61d692d086d0ff65fbfc72b013/addons/purchase_stock/models/purchase_order_line.py#L247-L249 However, since we are in a 2-route receipt setup, `move_dest` is the move from Input to stock for the done picking. Thus, `qty_to_push` is `20 - 10 = 10` instead of `20 - 35 = -15` **Solution** The previous logic assumes a pull flow, where downstream (move_dest_ids) quantities are always up-to-date and can be used as the source of truth to recompute demand. In push flows (e.g., multi-step receipts), this assumption does not hold. To fix this, we instead base the computation on the quantity of the current moves (qty) if nothing has to be attached. **Additional information** Known limitation: this does not address inconsistencies in return flows. When there're returns, units define in the pol and the one define in the sum of the picking can diverge, thus this pr won't fix that. opw-5512172 Forward-Port-Of: odoo/odoo#265583 Forward-Port-Of: odoo/odoo#248626
This update resolves an issue where attempting to create a new Global Invoice after canceling a refund through the CFDI system would fail. The fix ensures that the refund's CFDI status is correctly updated, allowing for the creation of new invoices related to the original order. This improves the functionality for Mexican POS operations.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120100 Forward-Port-Of: odoo/enterprise#117211
This update resolves a bug that occurred when reloading a chart of accounts, specifically when an account was originally set up in a different company. The fix ensures the system correctly identifies and handles accounts with old company prefixes, preventing errors and ensuring accurate account reloading.
Original PR description
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates: ```py re.match(f'^{values["code"]}0*$', account.code) ``` `account.code` is a non-stored…
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates:
```py
re.match(f'^{values["code"]}0*$', account.code)
```
`account.code` is a non-stored computed field that reads from the company-dependent field `code_store`. If the resolved account has no `code_store` entry for the target company (e.g. the account was originally set up under a different company but its xmlid was prefixed with the current company id), `_compute_code` returns False instead of a string, causing a TypeError in re.match.
```py
File "/home/odoo/src/odoo/19.0/addons/account/models/chart_template.py", line 442, in _pre_reload_data
if not account or not re.match(f'^{values["code"]}0*$', account.code):
File "/usr/lib/python3.10/re.py", line 190, in match
return _compile(pattern, flags).match(string)
TypeError: expected string or bytes-like object
```
```sql
apan_4342860=> SELECT
aa.id,
aa.code_store,
imd.module,
imd.name
FROM account_account aa
JOIN ir_model_data imd
ON imd.res_id = aa.id
AND imd.model = 'account.account'
WHERE aa.id = 1056;
id | code_store | module | name
------+-----------------+---------+-----------------
1056 | {"2": "510500"} | account | 1_co_puc_510500
(1 row)
```
This situation arises when a customer moves or reassigns an account between companies but the xmlid retains the original company prefix.
**Fix:**
After resolving the account via xmlid, check whether it actually belongs to the target company using filtered_domain with _check_company_domain. If it does not pass the check, unlink the stale ir.model.data entry and treat the account as not found, allowing the reload to re-establish the correct xmlid linkage via the code-based lookup that follows.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#2692913 changes
Resolved issues and error corrections
This update resolves an issue preventing valid vendor bills from being created when using the GT VAT affiliation. The system was incorrectly filtering document types based on company affiliation, impacting purchase document selection. This change ensures all legally valid document types can be used for purchase bills, improving data accuracy and usability.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#113133
This update resolves an issue where attempting to create a new Global Invoice after canceling a refund for a Mexican POS order would fail. The fix ensures that the refund's CFDI status is correctly updated, allowing for the creation of new invoices. This improves the functionality of the Mexican POS integration for handling refunds.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120100 Forward-Port-Of: odoo/enterprise#117211
This update resolves an issue where users could encounter errors when modifying the scheduling of marketing activities within campaigns. The fix prevents attempts to update activity hierarchies during campaign execution, improving stability and preventing potential data inconsistencies. This ensures campaigns run smoothly and reliably.
Original PR description
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing…
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save > IndexError: tuple index out of range ### Issue: The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: https://github.com/odoo/enterprise/blob/3e788e28dc76c928935d874e4e5a18d467c65539/marketing_automation/models/marketing_trace.py#L149 ### Fix: Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-6251614 Forward-Port-Of: odoo/enterprise#118994
5 changes
Resolved issues and error corrections
This update resolves an issue preventing valid vendor bills from being created in the GT accounting system. The system was incorrectly restricting document types based on company affiliation. This change now allows all legally valid document types to be used for purchase bills, ensuring accurate record-keeping.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#113133
This update resolves a bug that occurred when reloading a chart of accounts after an account was moved between companies. The original XMLID continued to point to the old company, causing errors. The fix ensures the system correctly checks if an account belongs to the current company before reloading, preventing the error and ensuring accurate account data.
Original PR description
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates: ```py re.match(f'^{values["code"]}0*$', account.code) ``` `account.code` is a non-stored…
When reloading a chart of accounts, `_pre_reload_data` resolves an account via its xmlid and then evaluates:
```py
re.match(f'^{values["code"]}0*$', account.code)
```
`account.code` is a non-stored computed field that reads from the company-dependent field `code_store`. If the resolved account has no `code_store` entry for the target company (e.g. the account was originally set up under a different company but its xmlid was prefixed with the current company id), `_compute_code` returns False instead of a string, causing a TypeError in re.match.
```py
File "/home/odoo/src/odoo/19.0/addons/account/models/chart_template.py", line 442, in _pre_reload_data
if not account or not re.match(f'^{values["code"]}0*$', account.code):
File "/usr/lib/python3.10/re.py", line 190, in match
return _compile(pattern, flags).match(string)
TypeError: expected string or bytes-like object
```
```sql
apan_4342860=> SELECT
aa.id,
aa.code_store,
imd.module,
imd.name
FROM account_account aa
JOIN ir_model_data imd
ON imd.res_id = aa.id
AND imd.model = 'account.account'
WHERE aa.id = 1056;
id | code_store | module | name
------+-----------------+---------+-----------------
1056 | {"2": "510500"} | account | 1_co_puc_510500
(1 row)
```
This situation arises when a customer moves or reassigns an account between companies but the xmlid retains the original company prefix.
**Fix:**
After resolving the account via xmlid, check whether it actually belongs to the target company using filtered_domain with _check_company_domain. If it does not pass the check, unlink the stale ir.model.data entry and treat the account as not found, allowing the reload to re-establish the correct xmlid linkage via the code-based lookup that follows.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269291This update resolves an issue where users couldn't create new Global Invoices after canceling a refund for a Mexican POS order. The fix ensures that the refund's CFDI document is correctly updated, allowing the system to recognize the refund and enable the creation of a new invoice. This improves the functionality of the Mexican CFDI reporting process.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120100 Forward-Port-Of: odoo/enterprise#117211
This update fixes a bug that occurred when users tried to reschedule marketing activities within a campaign. The change prevents errors related to activity hierarchy updates during campaign execution, ensuring campaigns run smoothly and reliably. It avoids a situation where users couldn't modify activity schedules without causing system issues.
Original PR description
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing…
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save > IndexError: tuple index out of range ### Issue: The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: https://github.com/odoo/enterprise/blob/3e788e28dc76c928935d874e4e5a18d467c65539/marketing_automation/models/marketing_trace.py#L149 ### Fix: Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-6251614 Forward-Port-Of: odoo/enterprise#118994
This update fixes an issue where return reports weren't consistently using the correct company data, leading to inaccurate calculations. The change ensures that return reports always use the specified company information, resolving potential discrepancies and improving report reliability.
Original PR description
When opening the report from the return, it would recompute all the options even if we passed the complete options of get_report_closing_options. This is fine in most cases, but when we have a return that has company_ids that does not match the logic from report it can causes issued. The forced_companies key, force the companies of the return to be the one we provide. So now the report companies in the options will always be the ones from the return when we open the report from the return without exception.
3 changes
Resolved issues and error corrections
This update resolves an issue preventing valid vendor bills from being created in the GT accounting system. The system previously restricted document types based on company affiliation, which was incorrect for purchases. This change now allows all legally valid document types for purchase bills, ensuring accurate record-keeping.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#113133
This update fixes a bug that prevented proper error messages from appearing when IoT scale operations encountered problems. Previously, the system didn't clearly communicate these errors, making it difficult to diagnose and resolve issues. This ensures users receive timely notifications about scale failures, improving operational efficiency.
Original PR description
This completes odoo/enterprise#11196, which missed error message handling for new IoT Boxes errors. `message_body` was undefined on `data.status` when `data.status === "error"`. <img width="1871" height="942" alt="image" src="https://github.com/user-attachments/assets/30b54c5b-da0d-497d-8d9e-912f7139140b" /> Forward-Port-Of: odoo/enterprise#119228
This update resolves an issue where marketing automation campaigns would fail when users attempted to adjust the scheduling of activities. The fix prevents modifications to trace hierarchies during campaign execution, ensuring campaigns run smoothly and avoiding errors related to outdated scheduling information. This improves campaign reliability and reduces potential disruptions for users.
Original PR description
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing…
### Note: **THIS IS A BACKPORT OF** https://github.com/odoo/enterprise/pull/107556 Some edits were made to the tests so that they match Odoo v18.0 ### Steps to reproduce: - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save > IndexError: tuple index out of range ### Issue: The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: https://github.com/odoo/enterprise/blob/3e788e28dc76c928935d874e4e5a18d467c65539/marketing_automation/models/marketing_trace.py#L149 ### Fix: Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-6251614 Forward-Port-Of: odoo/enterprise#118994
16 changes
New functionality added to Odoo
This update allows Odoo to import product data directly from PrestaShop stores running version 1.7 and later. This simplifies the process of bringing existing e-commerce catalogs into Odoo, saving time and effort for our users. It expands Odoo's capabilities to integrate with a wider range of online marketplaces.
Original PR description
Adds support for importing PrestaShop (PS) products from PS version 1.7 and up.
This update introduces the ability for employees to manage multiple company vehicles through Odoo. Previously, each employee was limited to a single vehicle, which is now being expanded to better accommodate business needs and employee requirements. This change simplifies vehicle tracking and reporting.
Original PR description
WIP to allow multiple company cars per employee
Enhancements to existing features
This update enhances the softphone's contact search functionality during call transfers. It now prioritizes internal users (colleagues) when searching, making it faster and easier to transfer to someone within the company. This improves the user experience by reducing irrelevant search results and streamlining the transfer process.
Original PR description
The softphone displays searched contacts grouped by the first letter of their name. This commit creates an extra group "Internal" at the top regrouping all internal users of the database, only when a search is performed, only while searching for a contact to which a call has to be transferred. Indeed, when transferring, it is likely you want to transfer to one of your colleague, and after a 2-3 letters search, it should be enough for your colleague to be nearly alone in its "Internal" group, while searching for "James" could lead to 100 "James" in the "J" section regrouping all the contacts your company is dealing with. Follow-up of task-5404888 task-5871346
This update expands the meal voucher report to include data for all companies within an organization, including parent and child branches. Previously, the report was limited to a single company. This change improves reporting accuracy and provides a more complete view of employee expenses.
Original PR description
- Added selection of company (only top-level can be selected so the report won't be partial or context dependant) - Company selection is done automatically if there's only one valid candidate - The report cannot be validated without a top level company and a top-level company cannot be selected if the user has not access to it - Used branch_ids to gather all branches that need to be computed [a root branch can be defined as a branch that has no parent or a branch which root_id is equal to its id] - Used sudo to make sure all subbranches can be computed #task-6220264
This update allows users to efficiently edit multiple sales orders simultaneously through a new 'mass editing' feature on the sales order list views. This streamlines the process of updating large numbers of orders, saving significant time and improving operational efficiency. Previously, changes required editing each order individually.
Original PR description
Enable multi_edit on sales order list views to allow mass editing. See also:https://github.com/odoo/odoo/pull/266345 task-6227460
This pull request updates the design of the Frontdesk welcome screens, enhancing their responsiveness and overall appearance. The changes aim to provide a more modern and user-friendly experience for new Frontdesk users. This is an important improvement to the user interface.
Original PR description
Follow-up of: - https://github.com/odoo/enterprise/pull/119827 Redesign of the welcome screens. Improved responsiveness and design task-6022341
This update simplifies the process for companies using fiscal years different from the calendar year. Previously, users had to manually configure return type periods for each type, which was difficult to find and manage. Now, companies can easily set these periods at the start of their returns set, improving efficiency and accuracy.
Original PR description
When a company has its fiscal year different than the calendar year, return types periodicities rarely follow an universal rule. Those rules vary a lot depending on the country. Currently, the only way for users to configure them is to open the return types and configure the desired periodicity & start date for each return type individually -> The discoverability is bad. Users should be able to configure it easily at the start of the returns set task: 5913359
Resolved issues and error corrections
This update resolves an issue where users were locked out of the documents list view after attempting to edit a row. The fix ensures the view correctly exits edit mode when a user clicks away, restoring normal functionality and preventing user frustration. This improves the overall user experience.
Original PR description
Problem: When a user selects a row, attempts to edit a cell, and then clicks away without saving, the view becomes unusable. The selected row remains highlighted, and the system prevents the selection of other lines. The user is locked out until they click the "Save" or "Discard" buttons. Cause: The UI becomes stuck in edit mode. The `onGlobalClick` event handler within `documents_list_renderer` was missing the method call to exit edit mode. Solution: Updated `onGlobalClick` to correctly trigger the method to leave edit mode. task-6059836 Forward-Port-Of: odoo/enterprise#119594 Forward-Port-Of: odoo/enterprise#113000
This update resolves an issue where cancelled journal entries were incorrectly displayed in the reconciliation view, preventing successful reconciliation and causing data inconsistencies. The fix removes a recent change that allowed draft entries in the reconciliation view, ensuring cancelled entries are properly excluded.
Original PR description
Issue: Cancelled journal entries were visible in the "Journal Items to Reconcile" view (action_move_line_posted_unreconciled) because the action domain had no filter to exclude them. This caused…
Issue: Cancelled journal entries were visible in the "Journal Items to Reconcile" view (action_move_line_posted_unreconciled) because the action domain had no filter to exclude them. This caused reconciliation failures, no reconciliation happened, and the cancelled record remained in the view. This regression was introduced during a refactor to allow draft entries in the reconciliation view, where the posted-state condition was removed from the domain: Enterprise commit: https://github.com/odoo/enterprise/commit/003cffabda7d91a6d10d58942ed972ca5e17366d As a result, cancelled journal items also became visible, causing reconciliation attempts to fail while the records remained in the view. Also, we are not allowed to reconcile cancelled move lines, and we already have the validation for this [here](https://github.com/odoo/odoo/blame/a236f67776616f6facdefb0117a6ffdde9b7c84c/addons/account/models/account_move_line.py#L2627) Issue is reproducible on runbot. Here is the video reference: https://drive.google.com/file/d/1ojIDxHn5Yst8gVFy8JyhwtJoDSSSJsmK/view?usp=sharing - OPW: 6247870 Forward-Port-Of: odoo/enterprise#119017 Forward-Port-Of: odoo/enterprise#118773
This update fixes a bug where credit limit warnings weren't correctly accounting for bank payments. Now, the system accurately calculates outstanding balances, including bank payments, ensuring warnings only appear when a customer exceeds their credit limit. This improves financial reporting accuracy and prevents unnecessary alerts.
Original PR description
Before this fix: The credit limit warning calculation only considered credit notes but ignored outstanding bank payments when computing the partner's effective outstanding balance. For example, if a…
Before this fix: The credit limit warning calculation only considered credit notes but ignored outstanding bank payments when computing the partner's effective outstanding balance. For example, if a customer had a credit limit of 1,000 and an invoice of 2,000 was created, then a bank payment of 1,500 was received, the warning would still incorrectly appear showing the customer exceeded their limit (2,000 > 1,000), even though the actual outstanding amount was only 500. After this fix: The credit limit warning now properly includes outstanding bank payments in the calculation. Two cases are handled: - Bank payments received but not yet matched to any invoice, these are identified by their open suspense account entry and deducted from the partner's outstanding exposure. - Bank payments already matched to the invoice, the reconciled amount is read from the invoice's receivable line and deducted accordingly. So with this fix, after a 1,500 bank payment, the system correctly recognises the outstanding amount as 500 and does not show a warning since it is within the 1,000 credit limit. task-5427613 Forward-Port-Of: odoo/enterprise#119829 Forward-Port-Of: odoo/enterprise#118957
This update resolves an error that occurred during DHL delivery confirmations when the scheduled delivery date was missing or set to a past time. The system now automatically adds one hour to the delivery date, preventing the error and ensuring successful order confirmations. This improves the reliability of DHL shipping confirmations.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update fixes a bug in the year-end tax calculations for Indonesian employees. Previously, a hardcoded rule incorrectly set tax allowances for employees using contract types other than 'Permanent Employee'. The update introduces new employee types and adjusts the rule to accurately calculate gross-ups for all employee types, ensuring correct PPh 21 calculations.
Original PR description
The JABATAN salary rule condition was hard-coded to check against `hr.contract_type_employee`, so employees using any other employee type would incorrectly get JABATAN = 0, producing a wrong tax allowance in year-end / termination PPh 21 recalculation.
Introduce two new Indonesia-specific employee types: "Permanent Employee" and "Non-Permanent Employee". The JABATAN rule now checks against the employee type code ("PERMANENT"), allowing users to tag multiple types as permanent if needed.
task-6215687This update fixes an issue where the 'Cancel Reason' wasn't being properly transmitted to the Peruvian EDI (SUNAT) documents when reversing invoices. The change ensures that all cancellation details, including the user-provided reason, are accurately reflected in the electronic credit note, meeting regulatory requirements. This improves data accuracy and compliance for Peruvian businesses using Odoo.
Original PR description
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit…
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit Note. Only the Credit Reason is successfully reported. ### Steps to reproduce the issue: 1. Download Accounting and l10n_pe 2. Switch to PE company 3. Create an invoice and confirm it 4. Create a credit note for the invoice with a cancel reason and a credit reason and click the reverse button 5. See that in the Peruvian EDI tab only the Credit Reason is reported but not the Cancel Reason ### Cause of the issue: In the l10n_pe_edi module, the override of the _prepare_default_reversal method maps the l10n_pe_edi_refund_reason to the new move's values, but completely omits the mapping of the wizard's textual reason field to the l10n_pe_edi_cancel_reason field of the resulting credit note. ### Reason to introduce the fix: To ensure the generated credit notes contain all required information for the Peruvian EDI (SUNAT). Mapping the cancel reason guarantees that the electronic document accurately reflects both the refund code and the descriptive cancellation text provided by the user. opw-6238525 Forward-Port-Of: odoo/enterprise#119610 Forward-Port-Of: odoo/enterprise#118479
This update corrects issues with VoIP call records not accurately reflecting user presence, particularly when calls were stuck in an ongoing state. It ensures call records are consistently updated, improving the accuracy of call status displays and preventing misleading presence indicators. This improves the overall user experience and data reliability.
Original PR description
[FIX] voip: make sure any create/write on voip.call syncs user presence Commit [1] introduced a "in-call" presence icon. Before this commit, code updating call records had to call a specific function…
[FIX] voip: make sure any create/write on voip.call syncs user presence
Commit [1] introduced a "in-call" presence icon. Before this commit,
code updating call records had to call a specific function if user
presence potentially had to be changed after the record update. While
not hacking create/write to do that might be prettier, it is also
subject to mistakes and one was already made: demo data call record
creation did not update user presence properly. Commit [2] indeed
introduced calling/ongoing call demo data and the user presence was not
correct just after database initialization.
This commit fixes that by now potentially syncing in writes and always
syncing on create.
[FIX] voip: unstuck user call presence sooner in case of stuck calls
At the moment, the Odoo phone has a freshness system for call records
that appear still calling/ongoing for a strange duration. Indeed, there
are still cases where a call ended and we could not detect it. For
example, the user simply closing the tab where a call is ongoing (we try
to warn the user before he leaves but if agrees to leave anyway, the
call is just stopped when connexions are lost but the call record stays
marked as "ongoing"). In those cases, we have 2 things:
- A once-a-month cron checks all cases that are calling for more than
5 minutes or ongoing for more than 4 hours. It moves them to "ended
unexpectedly".
- The displayed status in views, shows "calling" / "ongoing" only if the
record is not older than 5 min / 4 hours. Otherwise it shows "ended
unexpectedly" already (as if the cron already did its job), despite
the record still having the "calling" / "ongoing" status.
It is weird and non-perfect but this allows to not have a "heavy" cron
job and consistent-enough call records display in views.
Of course, the long-term plan is to have more reliable call records
status (PBX, ...).
A new problem related to this appeared though. Since [1], a call icon
is used as the discuss presence icon in case the user is currently on a
call. The "currently on a call" data being transferred based on a field
"has_active_call" synchronized on call operations. Problem: in the case
mentioned above (call stuck in ongoing), that field will stay wrong for
a full month, showing the user as being on call. This commit makes it
so the check for active calls now considers fresh-enough calls (just
like the display in views does). It is only updated on a new call
operation though, so if an user has a stuck call, he will still be shown
as being on call until he starts/ends another call (or manually correct
the stuck call record).
Again, hopefully, stuck call records will be a thing of the past soon
enough so that issue will be minimized.
Note: this also uses `effective_start_date` instead of `start_date` to
check for stale calls, as it handles the potential no start_date while
ongoing that would stay stuck forever (that should not happen but,
better safe than sorry).
[FIX] voip: not consider incoming calling calls for presence status
Commit [1] introduced a "in-call" presence status. Commit [2], alongside
several fixes (e.g. parents of this commit and mentioned commit),
introduced new call demo data, including calling/ongoing calls:
- One incoming calling for Mitchell Admin
- One outgoing calling for Marc Demo
- One incoming ongoing for Marc Demo
- One outgoing ongoing for Marc Demo
Consequence: both Mitchell Admin and Marc Demo always have the "in-call"
presence icon, which might not be the best for demo. Still nice to test
VoIP but misleading for the rest.
In the end, we can have the best of both worlds: at the moment Mitchell
Admin only has an incoming calling call... and actually, that kind of
situation should not lead to being consider as "in-call". Calling
someone does, but receiving a call that we are potentially ignoring at
the moment does not.
This commit makes it so incoming calling calls are not considered for
presence anymore, at the same time thus making Mitchell Admin presence
not impacted by default VoIP demo data.
[1] - https://github.com/odoo/enterprise/commit/f1e0c41fa7b4f425e45303e5e912bf093c56480a
[2] - https://github.com/odoo/enterprise/commit/f16faa029220ca7152289180c4de78783bab03be
task-6239844
Forward-Port-Of: odoo/enterprise#118645Code cleanup and technical improvements
This update refactors how Odoo uses reactive calls within several core modules, optimizing performance and enhancing stability. Specifically, it replaces single-argument reactive calls with proxy calls, a change introduced with Owl3. This impacts modules like Accounting, HR, and Documents, leading to smoother operation and reduced potential issues.
Original PR description
With Owl3, uses of `reactive` with only one arg can be changed to `proxy` calls. This commit changes all those uses in addons in the range [a..!w]. *: account_accountant,account_reports,documents,hr_contract_salary,hr_payroll,iap_extract,knowledge,planning,social,
This update refactors how Odoo handles reactive data calls, specifically targeting areas where single-argument reactive calls were used. The change, part of the Owl3 upgrade, improves performance and stability by utilizing a more efficient proxy mechanism. This impacts several core Odoo modules including web_enterprise, web_gantt, and web_studio.
Original PR description
With Owl3, uses of `reactive` with only one arg can be changed to `proxy` calls. This commit changes all those uses in addons in the range [w..]. *: web_enterprise,web_gantt,web_grid,web_studio
8 changes
Enhancements to existing features
This pull request introduces support for classifying and tracking prophylactic leave (maternity protection and health risk) within the payroll system for Belgian companies. It creates two new unpaid leave categories, aligning with local regulations and providing accurate payroll reporting. This improves compliance and reporting accuracy.
Original PR description
Divided existing prophylactic leave into two categories: maternity protection -> LEAVE14849 / dmfa_code: 51 health risk -> LEAVE225 (existing) / dmfa_code: 53 Added both as unpaid in the payroll structure PR community: task-6285834
This update enhances the clarity of bank statements when transactions are split into multiple lines. By adding transaction category data, Odoo now provides more descriptive labels for each line, closely matching the details from CodaBox. This makes it easier for users to understand and track their financial activity.
Original PR description
Currently, when global transaction is split into multiple lines, Odoo assigns the exact same communication text to every single split line. This makes it difficult for users to identify what each specific charge is for. To fix this, this commit introduces the transaction category data. Using this data to append specific transaction details to the end of the communication label. As a result, each split line now has a clear, descriptive label that closely matches the detailed breakdown provided by CodaBox. task-6059709
Resolved issues and error corrections
This update resolves a requirement from Luxembourg auditors regarding the classification of partners in our SAFT reports. Specifically, it ensures that less than 30% of transactions with payable or receivable accounts have missing supplier or customer IDs, aligning with Luxembourg's FAIA reporting standards. The changes update XML reports to accurately reflect partner classifications.
Original PR description
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on…
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on \Transaction\Line elements is determined by a partner's `customer_rank` and `supplier_rank`. This is a binary designation, one or the other. The Luxembourg FAIA report requires that less than 30% of \Transaction\Line elements with payable accounts (class 6) can not have \SupplierID. The same applies for \Transaction\Line elements with receivable accounts (class 7) and the \CustomerID element. TSB clarified that any partner on an receivable or payable line should be added to the Customer list or Supplier list respectively https://github.com/odoo/enterprise/pull/100749#issuecomment-3655127511. In addition, I verified that Luxembourg's analysis of four separate FAIA files (from ticket 5427296) aligns with this expectation. <img width="1322" height="690" alt="image" src="https://github.com/user-attachments/assets/1a82f99e-5b32-4dbb-96e1-1b25bab2629b" /> This commit adds partners to the \Supplier and \Customer lists if they have any payable or receivable lines, respectively. It also picks between the \CustomerID and \SupplierID based on a line's `account_type`. This logic is applied to `account_saft` and updates the other, country-specific SAFT reports where appropriate. It also retains the previous `customer_rank` and `supplier_rank` logic as a fallback for older XML reports and for accounts other than `asset_receivable` or `liability_payable`. opw-6118024 Forward-Port-Of: odoo/enterprise#119098 Forward-Port-Of: odoo/enterprise#118714
This update resolves a bug that caused the Asset Depreciation Schedule report to crash when dealing with a large number of assets grouped by account. By adding a safeguard to handle missing data, the report now functions correctly even with significant asset volumes, ensuring accurate reporting for our customers.
Original PR description
#### Description of the issue/feature this PR addresses: Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is…
#### Description of the issue/feature this PR addresses:
Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is active (large number of assets in one account group). The report becomes unusable for affected customers.
#### Current behavior before PR:
_regroup_lines_by_name_prefix sums each subline column by indexing prefix_subline['columns'][i]['no_format'] directly. Empty columns are built as {} by _build_column_dict (both col_value and col_data are None), so they have no 'no_format' key. With a comparison period enabled, an asset that has no value in the comparison period produces an empty column for that period; once prefix grouping fires (len(lines) >= prefix_groups_threshold, default 4000), the direct lookup hits that empty dict and raises KeyError: 'no_format'.
#### Desired behavior after PR is merged:
The prefix group total treats a missing 'no_format' as 0, matching the sibling caller in account_asset/models/account_assets_report.py that already guards with .get('no_format', 0). The report builds without crashing and the empty comparison column contributes 0 to the prefix group total.
opw-6225639
Forward-Port-Of: odoo/enterprise#119775
Forward-Port-Of: odoo/enterprise#119088This update resolves an issue preventing valid vendor bills from being created in the GT accounting system. The system incorrectly restricted document types based on company affiliation. This change now allows all legally valid document types for purchase bills, ensuring accurate record-keeping and compliance.
Original PR description
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to…
Currently, the system restricts fiscal document types for both sales and purchases based on the company’s VAT affiliation, which prevents valid vendor bills from being recorded. **Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT company`. - Navigate to Accounting > Vendors > Bills. - Create a vendor bill. - Try to select a document type such as `FPEQ` or `FCAP`. **Observation:** The system hides valid vendor document types (e.g., `FPEQ`, `FCAP`) if they do not match the company’s VAT affiliation. **Root Cause:** At [1], the method `_compute_l10n_gt_edi_available_doc_types` filters document types using the company’s VAT affiliation (`l10n_gt_edi_vat_affiliation`) for all move types. This logic is correct for sales (where the company is the issuer), but incorrect for purchases (where the vendor determines the document type). As a result, valid purchase document types are wrongly excluded. **Fix:** This commit updates the computation logic to: - Apply affiliation-based filtering only for sales (`out_*`). - Bypass the restriction for purchases (`in_*`), allowing all valid document types. This ensures that vendor bills can include any legally valid document type regardless of the company’s affiliation, while preserving the existing restrictions for sales workflows. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_gt_edi/models/account_move.py#L162-L166 opw-6099863 Forward-Port-Of: odoo/enterprise#113133
The EDI download button was failing to provide the correct XML files when Carvajal encountered an error. This update adds a necessary callback to generate the XML content, ensuring users can now successfully download the required EDI documents for Carvajal integration. This resolves a critical issue preventing proper data transmission.
Original PR description
When Carvajal returns an error, the EDI document is created with the XML attachment correctly stored in attachment_id. However, the Download button in the EDI Documents tab uses the computed field edi_content, which internally looks for an 'edi_content' callback in _get_move_applicability(). Since l10n_co_edi never provided this key, the computed field always returned empty bytes, resulting in an empty file download. Add the edi_content callback pointing to _l10n_co_edi_generate_xml so the Download button serves the actual generated XML. The "Download" button returns an empty file instead of the generated XML sent to Carvajal. <img width="1376" height="765" alt="Captura de pantalla 2026-06-11 a la(s) 12 21 55 p m" src="https://github.com/user-attachments/assets/ac1b6e85-e67d-4021-8d9c-07a03a390245" />
This update resolves an issue where bank statement CSV imports were incorrectly multiplying amounts by 100. This was caused by a double-parsing of debit and credit fields when both the 'extract' and 'import' modules are installed. The fix ensures that imported amounts are parsed correctly, regardless of which modules are used.
Original PR description
Steps to reproduce --- 1. With Accounting installed, import a bank statement CSV that has separate Debit and Credit columns using number separators (e.g. a line with "1.234,56"). 2. Map the columns…
Steps to reproduce --- 1. With Accounting installed, import a bank statement CSV that has separate Debit and Credit columns using number separators (e.g. a line with "1.234,56"). 2. Map the columns to Debit and Credit and import. The imported amounts are multiplied by 100: "1.234,56" is imported as 123,456.00. Issue --- This only happens when both `account_bank_statement_import_csv` and `account_bank_statement_extract` are installed, which is the default in any Accounting database since both modules are auto-installed. `account_bank_statement_extract` turns debit and credit into real Monetary fields on `account.bank.statement.line`: https://github.com/odoo/enterprise/blob/af863c5a53d0ab50fe67cb9ea910391d4a1979dd/account_bank_statement_extract/models/account_bank_statement_line.py#L7-L8 Because they are now real fields, the generic importer already converts those columns to floats: https://github.com/odoo/odoo/blob/bfa39854e56da4bf23295d62f63d66973ad0d78e/addons/base_import/models/base_import.py#L1281-L1285 The CSV statement wizard then parses the same columns a second time: https://github.com/odoo/enterprise/blob/d7ab7ee1287342638006e290ede20b955aae8370/account_bank_statement_import_csv/wizard/account_bank_statement_import_csv.py#L92-L93 The first pass correctly reads "1.234,56" as "1234.56", but the second pass sees a lone dot, mistakes it for the thousands separator, strips it, and produces 123456. The wizard now parses debit and credit only when they are virtual fields, so when they are real fields the values parsed by the generic importer are reused instead of being parsed twice. Without `account_bank_statement_extract`, debit and credit exist only as virtual import fields, so the generic importer skips them and the wizard parses them once. That is why the regression stays hidden until the extract module is present. opw-6227083 ---
This update resolves an issue where attempting to create a new Global Invoice after canceling a refund related to a Mexican POS order would fail. The fix ensures that the refund's CFDI document is correctly updated, allowing for the creation of a new invoice. This prevents a common error and improves the functionality of the Mexican CFDI reporting process.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136 Forward-Port-Of: odoo/enterprise#120100 Forward-Port-Of: odoo/enterprise#117211
2 changes
Resolved issues and error corrections
This update corrects a display issue in the combo configurator where extra prices weren't being converted to the correct currency, leading to inaccurate totals. The fix ensures that prices shown in the configurator match the calculated prices on the sale order line, regardless of the pricelist currency. This improves the accuracy of pricing and order totals for multi-currency sales.
Original PR description
Description of the issue/feature this PR addresses: In the combo configurator dialog, a combo item's extra_price and the price_extra of no_variant attributes are stored in the company/product…
Description of the issue/feature this PR addresses: In the combo configurator dialog, a combo item's extra_price and the price_extra of no_variant attributes are stored in the company/product currency but were sent to the front-end without conversion. When the order uses a pricelist in a different currency, the popup shows these extras at face value (e.g. an extra of USD 1700 appears as ARS 1700 instead of being converted). The sale order line itself already converts these extras, so the popup price and the actual line price didn't match. Current behavior before PR: _get_combo_item_data and _get_selected_ptavs_data return extra_price / price_extra raw, in the company currency. With a foreign-currency pricelist the combo configurator popup adds them 1-to-1 to the already-converted base price, displaying an incorrect total that doesn't match the resulting sale order line. Desired behavior after PR is merged: The controller converts extra_price and price_extra to the configurator's currency (via currency._convert()) before serializing them, so the popup shows the correct amounts in the pricelist currency and matches the price computed on the sale order line. A test (test_sale_combo_multicurrency.py) covers combo extra-price conversion with a foreign-currency pricelist. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a technical issue in the payroll calculation process for employees with contracts exceeding 35 years. The fix adjusts a key parameter to correctly account for Mexican labor law regulations regarding holiday accrual beyond the initial 35-year limit. This ensures accurate payslip generation for all employees.
Original PR description
**Steps to reproduce:** 1. Install l10n_mx_hr_payroll. 2. Create an employee with a contract date over 35 years ago (e.g., 1985). 3. Create a payslip for this employee. 4. Click on "Compute Sheet".…
**Steps to reproduce:**
1. Install l10n_mx_hr_payroll.
2. Create an employee with a contract date over 35 years ago (e.g., 1985).
3. Create a payslip for this employee.
4. Click on "Compute Sheet".
```Error: KeyError(36) while evaluating```
**Cause:**
The rule parameter [rule_parameter_holiday_table](https://github.com/odoo/enterprise/blob/c02c4571bb7db7197b07539ba390d4d20fdce9fe/l10n_mx_hr_payroll/data/hr_rule_parameters_data.xml#L722-L758) defines values
only up to 35 years. Seniority exceeding this range causes a KeyError.
**Solution:**
Extended the `rule_parameter_holiday_2024` table from 35 to 60 years,
following the Mexican Federal Labor Law (LFT) reform formula
(+2 days every 5-year milestone from year 6 onwards).
**NOTE:**(Alternative approach)
```python
@staticmethod
def _get_mx_holiday_days(years_worked):
if years_worked <= 0:
return 0
if years_worked <= 5:
return 12 + (years_worked - 1) * 2
five_year_periods = (years_worked - 6) // 5
return 22 + five_year_periods * 2
```
This approach removes the need for XML data maintenance and handles
all future seniority values mathematically without any cap issues.
opw-60905902 changes
Resolved issues and error corrections
This update optimizes how Odoo retrieves related mailings during mass campaigns, addressing a performance bottleneck. The previous method was slow and resource-intensive, particularly with large campaigns. This change significantly improves the speed and stability of mass mailing operations.
Original PR description
**Description of the issue/feature this PR addresses:** The method _get_ab_testing_siblings_mailings currently scans all mailings in a campaign to apply a simple filter, which becomes expensive on databases with many large mailings. **Steps to reproduce bug:** 1) Run this script to get [enough sufficiently large mailings](https://gist.github.com/brcut-odoo/bb0d6d334bfe110afe16021d17d1b443) 2) Open one of the mailings and recieve a crash from the _get_ab_testing_siblings_mailings **Current behavior before PR** https://drive.google.com/file/d/19xftvzsGSQ9DxB67LNiLkKApzsD192ax/view?usp=drive_link **Current behavior after PR** https://drive.google.com/file/d/1apTJ0rWTKaATYa67ZmmN-7bKhrw4KuTx/view?usp=drive_link opw-6245908
This update significantly speeds up the calculation of future timesheets based on public holidays. The previous process was slow due to repeated timezone conversions, which has now been optimized to only localize times when absolutely necessary. This improves the responsiveness of the system, especially when managing a large number of employees and holiday schedules.
Original PR description
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several years in the future), then it takes excessively long and the action may not complete. **Cause:** The pytz method `localize` and comparing times with non-static timezones is done repeatedly and unnecessarily which becomes costly with more records. **Solution:** Only localize the time when absolutely necessary (determining the date of the leave in the calendar timezone). **Performance Stats:** |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |100 |3.1s |393 |0.8s |117 | |1,000 |22.3s |2,090 |1.5s |183 | |10,000 |Timeout |N/A |6.7s |541 | opw-6087422