Tuesday, September 15, 2026
23 changes · 19.0
Enhancements to existing features
French partner records now automatically recheck and update their electronic invoicing address and identifier using official directory or Peppol data where possible. When several possible identifiers are found, users are guided to choose the right one, helping reduce invoicing setup errors.
Original PR description
for existing french partners that dont have their EAS set to the FRCTC, a check will be made to see if they are on the annuaire using the IAP annuaire lines, if one line exists, the identifier is set to that, if more than one line exists, there is no way for us to know which one belongs to that partner, so we prompt the user to go to the partner's settings and choose the correct identifier, if they are not on the annuaire but on peppol, we set the EAS and identiifer to the correct correspoding value found on peppol, if all cases fail, we default to the FRCTC EAS and their SIRET as the identifier. task-id-6327357 Forward-Port-Of: odoo/odoo#278593
Peppol document errors are now shown as separate, readable items instead of one technical line. This helps users understand what went wrong and what action may be needed when electronic invoices or documents fail validation.
Original PR description
Before this commit, Peppol error messages (e.g. Schematron errors) were logged in the chatter as a single unformatted line and without any humanization. The errors were too technical and the user could not easily know what action to take. This PR splits the raw error payload into individual entries, maps known error codes to human-readable explanations, and renders them as an HTML list in the chatter. task-6144909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280261 Forward-Port-Of: odoo/odoo#265253
Resolved issues and error corrections
This fix ensures manufactured products are placed in the correct storage location after components are unreserved and re-reserved. It prevents inventory from being stored in the wrong place when putaway rules are configured, improving warehouse accuracy.
Original PR description
Currently, when the user re-reserves a component and produces an MO for a lot-tracked product, putaway rules stop working. ## Steps to produce: - Install the Manufacturing application. - Go to…
Currently, when the user re-reserves a component and produces an MO for a lot-tracked product, putaway rules stop working. ## Steps to produce: - Install the Manufacturing application. - Go to Settings and enable Lots & Serial Numbers and Storage Locations. - Create a product named 'Laptop' and set it to be tracked by Lots. - Create a product named 'Graphics card' with some quantity on hand. - Create a Bill of Materials (BoM) for the Laptop with Graphics card as a component. - Create a location named 'Laptop Shelf' with 'WH/Stock' as its parent location. - Create a putaway rule: - When a product arrives in: WH/Stock - Product: Laptop - Store to: WH/Stock/Laptop Shelf - Create and confirm a Manufacturing Order (MO) for the Laptop. - Unreserve the components, open Details, and re-add the Graphics card. - Click Produce All and check the on-hand quantity list view of the Laptop. ## Issue: The Laptop is stored in WH/Stock instead of WH/Stock/Laptop Shelf. ## Root cause: When the user presses the unreserve button the finished move is passed to `_do_unreserve` https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/mrp/models/mrp_production.py#L2407 which unlinks all the move lines on finished product moves if they are not picked: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/stock/models/stock_move.py#L1043 Now when the user presses the Produce All button, `button_mark_done` is called, which calls `_post_inventory` at: https://github.com/odoo/odoo/blob/a51ca77c825d2dba326dd540e2b4c04ef6c2385d/addons/mrp/models/mrp_production.py#L2236 `_post_inventory` assigns `lot_ids` to the finished product moves at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/mrp/models/mrp_production.py#L1928-L1930 This calls `_set_lot_ids` which creates a move line with quantity 1 at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/stock/models/stock_move.py#L679-L683 After that, `_post_inventory` sets the quantity for the finished product moves at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/mrp/models/mrp_production.py#L1935 Which calls `_set_quantity` and the delta quantity is now zero at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/stock/models/stock_move.py#L477-L483 Because `_set_lot_ids` has already created a move line that satisfies the move quantity, `_process_increase` is not called. Since `_process_increase` is not called, `_set_quantity_done` is never called at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/stock/models/stock_move.py#L463-L465 Since `_set_quantity_done` is not called, `_apply_putaway_strategy` is never called within that function at: https://github.com/odoo/odoo/blob/157874aad3aebef5bc9268de6e17530641107e31/addons/stock/models/stock_move.py#L2565 As a result, the laptop ends up in stock instead of on the shelf. This issue did not occur in lower versions because the feature to produce multiple lots was introduced in version 19.0 by the following commit: https://github.com/odoo/odoo/commit/4bb4e08066449177f89382718ceadd840ce90d0e Before this commit, only `_set_quantity` was called. Since no move line was created because lot_ids were not set in `_post_inventory`, `_process_increase` was called, which then called `_apply_putaway_strategy`, so the putaway rules were applied correctly. ## Solution: Apply putaway rules in the post-inventory function after the user manufactures a product, ensuring the items are placed in the correct locations and preventing products from being misplaced even when putaway rules are defined. opw-6517324
Creating a new website now continues smoothly even if the external website configuration service cannot be reached. This prevents users from being blocked at the color palette step and improves reliability during website setup.
Original PR description
bug: configurator_missing_industry raised an uncaught RPC_ERROR when the IAP website API was unreachable, breaking the color palette step of the website configurator. steps: - Go in settings and set in the system parameters `website.website_api_endpoint` to anything that won't work - Create a new website - Traceback at the palette step fix: Wrap the IAP calls in a try/except for AccessError. task-6325919
Automation rules that trigger when a field reaches a value now avoid running twice during record creation when that field is filled automatically. This prevents duplicate emails, activities, and similar actions, improving reliability for workflows such as CRM lead creation from website forms.
Original PR description
An automation rule triggered when a field reaches a specific value can run its actions twice when a record is created without that field provided explicitly. For example, a rule that sends one email…
An automation rule triggered when a field reaches a specific value can run its actions twice when a record is created without that field provided explicitly. For example, a rule that sends one email and schedules two activities can send two emails and schedule four activities for one record. ### Reproduction Steps Create an automation on `crm.lead` that triggers when the stage is set to "New", with one email action and one activity action. Create an opportunity through the website contact form, which leaves the stage unset. The lead is assigned to the "New" stage, but both actions run twice. ### Cause The lead stage is computed and read during creation. That computation can trigger the automation before the creation hook processes the same record, causing both paths to run the actions. The processing code tracks records already handled during nested computations. The feedback flag used for this tracking is attached to the records, but the code checked the automation context instead. When the computation was triggered during creation, the flag was therefore missed. ### Fix Read the feedback flag from the records so nested computations update the shared tracking state. The creation hook then skips records already processed by the computation. opw-6331134
Australian payroll users can now register superannuation payments from a pay run regardless of how they opened the record. This prevents an error that occurred when using the Pay Runs kanban view, helping payroll teams complete super payment processing reliably.
Original PR description
Current behavior: -- Registering a super payment from a pay run opened out of the Pay Runs kanban fails with "Wrong value for account.payment.state. The same super contribution registers without…
Current behavior: -- Registering a super payment from a pay run opened out of the Pay Runs kanban fails with "Wrong value for account.payment.state. The same super contribution registers without error when opened from Payroll > Reporting > Australia > Super Contributions. Expected behavior: -- Register Super Payment should work regardless of how the super contribution record was reached. Steps to reproduce: -- - Take an Australian pay run through to Paid - Open Payroll > Payslips > Pay Runs, kanban grouped by Status (default) - Open the pay run from the Paid column, then Super Submissions - Lock the super contribution and click Register Super Payment Cause of the issue: -- The Pay Runs kanban is grouped by state, so the web client adds default_state to the context of records opened from a column. That context follows the smart button into action_register_super_payment, where account.payment is created without an explicit state. The ORM applies default_state from the context which is a hr.payslip.run value that account.payment.state does not accept. The same leak reaches account.move through action_post, which creates the payment journal entry. Fix: -- apply with_context(clean_context(self.env.context)) to the recordset to remove the default_state key opw-6478084
The Mexican DIOT tax report no longer uses the “Load More” pagination that could repeat partner lines when report data overlapped. This prevents duplicate entries and helps users view the report reliably.
Original PR description
Account reports can use "Load More" to paginate the lines generated when expanding a groupby. A report line can contain several expressions, which may return overlapping grouping keys. Problem: The…
Account reports can use "Load More" to paginate the lines generated when expanding a groupby. A report line can contain several expressions, which may return overlapping grouping keys. Problem: The limit and offset are applied while computing each expression, before their results are aggregated by grouping key. As a result, a grouping key from a previous page can be returned again by the next "Load More" request. This results in duplicate report lines. In 17.0, this causes an Owl error because `line.id` is used as the key when rendering the lines, and the lines can’t be viewed. The DIOT report is affected because it contains multiple expressions whose grouping keys can overlap. Solution: Disable "Load More" on the DIOT report by removing its pagination limit. Example steps to reproduce: 1. Create or switch to a Mexican company and install `l10n_mx_reports` so the DIOT report is available. 2. Create a partner and 100 posted journal entries for that partner in the same period. Add the `+DIOT: 16%` tag to all 100 account move lines and the `-DIOT: Retención` tag to the first 90. 3. Open Accounting > Reporting > Tax Reports > DIOT. 4. Unfold the partner and click "Load More". Related ticket: opw-6471063 Forward-Port-Of: odoo/odoo#287833
This fix ensures timesheets are matched to the correct invoice when different sales orders are invoiced together. It prevents one subscription's billing period from incorrectly limiting another order's timesheets, reducing the risk of incomplete invoice records.
Original PR description
### Steps to reproduce: - Install `sale_subscription_timesheet` module - Create a subscription (Order A) with delivered-timesheet products and log timesheets within its current period (e.g., January)…
### Steps to reproduce: - Install `sale_subscription_timesheet` module - Create a subscription (Order A) with delivered-timesheet products and log timesheets within its current period (e.g., January) - Create a standard order (Order B) with delivered-timesheet products and log timesheets outside of Order A's period (e.g., March) - Select both orders and invoice them simultaneously in a single batch (uncheck 'Consolidated Billing') > Result: Order B's invoice is created but silently fails to link its March timesheets, because they fall outside Order A's January window. ### Cause of Issue: In `_link_timesheets_to_invoice`, the `start_date` and `end_date` parameters are overwritten inside the invoice line loop when `_get_range_dates` is called. Because these variables are never reset per iteration, the first order that yields a date range locks in that window for every subsequent invoice line in the batch. Timesheets outside this leaked window are silently ignored. Additionally, the `_get_range_dates` hook is invoked before verifying if the invoice line actually contains timesheet products, causing it to execute on empty recordsets (e.g. invoice line notes) ### Fix: Prevent the date range leak by preserving the original parameter state of the dates and safely ensure the extension hook is never invoked with an empty recordset. opw-6507110 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284781
Vendor bill auto-completion no longer replaces a manually chosen recipient bank account when the bill currency has not actually changed. This prevents accidental payment details changes for vendors with multiple bank accounts.
Original PR description
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ###…
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ### Cause: When `invoice_vendor_bill_id` is set, an onchange assigns `currency_id` unconditionally, even when it is the same value This triggers `_compute_partner_bank_id`, which always recomputes the best matching bank account from scratch without considering the currently set value If the currency did not change, this recompute is unnecessary and silently overrides the manual selection ### Steps to reproduce: - Install `account` - Create a Vendor with 2 bank accounts (keep default values to have equal priority on all accounts) - Create and post a Bill for this vendor with at least one line - Create a new Bill for the same vendor - Set the Recipient Bank to the second account in the list - In Auto-Complete, select the first Bill Before the fix, the Recipient Bank is reset to the first account opw-6210414
Salespeople now receive the expected upsell warning when several smaller timesheet entries together exceed the prepaid service threshold. This helps teams spot extra billable work reliably, even when hours are recorded incrementally rather than all at once.
Original PR description
Steps to reproduce: -------------------------------------------- 1. Install `sale_timesheet` module 2. Create a product with: * Type: Service * Invoicing Policy: Prepaid/Fixed Price * Create on…
Steps to reproduce:
--------------------------------------------
1. Install `sale_timesheet` module
2. Create a product with:
* Type: Service
* Invoicing Policy: Prepaid/Fixed Price
* Create on Order: Project & Task
* Upsell Threshold: Set some value (e,g. 600%)
3. Create and confirm the sale order with that product
4. Create and confirm an invoice for the sale order
5. From Recorder Hours Smart button:
* Add two timesheets for hours 3 & 4 (Combined h > Threshold Percentage/100)
Observation:
--------------------------------------------
* When adding a single 7h timesheet, an upsell warning activity is correctly created for the salesperson in the chatter.
* When adding multiple incremental timesheets whose combined duration exceeds the threshold, no upsell warning activity is created.
Issue:
--------------------------------------------
* The `_compute_field_value` method filters on `invoice_status != 'upselling'` before recomputing the new invoice status.
* After the first incremental timesheet is added, the sales order already has the upselling status from the previous computation.
* As a result, subsequent computations skip the upsell activity logic, even though `has_displayed_warning_upsell` is still `False` and no warning activity has yet been created.
Solution:
--------------------------------------------
* Removes the `so.invoice_status != 'upselling'` condition from the filter.
* The order-level `invoice_status` was never the right place to control upsell activity creation. An order can have `invoice_status == 'upselling'` for various reasons (delivered > invoiced), but that doesn't mean all lines have already triggered their upsell warnings.
opw-6117754
Forward-Port-Of: odoo/odoo#287468
Forward-Port-Of: odoo/odoo#266275Fixed a rounding issue where settled sales orders in Point of Sale could show a down payment one cent too low and the remaining balance one cent too high. This ensures customers and staff see the correct totals when applying and settling fixed down payments with tax included.
Original PR description
Steps to reproduce: ------------------- 1. Create a product at $1000 with a 20% tax-included tax. 2. Create and confirm a sale order with that product. 3. In POS, open Quotation/Order, select the…
Steps to reproduce: ------------------- 1. Create a product at $1000 with a 20% tax-included tax. 2. Create and confirm a sale order with that product. 3. In POS, open Quotation/Order, select the order, apply a $500 fixed downpayment, and pay. 4. Go back to Quotation/Order, select the same order, and settle. The downpayment line shows -$499.99 instead of -$500.00, and the remaining total is $500.01 instead of $500.00. What's happening: ----------------- The accounting tax engine adjusts `price_unit` by a rounding delta during `reduce_base_lines_to_target_amount` (500 → 499.99) and stores the proportionally correct amounts in `extra_tax_data` (ETD): base=416.66, tax=83.34, total=500.00. During DP creation in POS, ETD is exported to the POS line and successfully imported by `import_base_line_extra_tax_data`, so the total displays correctly as $500.00. However, when settling, `settleSO` doesn't carry over `extra_tax_data` to the new POS line it creates, so the rounding correction is lost and the line total falls back to the raw price_unit of 499.99. The fix: -------- Reconstruct `price_unit` from the SO line's ETD manual amounts (base_excluded + sum of tax amounts) before calling `setUnitPrice`, so the correct total is restored. opw-5480626
Fixes product carousel scrolling issues on right-to-left language websites, such as Arabic. This prevents empty spaces and image distortion when visitors browse carousel items, improving the storefront experience.
Original PR description
**Description of the issue/feature this PR addresses:** When a dynamic product carousel is set to single-image scrolling mode in an RTL language (e.g., Arabic), sliding between items behaves…
**Description of the issue/feature this PR addresses:**
When a dynamic product carousel is set to single-image scrolling mode in an RTL language (e.g., Arabic), sliding between items behaves inconsistently, resulting in empty spots or temporarily distorted images.
This occurs because the DOM manipulation creating the infinite scroll was coded for LTR physical movements. In LTR, the first DOM element is visually on the left. In RTL, the visual layout is mirrored, with the first DOM element visually on the right. When we then trigger a "left" slide in RTL, the LTR-based JavaScript doesn't appropriately move the last element to the first index prior to the animation, resulting in an empty gap, among other issues.
This commit resolves the issue by checking the document's text direction. By swapping the target direction ("left" or "right") in onSlideSingleScroll and onSlidSingleScroll when RTL is active, the underlying array operations now correctly align with the animation.
**Steps to reproduce:**
- Website > Edit > add Product Carousel > Customize > change Scrolling Mode to Single
- Website > Edit > Theme > Website > Language > change to Arabic
- Click the arrows in the product carousel > observe inconsistent scrolling with visual glitches
**Current behavior before PR:**
- Visual glitches when sliding carousels in single-image scrolling mode for RTL languages
**Desired behavior after PR is merged:**
- No visual glitches when sliding carousels in single-image scrolling mode for RTL languages
opw-6490277Employee-paid expenses will now remain included in the Waiting Reimbursement dashboard total and filter after their accounting entry is posted. This prevents unreimbursed expenses from temporarily disappearing, giving employees and managers a more accurate view of outstanding reimbursements.
Original PR description
#### Description of the issue/feature this PR addresses: The "Waiting Reimbursement" tile stops counting an employee-paid expense once its journal entry is posted, instead of once the employee is reimbursed. #### Current behavior before PR: _compute_state sets the state to 'posted' as soon as a move is posted and unpaid, so an own_account expense never stays 'approved', yet get_expense_dashboard still totals the tile on 'approved' only. Regression from the removal of hr.expense.sheet in 704a5a1, which carried the 'posted' state until then. The "Waiting Reimbursement" search filter has the same condition. #### Desired behavior after PR is merged: The tile and the filter also match 'posted', so the expense stays counted until the payment is registered. opw-6410953 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Flexible attendance reports now cap expected weekly hours at the employee's contracted weekly schedule. This prevents reports from overstating expected hours when someone works more days than planned, giving managers more accurate attendance and overtime figures.
Original PR description
Issue: - When the attendance is flexible, the weekly expected hours shown in reports are incorrect. - This happens because the calculation is based only on the `Average Hour per Day` and doesn't take…
Issue:
- When the attendance is flexible, the weekly expected hours shown in reports are incorrect.
- This happens because the calculation is based only on the `Average Hour per Day` and doesn't take into account the `Hours per Week` set on the employee resource. It ignores the weekly limit defined in the employee's working schedule. -As a result, if an employee works more days than expected, the report may show more than the allowed weekly hours.
Example:
- An employee has a 32h/week contract and 8h/day.
- If they work 5 days, the system still counts 8h as expected for each day — totaling 40h instead of 32h.
Steps To reporduce:
- Set up a flexible contract with 32 hours/week (8 hours/day) for an employee.
- Log 5 attendances in one week with 8 worked hours each.
- Go to report and filter by employee by week, notice the current behavior yields 5 x 8 = 40 hours in expected_hours.
Solution:
- Check the weekly hours cap defined in `resource_calendar_id.full_time_required_hours`.
- If total `expected_hours` from earlier attendances this week exceeds that limit, set expected_hours = 0 for any excess.
OPW-4583064
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274805
Forward-Port-Of: odoo/odoo#218384Generated serial and lot numbers on receipts now automatically receive the correct expiration date based on the product's configured shelf-life settings. This prevents missing expiry information during receiving while preserving any expiration dates users provide manually or through imports.
Original PR description
**Issue** The expiration date is left blank when generating serial/lot numbers on a sml in a receipt, instead of being set from the product's default expiration settings. **Steps to reproduce** -…
**Issue** The expiration date is left blank when generating serial/lot numbers on a sml in a receipt, instead of being set from the product's default expiration settings. **Steps to reproduce** - Create a product tracked by SN, with Inventory > Traceability > Expiration Date enabled and an expiration time set. - Create and confirm a PO for that product. - Go to the receipt, open the Detailed Operations popup, and use "Generate Serials/Lots". -> The expiration date is not set on the generated serial/lot. **Cause** While generating the serial number, `action_generate_lot_line_vals` is called: https://github.com/odoo/odoo/blob/5d5f5381c27f67a8655a1c18bf1802c877d4cae2/addons/stock/models/stock_move.py#L1008 But it makes no reference to `expiration_date`. Moreover, it does not call `_compute_expiration_date` yet, before the save is performed: https://github.com/odoo/odoo/blob/5d5f5381c27f67a8655a1c18bf1802c877d4cae2/addons/product_expiry/models/stock_move_line.py#L38-L40 **Solution** Backport the fix from 19.0: https://github.com/odoo/odoo/commit/4f339301179c93a8bd48c55e3c54923c4698861a together with its follow-up, which avoids overwriting an expiration date already provided by a pasted import: https://github.com/odoo/odoo/commit/d0e0785c2fe63b6b7984432f5d0cdd73d4ca72ef opw-6417108 Forward-Port-Of: odoo/odoo#287225 Forward-Port-Of: odoo/odoo#284469
This fixes an issue where designated HR responsible users could see certain leave requests but could not approve or refuse them. The change ensures the right approver has access and can complete approvals from both the Time Off management views and calendar overview.
Original PR description
Steps to reproduce: ---------------------------------------- - Have a Time Off Type with approval "By Time Off Officer" - Have two users with employees and without any rights on Employee or Time Off…
Steps to reproduce: ---------------------------------------- - Have a Time Off Type with approval "By Time Off Officer" - Have two users with employees and without any rights on Employee or Time Off - Set the second user as time off approver and Hr responsible on the first one - As the first user create a Leave request with the thime off type of the first step **First issue:** - As the second user, open Time Off > Management > Time Off - The request appear in "Waiting For Me" but we cannot approve it, the buttons aren't there - Same on the form view **Second issue:** - As the second user, open Time Off > Overview - Remove the "My Team" filter to see the leave request - Click on it, then click "Approve" - `Validation Error: You are not allowed to approve this leave request.` Cause: ---------------------------------------- **First issue:** The field `can_approve` is computed through `_check_approval_update()` which calls `_get_next_states_by_state()` to see which states are accessible. In the `if` section of `is_time_off_manager` we prevent the 'hr' validated time off type leaves from being refused and validated. So only Time Off officers can approve or refuse them. **Second issue:** `action_approve()` in `HrLeaveReportCalendar` prevents the aprobation if `leave_validation_type` is not `manager` or `both`. Solution: ---------------------------------------- **First issue:** We also add the possible state `validate` and `refuse` for `hr` validated time off type leaves if the current user is the HR responsible of the employee on the leave. **Second issue:** Also allow `hr` for `leave_validation_type` in `action_approve()` in `HrLeaveReportCalendar`. To make it work, we also add a condition on `employee_id.hr_responsible_id.user_id` in the record rules allowing the HR responsible to see the leaves. opw-6545508
Saving a quotation immediately after rearranging its order lines could sometimes fail. This fix pauses saving while line reordering is still being processed, helping sales users avoid errors and keep their changes reliably.
Original PR description
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has…
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has multiple sale order lines 3. Reorder a sale order line and immediately save (there's more chance to reproduce if you have a lot of sol and if you use the shortcut `ALT + S`) 4. An error is thrown Issue: It is possible that the save takes place during the execution of super.sortDrop. This reassigns the id of all the records in this.props.list.records Therefore, calling `_handleQuantityAdjustment` with the recordMap computed before the save uses an id that has disappeard from this.props.list.records so we cannot find it at https://github.com/odoo/odoo/blob/4973903252865a6a7a2da235bc3a01675dbbff4d/addons/sale_management/static/src/fields/sale_order_line_field/sale_order_line_field.js#L263 which eventually throws an error Solution: Suspend any save mechanism when sortDrop starts and resume it when sortDrop has finished opw-6483206
Invoices for customers in the Canary Islands, Ceuta, or Melilla are now reported with the correct special tax regime code instead of a generic one. This improves compliance for Spanish electronic invoice reporting through SII and VeriFactu.
Original PR description
… key 8 When the customer is located in Canary Islands, Ceuta or Melilla, the invoice falls under a different tax territory and the ClaveRegimenEspecialOTrascendencia should be 08. Add the regime key 08 to the clave_regimen_selection in verifactu Previously this case was not checked and invoices were reported with the generic refime code. The regime key 08 is not available in verifactu. task-6372837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279435
This fix prevents the Pay on Site payment option from being automatically re-enabled when the website sale collection module is upgraded. Merchants who disabled this option will no longer have customers offered an unintended unpaid checkout choice after routine app or dependency updates.
Original PR description
Steps to reproduce: =================== 1. Go to the payment providers and set "Pay on Site" to disabled. 2. Go to Apps, clear the filter, look up "website_sale_collect" and upgrade it. This also…
Steps to reproduce:
===================
1. Go to the payment providers and set "Pay on Site" to disabled.
2. Go to Apps, clear the filter, look up "website_sale_collect" and upgrade it. This also happens on its own, as upgrading any custom module that depends on it upgrades it too.
3. Go back to the payment providers.
=> "Pay on Site" is enabled again, and published as well from 19.0 on. Customers are offered it at checkout and place orders that are never paid, without the merchant ever enabling anything.
Root cause:
===========
`data/payment_provider_data.xml` is loaded in update mode because it carries no `noupdate`, and it hardcodes the state of the provider:
<field name="state">enabled</field>
So every upgrade of the module writes that value back over whatever the merchant configured. Every other provider ships its data with `noupdate="1"` and leaves the state alone, this module is the exception.
The file has been loaded this way since the module was added:
- [1] created the module with an updatable provider record.
Fix:
====
Load the file with `noupdate="1"`. The record is still created, enabled, when the module is installed, it is simply not written again on later upgrades. The flag is read from the file rather than from the `ir.model.data` row, so databases where the provider already exists are covered on their next upgrade, no data migration needed.
[1]: 087c48c4ed2e
opw-6528110
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#286913Instagram posts now allow more time to complete when Instagram retrieves images from Odoo servers. This reduces failed posts caused by timeout issues on some hosted databases, improving reliability for social media publishing.
Original PR description
Bug === On some database on the saas, timeout issue happen for Instagram. Because Instagram downloads the image on our server, it needs more timeout than other social media. Task-6547753 Forward-Port-Of: odoo/enterprise#131069
Point of Sale now correctly allows valid product option selections even when related archived variants exist. This prevents customers or cashiers from being blocked from selling available product combinations because of archived records.
Original PR description
Steps to reproduce -------------------- - Install point_of_sale module; - Create a new product available in PoS; - Add a variant attribute with three values; - Modify one of the variants to use a…
Steps to reproduce -------------------- - Install point_of_sale module; - Create a new product available in PoS; - Add a variant attribute with three values; - Modify one of the variants to use a second value (add one of the two other values to product_template_variant_value_ids); - Archive this variant; - Open a PoS session where the product is available; - Select the new product; - You cannot select the two values added on the archived variant (error message: This option or combination of options is not available). Why is it happening -------------------- In the _isArchivedCombination function, we iterate over all the archived combinations for the product and create a sub-combination containing the values shared with the currently selected combination. If the sub-combination has the same length as the currently selected combination, it is considered archived. As a result, if the selected combination is a sub-combination of an archived one, it will be considered archived. opw-6413713 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Argentina electronic export invoices now send quantities using the configured product unit precision, up to the limit accepted by ARCA. This prevents valid invoices with small decimal quantities from being rejected because totals no longer match ARCA's recalculation.
Original PR description
### Problem `_get_line_details` (used by WSFEX and WSBFE) truncates `Pro_qty` with the precision of the `Product Unit of Measure` decimal precision: ```python uom_precision_digits =…
### Problem
`_get_line_details` (used by WSFEX and WSBFE) truncates `Pro_qty` with the precision of the `Product Unit of Measure` decimal precision:
```python
uom_precision_digits = min(self.env['decimal.precision'].precision_get('Product Unit of Measure'), 2)
```
That record no longer exists in 19.0. It was renamed to `Product Unit` (same xmlid `uom.decimal_product_uom`, moved from `product/data/product_data.xml` to `uom/data/uom_data.xml`), so `precision_get` does not find it and returns its hardcoded fallback of 2. Every quantity is sent to ARCA with two decimals, whatever the database has configured.
`Pro_total_item` is built from that same quantity without the truncation, so a line whose quantity has more than two decimals makes ARCA's own check fail:
```
1815: Campo Cmp.Items.Pro_total_item invalido. El valor no es igual a Pro_qty * Pro_precio_uni - Pro_bonificacion.
```
### Evidence
Same database and same kind of export invoice, before and after upgrading to 19.0. The database has its quantity precision set to 3 digits and the invoice lines have `quantity = 0.042`.
Accepted, before the upgrade:
```xml
<Pro_qty>0.042</Pro_qty>
<Pro_precio_uni>62100.0</Pro_precio_uni>
<Pro_bonificacion>0.0</Pro_bonificacion>
<Pro_total_item>2608.20</Pro_total_item>
```
Rejected with 1815, after the upgrade:
```xml
<Pro_qty>0.04</Pro_qty>
<Pro_precio_uni>110500.000</Pro_precio_uni>
<Pro_bonificacion>0.00</Pro_bonificacion>
<Pro_total_item>4641.00</Pro_total_item>
```
ARCA computes `0.04 * 110500 = 4420.00` against the declared `4641.00`.
### Fix
Ask for the decimal precision by its current name, and cap the quantity at 6 decimals, which is the limit the WSFEX specification gives for this field (*Manual para el desarrollador* v3.1.1, page 15).
<img width="691" height="298" alt="qty" src="https://github.com/user-attachments/assets/d6ea6cce-9e7b-49be-a546-bde24b2cd705" />
https://www.afip.gob.ar/ws/documentacion/manuales/WSFEX-Manualparaeldesarrollador_V3.1.1_ARCA.pdf
The cap cannot be lower than the precision of the `quantity` field itself: `Pro_total_item` is derived from that same quantity, so truncating below it can only break the identity ARCA validates.
### Notes
- The truncation was introduced by #106509 and forward-ported here through #110218. The reported problem there was the unit price; the quantity was included along with it.
- 18.0 is not affected by the rename, since the record is still named `Product Unit of Measure` there. It does carry the same `min(..., 2)` cap, so a database with a quantity precision of 3 hits the same rejection. Not covered by this PR.
### Test plan
- The WSFEX and WSBFE test files are unchanged: `Product Unit` ships with 2 digits, so `min(2, 6)` keeps the payload identical for them.
- On a database with the quantity precision set to 3, an export invoice line with `quantity = 0.042` is sent as `0.042` and is accepted.Rental orders can now be created successfully when optional rental products are involved, even if the website rental add-on is not installed. The system now handles rental dates consistently before pricing is calculated, preventing errors and keeping the sales process smooth.
Original PR description
Problem: When the website_sale_renting module is uninstalled and you try to create a rental order with a product that has an optional rental product, the system crashes with a traceback. This happens…
Problem: When the website_sale_renting module is uninstalled and you try to create a rental order with a product that has an optional rental product, the system crashes with a traceback. This happens because the rental start and end dates are passed to the product pricing calculations as plain text strings instead of proper date formats, which breaks the timezone math. Solution: This commit ensures that the rental start and end dates are converted into proper datetime formats before any duration or pricing calculations occur, preventing the error and allowing the products to be added to the rental order smoothly. Steps to reproduce(runbot v18): 1. Install the Rental (sale_renting) and Website modules. 2. Uninstall the website_sale_renting module. 3. Create a rental product and configure another rental product as its optional product. 4. Open the Rental application and try to add the created product to a rental order. 5. A traceback is raised while calculating the rental price. opw-6485776 Forward-Port-Of: odoo/enterprise#130071 Forward-Port-Of: odoo/enterprise#128668