Daily updates from Odoo
Thursday, August 13, 2026
49 changes
8 changes
Resolved issues and error corrections
This fix prevents small rounding differences from creating unbalanced journal entries when account transfer rules send less than 100% to a destination. Businesses using automated transfers can now rely on the generated accounting entries to balance correctly, avoiding one-cent posting errors.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
The payroll validation button now correctly opens any needed follow-up prompt, such as a wizard to complete missing employee information. This prevents users from clicking Validate and seeing no response when additional data is required.
Original PR description
action_validate() called action_payslip_done() without returning its result. When action_payslip_done() returns a client action (e.g. a wizard to fix missing employee data instead of raising), that action was lost and the Validate button appeared to do nothing, with no error or warning shown. task-6373549
Customers can now use Order Again for rental products even when their cart already has a rental period. The cart reuses the existing rental dates, preventing a false conflict that previously stopped the item from being added.
Original PR description
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview…
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview and click `Order Again`. - In the cart, modify the rental period. - Go to My Account > Your Orders, open the sales order, and click `Order Again` again. Issue: --- - Clicking Order Again a second time does nothing and - The following error is logged in the terminal: `You cannot mix different rental periods in the same order.` Root cause: --- - When the user clicks `Order Again`, the `/my/orders/reorder` route calls `add_to_cart`[1], which in turn invokes `_cart_add`[2]. If no rental dates are provided, `_cart_add` computes default rental dates based on the product's rental periodicity [3]. - However, when the current cart already has a rental period set, these computed dates differ from the cart's existing rental period. As a result, the rental consistency check detects the mismatch and prevents the product from being added to the cart. Solution: --- - When the current sale order already has a rental period set, reuse those dates instead of computing default ones. This ensures the product is added using the existing cart rental period and avoids the false conflict. [1]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/reorder.py#L63-L76 [2]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/cart.py#L134-L141 [3]: https://github.com/odoo/enterprise/blob/a39da12a4a85d749235d59a05ebd67b91f9867b0/website_sale_renting/models/sale_order.py#L60-L64 opw-6357001 ---
VoIP contact searches now recognize phone numbers even when the user's input includes an automatic country code and the saved contact number is stored differently. This makes keypad suggestions and contact tab searches more reliable, while showing a readable formatted phone number to users.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6290760 compr https://github.com/odoo/odoo/pull/278018 Forward-Port-Of: odoo/enterprise#127466 Forward-Port-Of: odoo/enterprise#124797
Australian payroll now correctly includes each employee's unused leave when payslips are processed together. This prevents leave payouts or balances from being skipped in multi-employee payroll runs.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
Accounting users can now export Spanish VAT record books that include Point of Sale data without needing separate POS access. This prevents access errors during tax reporting while still using POS information only internally to build the report.
Original PR description
Steps to reproduce:
- With an ES Company
- Open a POS session, add product with tax and pay
- As a user with only accounting access
- Go to Accouting > Reporting > Tax report
- Select Generic Tax report
- Print "VAT record Books"
Issue:
An AccessError will raise
```
Access Error
You are not allowed to access 'Point of Sale Session' (pos.session) records.
This operation is allowed for the following groups:
- Point of Sale/User
Contact your administrator to request access if necessary.
```
Analysis:
Vat Record Books handler for POS needs to read pos.session and pos.order records. Currently, the action is performed with the rights of the user running the report, so accounting-only user face an error.
As POS records are only read internally to build the report, we add sudo call to get the data.
opw-5862529
Forward-Port-Of: odoo/enterprise#126590
Forward-Port-Of: odoo/enterprise#125980Belgian payroll now calculates fictitious remuneration for departure holiday attestations and December double holiday regularization using the salary that applied during each absence period. This prevents employees with mid-year salary changes from having those absences valued at the wrong wage, improving payroll accuracy.
Original PR description
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all…
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all assimilated absence periods. **For an employee with:** - 20 days of assimilated absence in February with a salary of 2,000. - A salary increase to 3,000 in June. - Another 20 days of assimilated absence in November. ``` The previous computation was: (40 × 3,000) × (3 / 13 / 5) ``` - where all assimilated absence days were valued using the wage applicable on the last day of the previous year. - Instead, the remuneration should be computed using the wage applicable ``` during each assimilated absence period: ((20 × 2,000) + (20 × 3,000)) × (3 / 13 / 5) ``` - Compute the fictitious remuneration using the contract wage applicable to each payslip period so that each assimilated absence is valued with the correct monthly salary before applying the holiday formula. task-5932817
Belgian payroll now reports the correct mobility budget balance when it is paid after an employee's contract no longer includes a mobility budget. This prevents the DMFA declaration from showing zero and helps ensure accurate social security reporting.
Original PR description
When the mobility budget balance is paid on a contract that no longer carries a mobility budget, fall back to the previous quarter's contract to declare the correct amount instead of 0. Task-6384786 Forward-Port-Of: odoo/enterprise#127318
4 changes
Resolved issues and error corrections
Automatic account transfers now keep journal entries balanced when destination percentages are below 100%. This prevents small rounding differences, such as one-cent mismatches, from blocking or distorting transfer postings.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
Belgian payroll now automatically applies an employee's default private-use fuel card amount when creating a payslip, as long as the employee has no company car or mobility budget. This prevents the taxable benefit from being missed and keeps payslips aligned with the employee's payroll settings.
Original PR description
Steps to reproduce: - Set a "Fuel Card - Private use" default on the employee's payroll tab (fuel_card_personal_use), with no company car. - Generate/compute a monthly payslip for that employee. - The FUEL_CARD_PRIV salary rule never fires, so the private-use benefit-in-kind stays at 0 and is missing from the payslip. FUEL_CARD_PRIV is a property_input salary rule, so its amount comes from the payslip's property inputs, but nothing ever copied the employee's fuel_card_personal_use default into them. Seed FUEL_CARD_PRIV from that default in _compute_input_line_ids(), gated on fuel_card, no company car (transport_mode_car) and no mobility budget, matching this version's own benefit view visibility conditions. Added tests covering the default, each exclusion case, and manual payslip overrides. Task 6469003
The timesheet menu has been adjusted to display more cleanly on mobile devices. This makes it easier for users to enter and manage timesheets from smaller screens without dealing with a clunky layout.
Original PR description
In this commit, we improve the display of the timesheet systray in mobile view as it was clunky. task-6332208
This fixes an issue where Belgian SODA file imports could fail for users who do not have Analytic Accounting access. The import can now continue normally when Analytic Accounting is disabled, reducing unnecessary blockers in accounting workflows.
Original PR description
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error. This occurs because the import…
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error. This occurs because the import wizard reads the `analytic_account_id` field on the `soda.analytic.mapping` model to build an internal dictionary of departments. Because this field is restricted to the Analytic Accounting group, the evaluation of this field crashes the import for users even when the Analytic Accounting feature is disabled. This commit prevents the crash by using `.sudo()` when reading the analytic account ID. This safely bypasses the field-level group restriction, allowing the dictionary to be built with False values without interrupting the core import process. **Steps to reproduce:** - Log in as Mitchell Admin, change company to “My Belgian Company” - Settings > Users & Companies > Users > Mitchell Admin > Access Rights > Extra Rights > ensure “Analytic Accounting” is unchecked - Also ensure Mitchell Admin is not part of the “Analytic Accounting” group - Accounting Dashboard > remove “Favorites” from filter > drag & drop a SODA XML file to “Miscellaneous Operations” > save > observe Access Error **Current behavior before PR:** - Users who don't belong to the Analytic Accounting group encounter an access error when attempting to import SODA XML files, even when the Analytic Accounting feature isn't enabled **Desired behavior after PR is merged:** - Those users no longer receive an access error opw-6376039
6 changes
Resolved issues and error corrections
Users without accounting permissions could be prevented from confirming sales orders when a Studio approval rule referenced certain customer follow-up fields. This fix lets the approval check evaluate those rules correctly, avoiding unnecessary access errors while preserving the approval process.
Original PR description
continuation of [PR](https://github.com/odoo/enterprise/pull/121856) Issue: Inside _get_approval_spec filtered_domain is called a few times and due to a related field that calls an access rights group that the user who used the action isnt apart of is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5)create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Solution: Go one up the stack where _get_approval_spec is called and add a syudo for those calls opw-6316069 Forward-Port-Of: odoo/enterprise#127412
When receiving lot-tracked products with putaway rules, the Barcode app now keeps the correct destination shelf for each scanned lot. This prevents extra lots from being placed on the general stock location by mistake, improving warehouse accuracy.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2…
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2 units of that product; putaway sets the reserved move line destination to WH/Stock/Shelf 1. 4. In the Barcode app, scan a first lot, then a second lot. The second lot lands on a separate line at WH/Stock instead of WH/Stock/Shelf 1. Issue --- The first lot reuses the reserved line and keeps its Shelf 1 destination. The second lot cannot reuse it because its tracking number differs, so `_findLine` returns nothing and `_getNewLineDefaultValues` builds a new line with `location_dest_id` set to `_defaultDestLocation()`, the picking's default destination (WH/Stock). https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L1591-L1601 Putaway relocates the destination on the move line at reservation, never on the picking, so only the reserved line carries Shelf 1. Since `groupKey` includes `location_dest_id`, the new line does not group with the first lot and shows separately at WH/Stock. This is not a regression: new lines have always defaulted to the operation destination. https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L239-L241 The new line now inherits the selected line's `location_dest_id`, already relocated by putaway, instead of the default. opw-6317077 Forward-Port-Of: odoo/enterprise#125309
Global invoice creation for Mexican point-of-sale orders now ignores cancelled refunds, so only completed refunds affect the invoice totals. This prevents valid invoices from failing when a cancelled refund exists alongside a paid refund.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click…
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click "Return Products" to make a refund, but don't pay it, cancel it instead. 4. From the same order, click "Return Products" again to make a second refund, and pay it normally. 5. Go to the orders list, select the main order and the paid refund (not the cancelled one), then Actions > Create Global Invoice. -> Observation: error in the global invoice. In the CFDI tab of the main order the line is "Send Global In Error", and hovering on it the detail says "Failed to distribute some negative lines". Why: ---- When we make the global invoice, we remove the refunds from the order. A cancelled refund was never paid, so we should not count it. But we were counting it too. So we removed the refund amount twice in our case, one for the paid refund, and one for the cancelled one, and we end up with an order with negative amount that cannot be distributed. The fix: -------- We now skip the cancelled orders when we search the refunds, the same way it is done above when we collect the refunded orders. opw-6261404 Forward-Port-Of: odoo/enterprise#127560 Forward-Port-Of: odoo/enterprise#120996
Automated account transfers now balance correctly when destination percentages are below 100%. This prevents one-cent rounding differences from creating unbalanced journal entries, improving reliability for accounting workflows.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
The UK CIS report now correctly shows payments for receipts that include CIS tax, not just vendor bills. This helps businesses keep CIS reporting complete and accurate across more purchase document types.
Original PR description
With the l10n_uk_reports_cis module installed: - Create a vendor bills and add a CIS tax --> This vendor's bills appear correctly in the report. - Create a receipt and add a CIS tax --> This type of bill appears in the report, but the payment is not showing up. opw-6282548 Forward-Port-Of: odoo/enterprise#124043
This fixes an issue where signatures could disappear from downloaded signed PDFs when the original document used unusual page positioning from another PDF tool. Users can now trust that signatures visible during preview will also appear correctly in the final downloaded document.
Original PR description
Steps to reproduce (version 16+): 1) Obtain a pdf with a negative origin point: This can occur when a customer exports a pdf from another software, or it can be made manually using a python script 2) In the sign app, upload the pdf and create a new template, add a signature field to the document. 3) Sign the document. The preview will load correctly and the signature will be visible 4) Download and open the signed pdf. The signature is not on the document Notes: Issue occurs because the signature was added to the pdf outside of the visible area. The preview works because the signature is rendered on top of the unsigned document in the correct location. The issue can be fixed applying a translation to the canvas. Ticket: [6317223](https://www.odoo.com/odoo/project/49/tasks/6317223?debug=assets) Forward-Port-Of: odoo/enterprise#121960
2 changes
Resolved issues and error corrections
Deferred Revenue Report exports no longer fail when annotations are included. This prevents a server error and lets accounting users reliably download annotated XLSX reports.
Original PR description
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to…
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to **Accounting → Reports → Deferred Revenue Report**. * Add an annotation to a deferred revenue line by clicking the **annotate** from three dots next to the account. * Export the report in **XLSX** format. **Observed behavior:** * The export fails with a server error: `UnboundLocalError: cannot access local variable 'annotations_x_offset' where it is not associated with a value` **Cause:** * The variable `annotations_x_offset` is assigned inside the `for header_level_index, header_level in enumerate(options['column_headers'])` loop, which writes the "Annotations" column header for each header level. * The Deferred Revenue Report produces an empty `column_headers` list, so the loop body never executes and `annotations_x_offset` is never assigned. * When the code later tries to write annotation data for each report line, it references the unassigned variable, causing Python to raise `UnboundLocalError`. **Fix:** * Introduce a boolean flag `annotations_header_written = False` before the header loop to explicitly track whether the "Annotations" column header has already been written. * Inside the header loop, set `annotations_header_written = True` after writing the header. * After writing all individual column headers (where `x_offset` already points to the first free column after all data columns), add a fallback: if `report_annotations` is set but `annotations_header_written` is still `False`, assign `annotations_x_offset` from the current `x_offset` and write the "Annotations" header. opw-6354473 Forward-Port-Of: odoo/enterprise#122768
The Dutch tax reporting status process now skips or handles tax return status records that are missing their related closing entry. This prevents one incomplete record from blocking status updates for other Digipoort tax returns.
Original PR description
The `l10n_nl_reports_sbr_status_info` contains the `l10n_nl_reports_sbr.status.service` class. The class is responsible for fetching the status of sent Digipoort tax returns. The status is then posted as a chatter message to the tax return's closing entry. Issues can arise when one of the status service records is, for whatever reason, missing a closing entry. In such case, the message cannot be posted, resulting in an exception being raised. Since the records are processed in a loop without a try-catch, this causes the whole action to fail. This can lead to one broken record effectively shutting down the whole module's functionality. This PR adds some if-else checks to gracefully handle the case where the closing entry is missing. Related tickets: opw-5901446 and opw-6410082 Forward-Port-Of: odoo/enterprise#127597 Forward-Port-Of: odoo/enterprise#125996
1 change
Resolved issues and error corrections
Acerta payroll exports for Belgian employees now include weekend days when certain leave periods, such as sick leave, overlap a weekend. This prevents missing leave information in reports and helps ensure payroll files match Acerta’s expected format.
Original PR description
## Steps to reproduce: - Install l10n_be_hr_payroll_acerta - Create an employee in a belgian company - Create a sick time off for the created employee that overlaps with a weekend - Export acerta report for the employee - Notice the weekend that overlaps with the time off is not present in the report ## Cause: While exporting the report file we only loop over the created work entries' dates and since weekends doesn't have work entries we don't consider them in the report. ## Fix: When generating the line of a leave's start date we check if the leave overlaps with a WE, we fetch the WE's date and we generate a line for each day of the WE. According to Acerta this is the correct behavior for their reports for specific types of leaves. **opw-6313534** Forward-Port-Of: odoo/enterprise#124500
13 changes
New functionality added to Odoo
This update improves Odoo VoIP by adding early support for buying phone numbers and ringing phones through PBX integration, while also fixing issues with incoming calls, call groups, and phone number formatting. It should make business calling workflows more reliable and prepare the VoIP module for broader phone service capabilities.
Enhancements to existing features
This update improves Belgian payroll handling for Joint Committee 302 employees who are paid through tips. It adds the related payroll rules, employee and contract settings, warnings, reporting data, and validation coverage so payroll teams can process these cases more accurately.
Original PR description
Task: 6037567
VoIP calls now coordinate across open browser tabs so that when a call is answered or brought forward, other tabs automatically place their sessions on hold. This helps prevent overlapping calls or audio conflicts and makes the calling experience more reliable for users working with multiple tabs.
Original PR description
Put sessions on hold in other tabs when a call is accepted or promoted. The shared worker now tracks connected clients and assigns each tab a unique userAgentKey. When a session is promoted to front, the worker broadcasts HOLD_ALL_SESSIONS to every tab. The receiving tab ignores broadcasts matching its own userAgentKey. task-5973023
Payroll rules and related country-specific payroll modules were updated to remove an outdated paid amount setting. This simplifies payroll configuration and helps keep payslip calculations consistent across localizations.
Original PR description
task-6186326
Belgian payroll now avoids applying flat-rate withholding tax to double holiday pay and 13th month payslips when the employee's regular monthly tax situation indicates no tax is due. This helps prevent over-withholding in eligible cases while keeping the tax calculation aligned with normal payslip rules.
Original PR description
This commit adds an exemption that skips the flat-rate professional withholding tax on double holiday and 13th month payslips when two conditions both hold: no cumulated PP from regular monthly payslips this year, and the theoretical monthly tax on base salary plus 1/12 of the exceptional gross works out to zero. That theoretical tax is simulated the same way as a real monthly payslip, including the flat-rate professional fees and transport tax deductions, so it does not overstate what the employee actually owes. It also pulls the bareme bracket logic into its own method so both the standard and theoretical paths can share it. task-6322148
Belgian payroll cash register settings now appear when the selected employer category allows Joint Committee 302, instead of depending on whether an employee is already assigned to that committee. This makes the settings available earlier and keeps payroll configuration aligned with the employer category setup.
Original PR description
Cash register settings are currently displayed only when the company has an employee assigned to Joint Committee 302. This makes their availability depend on the employee configuration. The employer category already defines the allowed joint committees. Base the visibility on whether the selected category allows Joint Committee 302, making the settings available as soon as the relevant payroll configuration is selected. Task: 6395308
Users can still add appointment events to external calendars such as Google, Outlook, Apple, and iCal, but the responsibility is now handled by the Calendar app instead of Appointment. This centralizes the feature so calendar links can be reused more consistently across appointment-related communications.
Original PR description
Moving the possibility for users to add a calendar event to their iCal/Outlook/Apple or Google calendars from appointment to calendar. Task-6218949
Turkish payroll now calculates severance pay and provisions based on an employee's departure date and reason, rather than whether the employee record is archived. Several internal salary rule lines are hidden from display, and manual deduction/addition labels are renamed to clearer business terms.
Original PR description
- Severance Pay and Severance Provision now trigger on the employee's departure date and departure reason instead of the employee being archived. - Set visibility to NEVER for: Previous Months Gross, Previous Months Paid Tax, Gross From Net, SSI Company Contribution, SSI (unemployment) Company Contribution, Taxable Salary, Current Month Actual Deducted Tax (Pre Exempt), Expected Net Salary. - Rename Manual Deductions -> Other Deductions, Manual Additions -> Other Allowances. task-6459874
UrbanPiper order screens now present order details and information popups more clearly for point-of-sale users. Demo data also includes rider information, making examples more realistic and easier to understand during setup or testing.
Original PR description
In this commit: ================ - Improved the Order Details and Order Info popup UI for UrbanPiper orders. - Enriched demo data by including rider info task-6053362
Signature request activities now show key details such as the reference, requester, signers, and documents, making it easier to understand what needs attention. Completion messages on linked records are cleaner and include a link to the signed document plus the signer list, helping users quickly find final signed files.
Original PR description
Show the request reference, creator, signers, and documents on the activity card, add an icon to the "View" button, and post a cleaner completion message on the linked document with a link to the signed document and the list of signers (attaching the documents only, not the certificate). task-6127862
Resolved issues and error corrections
Belgian payroll users can now generate 274.xx tax XML reports even when the accounting payroll add-on is not installed. The required SME exemption setting has been moved into the core Belgian payroll configuration, preventing an error and making the report available in more setups.
Original PR description
[FIX] l10n_be_hr_payroll: fix 274.xx xml generation (without accounting)
Bug reproduction:
1 - Install only l10n_be_hr_payroll (without accounting) 2 - Belgium company → create new employee
3 - Create payslip with employee validate it
4 - Payroll → Reporting → 274.XX → Generate XML
5 - Traceback about exemption_sme_status is there
Bug cause:
1 - Field exemption_sme_status is defined in l10n_be_hr_payroll_account
1.1 - It can be defined in l10n_be_hr_payroll instead
2 - When there is only l10n_be_hr_payroll installed
2.1 - It cannot find the mentioned field
Bug solution:
1 - Move field From l10n_be_hr_payroll_account to l10n_be_hr_payroll
task-6422367This fixes an issue where closing entries from German point-of-sale sessions were not being recorded in the Fiskaly portal. The certification module now uses the updated accounting validation process, helping ensure compliant register closures after sales sessions.
Original PR description
Steps to reproduce: =================== - In a Fiskaly-enabled German company, open a PoS session and make some transactions. - Close the register. Issue: ====== - The closing register entry is not registered in the Fiskaly portal. Cause: ====== - `l10n_de_pos_cert` calls the _validate_session method. - After the PoS accounting refactor, `_validate_session` was replaced by `_validate_session_accounting`. Fix: ==== - Update the method call to use `_validate_session_accounting`. task-6455319
Mexican payroll now clearly separates Integrated Daily Wage for severance from Base Contribution Salary for Social Security, reducing confusion and improving confidence in payroll results. The Social Security salary calculation now uses actual accrued days from the prior two-month period, excluding unpaid absences, to better align with Mexican legal requirements.
Original PR description
In Mexico, there are two distinct payroll concepts: * Integrated Daily Wage (SDI): used for severance pay (liquidations). * Base Contribution Salary (SBC): used for Social Security (IMSS).…
In Mexico, there are two distinct payroll concepts: * Integrated Daily Wage (SDI): used for severance pay (liquidations). * Base Contribution Salary (SBC): used for Social Security (IMSS). Previously, these concepts were used interchangeably in the code. While the calculations for IMSS were mathematically correct, they incorrectly referenced the Integrated Daily Wage. This naming inconsistency could cause users to lose confidence in the system's accuracy. All IMSS rule calculations now correctly reference the SBC concepts. Additionally, to ensure strict compliance with Article 34 of the Mexican Social Security Law (LSS): > The daily wage will be determined by dividing the total amount of variable earnings obtained in the previous bimester by the **number of accrued wage days**, and adding its result to the fixed elements of the daily salary. The calculation for the variable portion of the SBC is updated to reflect the actual accrued days of the previous bimester, excluding unpaid absences. target: master task-6374791
6 changes
Resolved issues and error corrections
Studio approval rules can now be checked even when a sales user lacks access to accounting-related fields used in the rule. This prevents valid sales order confirmations from being blocked by an access error when approvals depend on related customer follow-up information.
Original PR description
continuation of [PR](https://github.com/odoo/enterprise/pull/121856) Issue: Inside _get_approval_spec filtered_domain is called a few times and due to a related field that calls an access rights group that the user who used the action isnt apart of is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5)create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Solution: Go one up the stack where _get_approval_spec is called and add a syudo for those calls opw-6316069
Global invoices for Mexican POS orders now ignore cancelled refunds, preventing invoice creation errors when a customer return was started but not completed. This helps ensure valid paid refunds are processed correctly without incorrectly reducing the original order twice.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click…
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click "Return Products" to make a refund, but don't pay it, cancel it instead. 4. From the same order, click "Return Products" again to make a second refund, and pay it normally. 5. Go to the orders list, select the main order and the paid refund (not the cancelled one), then Actions > Create Global Invoice. -> Observation: error in the global invoice. In the CFDI tab of the main order the line is "Send Global In Error", and hovering on it the detail says "Failed to distribute some negative lines". Why: ---- When we make the global invoice, we remove the refunds from the order. A cancelled refund was never paid, so we should not count it. But we were counting it too. So we removed the refund amount twice in our case, one for the paid refund, and one for the cancelled one, and we end up with an order with negative amount that cannot be distributed. The fix: -------- We now skip the cancelled orders when we search the refunds, the same way it is done above when we collect the refunded orders. opw-6261404 Forward-Port-Of: odoo/enterprise#127560 Forward-Port-Of: odoo/enterprise#120996
The Sign Documents wizard now keeps the Employee role selectable when users choose multiple signature templates that use separately created roles with the same name. This prevents signature requests from being blocked when combining templates such as contracts and policies.
Original PR description
Problem: When selecting several sign templates with different signatory counts in the "Sign documents" wizard (e.g. a Contract template together with a Computer Policy template), the Employee Role…
Problem: When selecting several sign templates with different signatory counts in the "Sign documents" wizard (e.g. a Contract template together with a Computer Policy template), the Employee Role field would empty out or disappear entirely, with "No records" shown in the dropdown. This blocked users from sending the signature request at all. Purpose: `_compute_responsible_ids` matched roles across the selected templates by recordset identity (`&=`), i.e. by database id. Since the Sign Template Builder allows free-text role creation, two templates can end up with roles that are visually/semantically identical (same name, e.g. "Employee") but were created as separate `sign.item.role` records with different ids. The id-based intersection then evaluated to an empty recordset, which made the Employee Role field's domain empty and the field itself collapse in the UI. This fix matches roles by name instead of by id when computing the common roles across selected templates, and resolves the correct per-template role id by name in `validate_signature` instead of reusing a single id across every template. Steps to Reproduce On Runbot: 1. Go to Sign > Templates and create two templates, each with one role named "Employee", added independently (so they end up as two distinct sign.item.role records with the same name). 2. Go to an employee's Contract, click "Sign Documents". 3. Select both templates in "Documents to sign". 4. Observe the Employee Role field empties out / shows no records, and the request cannot be sent. opw-6445327
Swiss payroll now counts flexible employee absences using the dates selected in the time off request, avoiding an extra day caused by timezone conversion. This prevents one-day accident leave from being prorated as two days, helping keep regular wage and accident salary amounts accurate.
Original PR description
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating…
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating the accident salary. Steps to reproduce: * Install Swiss Payroll. * Configure a monthly employee without a working schedule. * Assign one day of accident time off. * Generate the payslip for that month. Cause: The Swiss wage computation derives absence boundaries from the date portion of the leave's UTC datetimes: https://github.com/odoo/enterprise/blob/16c29e1bab34b5bcb2b001477d928ec5eb294a97/l10n_ch_hr_payroll/models/hr_payslip.py#L313-L330 A fully flexible employee's full day leave starts at local midnight. In timezones ahead of UTC, that start is stored on the previous UTC date, so the inclusive calendar day computation adds an extra day. Solution: We need to use the requested time off dates for both payslip range filtering and absence proration. These fields preserve the calendar days selected by the user independently of timezone conversion, while leaving the UTC datetimes and half-day handling unchanged. opw-6435086
Fixes a mobile Documents issue where the Info & Tags panel could appear enabled but remain hidden or inaccessible after reloads, view switches, previews, or selection changes. This keeps document details and chatter actions available in the correct state, reducing confusion for mobile users.
Original PR description
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not…
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not displayed but the button is still enabled - Switching to the list view properly shows it **Issue:** Original fix (see [1]) was not enough for every case. Additional issues: - Chatter hidden on init even when its panel has `visible = true` - State desynchronized with the view when switching menu type (kanban/list) or by previewing a document and coming back - When using the button with an open preview, chatter shows up in the background but is not accessible (and going back discards it) - Removing selection with an open chatter disable the related action **Fix:** - Disable the chatter on mobile init by default to avoid having to manually move it back - Reset chatter on selection removal to avoid getting stuck in the menu - Reset chatter on view switch to avoid being in the wrong state afterwards (and revert the previous css changes) Not a great fix (quite mobile-specific) and there might still be some edge cases. [1] original fix: https://github.com/odoo/enterprise/commit/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52 opw-6061993
Large accounting reports now render fewer hidden lines, reducing page weight and improving responsiveness when users fold sections or search. This helps teams work more smoothly with reports containing thousands of lines until the newer virtual grid technology is available.
Original PR description
When a report has 1 000+ lines, the DOM gets quite heavy which make DOM operation very slow. To help reduce this, we now will minimize the number of components rendered by removing components that previous were just hidden using "d-none" on the line. This will require more creation and suppression of components but it should make the DOM size smaller so it should help on larger reports where a lot of lines are hidden (by folding back a line, or by using the search bar). opw-6427411 opw-6442756 PR Note: this is only required until saas-19.5/20.0 since the virtual grids are added then which will resolve this issue since the virtual grids only render what's in the view of the user with long paddings on top and bottom so only ~70-80 lines are actually rendered.
5 changes
Resolved issues and error corrections
The general ledger CSV export now keeps account and transaction lines in the same order, even when multiple companies use the same account codes. This prevents export failures and helps users reliably download reports.
Original PR description
Description of the issue this commit addresses: Account and move lines can be returned in different orders when account codes are shared across companies. The CSV generator can then exhaust its account iterator and raise StopIteration. --- Desired behavior after this commit is merged: This commit orders move lines using the account sequence returned by the report, keeping both CSV iterators aligned. --- runbot-[242131](https://runbot.odoo.com/odoo/error/242131)
Odoo now recognizes valid Brazilian electronic invoice XML files even when the main invoice tag has no attributes. This prevents legitimate vendor bills from being skipped during import, reducing manual rework for Brazilian accounting users.
Original PR description
### Issue before this commit: Certain valid Brazilian NF-e (electronic invoice) XML files fail to import because the system silently ignores them during the initial EDI recognition phase. ### Steps to reproduce the issue: 1. Download Accounting and l10n_br_edi 2. Go to Vendor > Bills 3. Try to import both xmls in the ticket 4. One of the two will not be imported correctly ### Cause of the issue: https://github.com/odoo/enterprise/blob/3ed1721b702555e96c9774969927f6517e855704/l10n_br_edi/models/account_move.py#L819-L827 This function relies on a strict byte string search for b"<NFe " while it's also correct if the tag is only `<NFe>`. ### Reason to introduce the fix: To make the initial NF-e file recognition more robust and compliant with standard XML namespace rules, ensuring Odoo successfully processes all valid Brazilian invoices regardless of attribute formatting. opw-6402843
Luxembourg payroll now calculates historical payslips using the wage index that applied at the payslip period, rather than the current index. This helps ensure past salary calculations remain accurate when wage index rates change over time.
Original PR description
Historical payslips incorrectly used today's wage index instead of the index active during the payslip period. Now, salary rules evaluate the indexed wage using `payslip.date_to` via the new `_get_l10n_lu_indexed_wage(date)` contract method. Task: 6395557
This fixes an incorrect classification used when reporting Swiss withholding tax employee changes. The correction helps ensure payroll mutation data is transmitted accurately to Swissdec, reducing the risk of rejected or misleading declarations.
Original PR description
task-6116327 Forward-Port-Of: odoo/enterprise#127745
Mexican invoices paid within the required short payment window are now correctly treated as PUE and blocked from being sent to CFDI/SAT payment reporting. This prevents incorrect XML submissions, especially when grouped payments involve multiple invoices.
Original PR description
Issue: Sending PUE invoices to CFDI/SAT is no more suitable Step to reproduce: - In a Mexican company - Create an invoice (Invoice A) - Add a line - Set Payment Terms to "Immediate payment" - Confirm…
Issue: Sending PUE invoices to CFDI/SAT is no more suitable Step to reproduce: - In a Mexican company - Create an invoice (Invoice A) - Add a line - Set Payment Terms to "Immediate payment" - Confirm - Duplicate (Invoice B) - Confirm - Duplicate again (Invoice C) - Set Payment Terms to "30 days" - Confirm - Go to Invoice A - Pay it. It should appear as "Paid" - Send it to CFDI - Go to Accounting > Customer > Invoices - Select Invoice B and C - Pay and select the "Group Payments". They should appear as paid. - In every invoice, click the "Update Payment" button Current behavior: - In Invoice A -> Sheet CFDI: A button "Force CFDI" allow sending the invoice to CFDI - In Invoice B/C -> sheet CFDI: Click on the "Download" part of the Payment line, the XML that was sent to CFDI include both invoice B and C Expected behavior: - It shouldn't be possible to send invoice A to CFDI. - Invoice B shouldn't be sent to CFDI Cause: Invoice paid in less than 30 days as referred as PUE and shouldn't be sent to CFDI. opw-5381600
4 changes
New functionality added to Odoo
A new FedEx-certified delivery module has been added to align Odoo shipping workflows with FedEx certification requirements. This helps businesses using FedEx meet required integration guidelines and continue processing shipments through the updated FedEx API.
Original PR description
For the certification process of FedEx there were some changes needed in the delivery_fedex_rest module. This modules made those changes according to the FedEx guidelines. Task-id: 6164275
Enhancements to existing features
General Ledger Excel exports now group accounts into smarter batches instead of processing each account separately. This reduces export time for companies with large accounting datasets while keeping memory usage under control.
Original PR description
### Description of the issue/feature this PR addresses: This PR optimizes the XLSX export process for large accounting reports by implementing a "smarter" batching strategy. Three months ago, a…
### Description of the issue/feature this PR addresses: This PR optimizes the XLSX export process for large accounting reports by implementing a "smarter" batching strategy. Three months ago, a batching mechanism was introduced to prevent memory errors during large exports. However, that implementation batched every single account individually. While this solved the memory consumption issue, it introduced a significant performance regression: processing thousands of tiny batches one-by-one is extremely slow due to the overhead of repeated report engine calls. This change introduces a weighted batching system that groups multiple accounts together into a single batch until a maximum line threshold is reached. This strikes an ideal balance between low memory usage and high execution speed. ### Current behavior before PR: The system uses _get_accounts_with_move_lines to retrieve a list of accounts. The export logic iterates through every account individually, creating a separate batch for each one. For reports with many accounts (even those with few moves), the overhead of calling the report engine for every single account causes the export to take an excessive amount of time. Memory usage is low, but time performance is poor. ### Desired behavior after PR is merged: The new _get_account_ids_and_weights_with_move_lines method fetches both the account IDs and the count of moves (weight) associated with them in a single SQL query. The _build_account_batches method packs accounts sequentially into batches of up to 500,000 lines. Small accounts are grouped together. Large "mega-accounts" that exceed the limit are isolated into their own batches to prevent memory spikes. _get_accounts_with_move_lines is deprecated. It is effectively superseded by the more informative weighted query, providing the data necessary for the smarter partition logic. ### Benchmarks | # Move Lines | Before | After | | --- |---|---| | ~5.6million | Times Out | 32sec | | ~3.5million| Times Out | 11sec | ### References #103329 opw-6077972 opw-5723374 opw-5950806 opw-5915227 opw-6066290 opw-5914983 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Shipments that require a commercial invoice now explicitly request it from DHL, instead of only sending invoice details in the shipment data. This helps ensure the needed customs invoice is generated for affected DHL deliveries, reducing manual follow-up and shipping delays.
Original PR description
When `_should_generate_commercial_invoice` is True, we add the invoice data to the payload, but we never request this commercial invoice. opw-6357101
Manufacturing orders now close as expected after users confirm a consumption warning in the shop floor flow. This prevents completed work from remaining visible and reduces confusion for production teams.
Original PR description
When confirming a consumption warning wizard, the MO will not close Steps to reproduce: ------------------- * Create a Product A, Product B * Create a BOM for Product A: - One Component B used during an Operation * Create, confirm and plan a MO for Product A * Start the Operation and go to shopfloor from the smartlink * Set the Quantity of Component B used to 2. * Mark as Done the Operation * Close operation and confirm the consumption warning wizard. -> The Mo is still visible. Observation: ------------- Why the fix: ------------ opw-6449118