Friday, June 12, 2026
28 changes · saas-19.3
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
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 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…
Code cleanup and technical improvements
This update improves the generation of France's fiscal reports by introducing reusable functions and streamlining existing code. Comprehensive test cases have been added to ensure accurate data extraction and XML report formatting for these critical financial documents.
Original PR description
-Created a utils file for france fiscal reports that has the common functions, and refactored some parts of the code in the report handlers. -Created test cases for adding and removing lines from a report, extracting the data, and exporting the report as xml for the france localization fiscal report. task-6138193
#### 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
This update fixes an issue where currency differences were incorrectly aggregated in hierarchical financial reports. Previously, the system was combining figures from different currencies, leading to inaccurate totals. This change ensures that reports accurately reflect the value of transactions in their original currency, improving reporting reliability.
Original PR description
opw-6015098 Forward-Port-Of: odoo/enterprise#119311 Forward-Port-Of: odoo/enterprise#114827
This update resolves an issue where canceling a Global Invoice on a Mexican POS order prevented the creation of a new Global Invoice for the same order. The fix ensures that the refund process correctly updates CFDI documents, allowing users to generate new invoices after a refund is processed. This improves the functionality of the Mexican POS integration.
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#120349 Forward-Port-Of: odoo/enterprise#117211
This update ensures Polish company invoices sent to KSeF (a Polish tax system) correctly include a required field ('PrefiksPodatnika') in the FA(3) XML format. This is necessary for legal compliance with Polish tax regulations for common EU transactions like intra-Community sales and triangular sales, ensuring accurate reporting to the tax authorities.
Original PR description
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed…
Steps to reproduce 1. Configure a Polish company with KSeF enabled. 2. Create a customer invoice using a tax tagged with K_21 (0% EU G, intra-Community supply of goods), K_12 (0% EU S, services taxed in the buyer's EU country) or Triangular Sale. 3. Send the invoice to KSeF and download the generated FA(3) XML. Issue The Podmiot1 (seller) block in the rendered FA(3) XML omits the PrefiksPodatnika element, see https://github.com/odoo/odoo/blob/89219a843545d8bb0cad6ea806a1167cee6289da/addons/l10n_pl_edi/data/fa3_template.xml#L34-L42. According to the official Ministry of Finance documentation (https://ksef.podatki.gov.pl/media/4u1bmhx4/information-sheet-on-the-fa-3-logical-structure.pdf, page 11), this conditional field must carry the value "PL" when the invoice documents: - the intra-Community supply of goods, - the provision of services referred to in Article 100 sec. 1 item 1 of the Act for EU VAT taxpayers, - the supply carried out under a simplified triangular transaction by the second taxpayer (Article 135 sec. 1 item 4 (b) and (c)). The XSD marks the element as optional (minOccurs="0", fixed="PL") so KSeF accepts the XML, but the seller's tax reporting is still legally non-compliant for the three cases above, and the field is missing from the KSeF PDF viewer rendering. opw-6213178 Forward-Port-Of: odoo/odoo#264659
This update ensures accurate calculation of variable double holiday pay for employees in Belgium. Previously, the system wasn't properly prorating holiday pay based on legal leave entitlements, leading to potential payment discrepancies. This fix corrects this issue, ensuring compliance and accurate payroll processing.
Original PR description
If you have a double holiday attest, we need to prorate the amount based on legal leave rights. The proration with regards to the previous work time rate wasn't done. Forward-Port-Of: odoo/enterprise#120403
This update fixes an error in the Colombian DIAN module that incorrectly flagged invoices due to timezone differences. The change ensures invoice dates are validated accurately using Bogota local time, preventing reporting issues with DIAN. This improves compliance and data accuracy for Colombian businesses.
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#120384 Forward-Port-Of: odoo/enterprise#115256
This update resolves an issue where account reassignments (moving accounts between companies) caused errors during chart of accounts reloading. The fix ensures that the system correctly identifies if an account is still associated with the target company, preventing errors and ensuring accurate account data is loaded.
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#269696
Forward-Port-Of: odoo/odoo#269291