Friday, August 21, 2026
80 changes · master
New functionality added to Odoo
Belgian payroll can now include manual expense reimbursement amounts directly on payslips through a dedicated input and salary rule. The yearly total of these reimbursements is also reflected on the 281.10 tax form, helping payroll reporting stay complete and accurate.
Original PR description
. Add manual Expense reimbursement payslip input and its corresponding salary rule . Show the sum of all the values of the year on 281.10 task-6462236
The website builder AI can now read and update site navigation menus, including creating, renaming, moving, reordering, deleting, and linking menu items to page anchors. This helps users adjust website navigation through the AI assistant while keeping safeguards such as limited nesting and read-only mega menus.
Original PR description
Add two AI tools, "Get Website Menus" and "Edit Website Menus", so the website builder agent can read and modify the site navigation menu: create, rename, move/nest, reorder and delete menu items, including linking an item to an anchor within the current page. Update the skill instructions with the tool workflow and rules (two levels of nesting max, mega menus read-only, atomic operations), wire up the new server actions, and extend the builder plugin so the menu reloads after an AI edit to the menus, following the normal user behaviour. task-6143430
Enhancements to existing features
The US sales tax report now captures more complete sales tax details, including exempt, non-taxable, taxable amounts, and tax rates by jurisdiction. This helps businesses prepare more accurate state-level tax reports and lays groundwork for future e-filing support in Odoo, including automated Avalara-based configuration.
Original PR description
*: account Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to capture all relevant…
Resolved issues and error corrections
Opening the Time Off Type details from a new leave request no longer saves or submits the request before the user is finished. This prevents accidental confirmations or approvals and also avoids related display errors that could hide newly created leave requests until refresh.
Original PR description
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls…
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls `willOpenRecordInDialog()`, which defaults to `record.save()`. For a new leave request, this triggered `hr.leave.create()`'s validation logic, auto-confirming (or even auto-approving) the request before the user had finished the wizard. This premature save was also the root cause of two related bugs, both fixed as a side effect: closing the Time Type dialog threw `TypeError: Cannot read properties of undefined (reading 'focus')` (the save re-rendered the parent, leaving `Many2One`'s `onClose` pointing at a stale component), and that crash aborted the promise chain before it could reload the calendar, leaving a newly-created leave request missing from view until a manual refresh. Adds a `many2one_no_save` field widget overriding `willOpenRecordInDialog` to skip the save, applied to `work_entry_type_id` on the base `hr_leave_view_form` so all inheriting views are covered. task-6452848 Forward-Port-Of: odoo/odoo#281263
Code cleanup and technical improvements
Point of Sale customer displays now communicate with terminals more directly and only when a display is actually connected. This reduces unnecessary background activity, improves reliability after startup or reload, and makes future display-related changes easier to maintain.
*: account Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to capture all relevant information, such as exempt sales, taxable sales, non-taxable sales, and the tax rate. It supports both Avalara and non-Avalara users. Configuration: Users can configure taxes specifically for the US jurisdiction by setting the jurisdiction type, the following information required by the type (state, county, city). If the tax is an exempt or nontaxable of a standard tax rate, then it can be added to the standard tax rate on its exempt and nontaxable tax field. For Avalara users, the configuration is automatically handled based on the Avalara response. The following tax types are supported: - Fully exempt taxes (ex. 0% exempt tax) - Fully nontaxable taxes (ex. 0% nontaxable tax) - Rate-reduction taxes (ex. 6% rate reduced to 4% tax) Report: The US tax report will organize the taxes based on its state. Per state, it lists the taxes in order based on its jurisdiction type: state, special, county, city. The header will total the columns based on the base lines to avoid double-counting. Per tax row, the column values include its linked exempt and nontaxable taxes. - Gross should be a sum of exempt, nontaxable, and taxable values. - Exempt displays the amount that are exempted. - Nontaxable displays the amount that are nontaxable. - Taxable displays the amount that are taxable. **Note: Rate-reduced taxes will not have its own row and are aggregated into its parent tax. Additional changes: To support city jurisdiction type on taxes, the res.city.csv file needs to be moved from l10n_us_hr_payroll to l10n_us for access. task-6223342 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Point of Sale customer display can now open directly on a connected secondary screen when the browser supports it and permission is granted. If that is not possible, it still opens normally on the same device, giving shops a smoother customer-facing display setup without disrupting existing workflows.
Original PR description
In this commit: ================= When a secondary screen is detected via the `Multi-Screen Window Placement API`, the customer display opens there; otherwise it falls back to opening in a new window on the same device. The Multi-Screen Window Placement API (`window.getScreenDetails()`) lets the browser report all connected displays along with their position and size, so the customer display window can be placed precisely on an external screen instead of just opening on the same monitor as the POS. It requires user permission and is only supported in Chromium-based browsers, so the feature gracefully falls back to opening on the same device when the API is unavailable, no secondary screen is found, or permission is denied. Task: 6305983
The mail interface now supports customized tab views in areas like discussions and the messaging menu. This gives teams more flexibility to organize communication views in ways that better fit their workflows.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update expands automated checks for several onboarding flows and fixes issues those checks uncovered, including outdated screen targets and unreliable form entry behavior. This helps make first-time setup experiences in apps like Frontdesk, Expenses, Appointments, Subscriptions, Payroll, and Sales more dependable for users.
Original PR description
Add frontdesk_tour, hr_expense_extract_tour, appointment_tour, sale_subscription_tour and payroll_tours to the onboarding tours test, fixing the tours themselves where the robot-mode replay uncovered real bugs: obsolete selectors, incomplete many2one selections, dirty-form-on-save races, and (for payroll_tours) a full rewrite of the contract-creation flow to match the hr.version model that replaced the old hr.contract-based UI. Also fix searchOrCreateMany2X: always type the field value explicitly in the "Create and edit" dialog instead of relying on its async pre-fill on desktop, which can lose the race against the next tour step on heavier form views. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
HR users can now create employee versions for several employees at the same time through a guided wizard. This reduces repetitive work and helps teams manage employee record changes more efficiently across groups of staff.
Original PR description
This commit introduces a new wizard in the HR module that allows users to create employee versions for multiple employees at once. TaskID: 6471477
The help and participant-list messages have been updated to be clearer for users. The option to leave a conversation is now handled consistently through the conversation action menu rather than a typed command, with wording that fits all conversation types.
Original PR description
* = im_livechat Updated `/help` description and `/who` message. Moved leave conversation eligibility logic to channel model. Renamed "Leave Channel" to "Leave Conversation" so that it works for all channel types. Removed /leave command. task-[6008262](https://www.odoo.com/odoo/project/1519/tasks/6008262) enterprise: https://github.com/odoo/enterprise/pull/112959
Website forms now automatically include required fields when a form action is changed to a less-common model, preventing silent submission failures. Long single-choice fields are shown as dropdowns for easier use, and empty date fields display cleanly instead of showing undefined values.
Original PR description
Selecting an action from "More Models" emptied the form: those models have no registered fields, unlike curated actions. Without the model's mandatory fields, the form silently fails at submission. Now those fields are added and flagged model-required (non-removable), so the form stays submittable. task-4952094
Spreadsheet scorecards now define their main value and baseline using formula syntax, making them more consistent with spreadsheet behavior. This improves reliability and clarity when scorecards are configured or displayed, including in dashboard views.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Manufacturing teams can now update the recorded work order duration for a specific employee. This helps keep employee time logs accurate for production tracking and related costing.
Original PR description
Now the work order duration for a specific employee can be updated.
Backend refund orders now follow the same limits as the Point of Sale frontend. Staff can still adjust quantities, delete lines, add customer notes, and specify lots, but cannot change key commercial details such as products, prices, discounts, or add new lines, reducing refund errors and inconsistencies.
Original PR description
In the frontend the refund process is limited to only certain actions/ modifications. However if you refund from the backend multiple fields are editable. Currently you are allowed to change the product, its unit price, the discount, add a new product line,... We block all those actions and we keep: - editing the quantity - deleting order line - customer note (why not?) - lot (allows to specify which lot we return) task-6445165
The emoji picker is now easier to use with clearer search guidance, a better-positioned search icon, and a quick button to clear searches. Frequently used emojis also stay in a stable order while the picker is open, making selection more predictable for users.
Original PR description
This commit improves the emoji picker UX by: - changing the search placeholder to 'Find the perfect emoji'. - moving the search icon to the left. - adding an `oi-filled` button to clear the emoji picker search. - preventing frequent emojis from being reordered while the picker is open. Task-[5879855](https://www.odoo.com/odoo/project/1519/tasks/5879855) <img width="337" height="407" alt="image" src="https://github.com/user-attachments/assets/cb832b4e-376b-4a1f-9d0b-b308186e2eb2" /> <img width="337" height="407" alt="image" src="https://github.com/user-attachments/assets/70652df6-a64f-4dd6-b589-00854d0f54b7" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website editors now manage mega menus directly from each menu item using a checkbox instead of a separate add action. The update also adds easier content drop areas and a blank template, making it faster to build and customize large navigation menus.
Original PR description
1. Remove + mega menu item and make it a checkbox on menu item instead 2. Add dropzones before & after each template 3. Remove size on the editor for mega menu and rely on general layout 4. Add a blank template last task-6171291 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Helpdesk field service teams can now plan interventions from the standard Planning view, see all shifts, and open scheduled work filtered to the current ticket. The update also separates scheduled and completed shift counts, making it easier to understand upcoming and finished work at a glance.
Original PR description
- "Plan Intervention" now opens the standard Planning view showing all shifts. - "Scheduled" opens the Planning view filtered on the current ticket. - Open the Gantt view on the next scheduled shift, or the most recent shift when no upcoming shift exists. - Display scheduled and completed shift counts separately. task-6267783
Worksheet section titles are now shown when worksheets are printed as PDFs and viewed in the portal. This preserves the worksheet structure for customers and field service users, making forms easier to read while keeping folded sections working as before.
Original PR description
Previously, worksheet sections were not displayed in printed PDFs or on the portal UI, causing the worksheet structure to be lost. This change ensures that section titles are rendered in both the printed PDF and the portal UI while preserving the existing behavior for folded sections. task-6314616
The timesheet timer menu now loads more quickly by avoiding repeated background requests and reusing information that has already been prepared. This should make opening and using the timesheet systray feel smoother, especially for users who track time frequently.
Original PR description
This PR removes some blocking RPC calls and caches information to make the loading of the systray as lightweight as possible. Changes include: - Move `field_get` to the lazy session info, so the field metadata is available client-side without a dedicated round-trip. - Cache the pre-filled form: it does not change as long as the task / project context stays the same, so it is computed once and reused. - Drop the `get_server_time` RPC and rely on the client-side clock. - Add a client-side systray cache service to avoid redundant requests. Task-6131386 Forward-Port-Of: odoo/enterprise#125368 Forward-Port-Of: odoo/enterprise#120429
The VoIP softphone now opens directly to a pre-filled keypad when launched from a form with an available phone number. Calls made without changing that number are automatically logged against the related record, helping teams save time and keep customer activity history accurate.
Original PR description
``` [IMP] voip: auto-fill keypad with partner phone and create call activity on form record When the softphone is opened from the systray while a form view is active, automatically switch to the keypad tab and pre-fill the partner's phone number if the record has a partner_id with a phone field. Falls back to the record's own phone fields (via _phone_get_number_fields) when no linked partner is found or the partner has no phone number. If the user dials the pre-filled number without modification, the form record context (res_id, res_model) is passed to makeCall so that a phonecall activity is created and linked to that record. ``` Task-6365445
UK companies now submit HMRC VAT returns from the tax return itself instead of the tax report screen. This makes the filing process more intuitive and avoids generating unnecessary returns from the UK tax report.
Original PR description
Before this commit: - The tax return submission to HMRC for UK companies is done in the tax report view itself. - Even the returns are being generated for the UK tax report, but the filing process is handled in the tax report, which is unintuitive. After this commit: - The UK tax return filing to HMRC has been moved to the tax return itself. - So there are no more useless returns generated for the UK tax report. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10198 Task-5865605
Website editor users will now see an AI badge next to individual blocks that were generated or changed with AI. This helps set expectations that some standard editing options may behave differently for those blocks.
Original PR description
This commit shows an icon next to the name of snippets edited with the AI so users know standard builder options may behave differently. The flag `containsAiContent` was only set on the zone, but the icon is shown per snippet, so it is now stamped on each generated block instead. task-6251800
Belgian payroll now includes salary rules for handling gift vouchers. This helps payroll teams calculate and report these benefits more consistently within Odoo.
Original PR description
Task: 6424079
The Belgian payroll module now includes a salary rule for calculating an additional net salary component. This helps payroll teams handle this type of compensation more directly and consistently within Odoo.
Original PR description
This commit introduces a new salary rule to the Belgian HR payroll module, allowing for the calculation of an additional net salary component. task-6409188
The salary configurator now avoids duplicate background work and reduces database lookups when users update salary offers or benefits. This should make salary simulations faster and more efficient without changing the user-facing process.
Original PR description
In the salary configurator (`/update_salary` and `/onchange_benefit` routes), `create_new_version()` was executing a redundant second call to `offer._get_version()`. This caused an extra dummy `hr.employee` and `hr.version` record to be created in memory, triggering an unnecessary nested `hr_version_context` savepoint. Fix: Pass the existing `version.payroll_properties` record into `create_new_version()` directly to avoid the second `_get_version()` call and eliminate the nested savepoint cycle. `_get_compute_results()` was executing multiple separate `search()` queries on `hr.contract.salary.resume` for different value types. Combine these searches into a single query per request to reduce database round-trips. Task: 6226629
WhatsApp conversations now keep at least one internal agent assigned by hiding options that would let the final agent leave. This helps ensure customer conversations remain accessible, supported, and manageable by the business.
Original PR description
Prevent last agent from leaving the conversation by hiding the Leave conversation action and /leave channel command. This prevents scenarios where a Whatsapp channel becomes orphaned with only the external Whatsapp customer remaining, which would make the conversation inaccessible and unmanageable. task-[6008262](https://www.odoo.com/odoo/project/1519/tasks/6008262) community: https://github.com/odoo/odoo/pull/257521
Time off requests made from the Gantt view now handle multi-day date ranges more consistently. When a selected range effectively counts as one working day due to weekends, non-working days, or overlapping leave, users are no longer shown misleading half-day choices.
Original PR description
Purpose: When taking a range which results in only 1 day taken (because it overlaps with a non working day or another time off), you only see the selector of morning / afternoon like for a unique day, but you shouldn't be able to select morning or afternoon. - added selection for request periods in the gantt for day ranges similar to the one in form view task-id: 6456270
Helpdesk reports and ticket groupings now show the total time spent instead of the average time. This gives managers a clearer view of workload and effort across tickets, periods, and reporting groups.
Original PR description
Previously, the average number of hours spent was displayed in the Ticket Analysis and SLA Status Analysis reports. The grouped view in both My Tickets and All Tickets also showed the average time rather than the total time, making it difficult to understand the actual time spent. From this commit onward, the total time spent will be displayed instead of the average. This provides a clearer view of how much time has been spent over a specific period or based on the selected grouping criteria. Task-4652757
The manufacturing work order time log dialog now updates the employee's total logged time instead of only the most recent entry. This makes the displayed time better match what users expect and reduces confusion when tracking work on production tasks.
Original PR description
Before, the update time log dialog was targeting the last employee time log entry, causing confusion as it didn't match the total time spent on the task. The employee total time is defined as the sum of its time log entries without checking if they overlap, unlike the work order duration. Task-6467195
WhatsApp message templates can now use meaningful placeholder names, such as customer name, instead of only numbered fields. This makes templates easier to read and keeps Odoo compatible with newer WhatsApp Cloud API template formats.
Original PR description
This commit introduces support for named parameters in WhatsApp templates, allowing users to use descriptive placeholders like `{{customer_name}}` in addition to the standard positional `{{1}}` format.
This change ensures compatibility with newer template formats supported by the WhatsApp Cloud API and improves template clarity.
Documentation: https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/overview#parameter-formats
Task-5871301Payroll setup now offers a clearer closing-date selection, including the 15th of the month, ordered from month-end backwards. Employee onboarding screens show only relevant actions at the right time, and missing employer category warnings appear earlier on the dashboard so payroll issues can be addressed before payslip processing.
Original PR description
In this PR expected to update Payroll closing date in payroll config, where before picking the day of payroll fells weird because of the order and also not possible to choose the 15 og the month. Update to list all possible options from the last day ot the month below in decreasing order. During creation first employee, there are smartbuttone that better to show with specific condition - Salary adjustment -> Displayed only when an active contract exists. - Time off -> Displayed only after the employee record has been saved. - History -> Displayed only when the employee record has been saved. Update warning missing employer category, where before only visible in the payslip. Display the warning on the dashboard so users are awated upfront than discovering it later on Individual payslip. task-6438703
Rescheduling tasks in the Gantt view now keeps the same number of working hours between the planned start and end dates. This helps project schedules remain accurate when tasks are moved, reducing manual corrections for planners and managers.
Original PR description
When rescheduling tasks from gantt view, we should keep the number of working hours between the start and end dates of the task when rescheduling it --- task-5376423
Australian payroll can now include post-tax deductions on payslips that reduce net salary without being reported through Single Touch Payroll. The change also supports separate accounting treatment for different deduction types and refreshes year-to-date opening balances when new salary rules are added.
Original PR description
This commit allows post tax deductions to be added to the payslip without impacting STP. This also allows automatically creating opening balances entries for new salary rules. task - 6236042 Forward-Port-Of: odoo/enterprise#119952
Sale orders now keep combo product totals consistent when switching between tax-exclusive and tax-inclusive views. This prevents inflated order totals and gives sales teams and customers accurate pricing for combo items.
Original PR description
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines…
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines (e.g. 160.00). 4. Switch the document tax mode from "Tax Excl." to "Tax Incl." using the toggle at the top of the Order Lines tab. **Issue:** - After switching to "Tax Incl." mode, the total on the sale order is higher than the previous untaxed amount (e.g. shows 266.00 instead of the 160.00). - The same switch works correctly on regular (non-combo) product lines **Expected behavior:** - the new total should equal the previous untaxed amount. **Why this happens:** - `_onchange_order_line` is triggered on every `order_line` change, including when switching `document_tax_mode` causes `price_subtotal` to update on existing lines. - The unconditional write to `product_uom_qty` and `discount` on all combo item lines was calling '_compute_price_unit` even when neither value had changed. - `_compute_price_unit` then called `_reset_price_unit` under the new `document_tax_mode`, which re-calculated the stored `price_unit` instead of leaving it untouched for `_compute_amount` to reinterpret correctly. **Fix:** - Only sync `product_uom_qty` and `discount` to the combo item lines whose current values actually differ from the parent line. When no value has changed, no write occurs, so `_compute_price_unit` is not called. opw-6427963 Forward-Port-Of: odoo/odoo#280019
This fix restores automatic SInvoice submission for Vietnamese POS orders when the invoice option is selected. Businesses no longer need to manually send these e-invoices after validating a point-of-sale order, reducing missed submissions and extra admin work.
Original PR description
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a…
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a VN company, the e-invoice is NOT automatically submitted to SInvoice. Users must manually trigger the send wizard. ### Steps to reproduce: 1. Install l10n_vn_edi_viettel_pos, activate VN company 2. Make an order from POS and check the invoice box 3. Observe SInvoice subsmission error ### Cause of the issue: - caused by commit https://github.com/odoo/odoo/commit/4f30306ccc9ff82911f90ed8b3714b212e4b77dc, which decoupled invoice PDF generation from POS order validation by setting `generate_pdf=False` in context when `use_download_invoice` is False (default) - `_generate_pos_order_invoice()` to skip `_generate_and_send()`, which skips VN SInvoice submission. ### Fix: Override `_generate_pos_order_invoice()` to force generating PDF when auto-send to SInvoice is enabled, restoring `_generate_and_send()` during order validation opw-6427675 Forward-Port-Of: odoo/odoo#280932
Authorize.net refunds now correctly handle payments originally made by eCheck/ACH, not just credit cards. This prevents refund failures for settled bank-account payments and helps businesses process customer refunds more reliably.
Original PR description
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm…
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XX is invalid according to its datatype 'String' - The actual length is less than the MinLength value` **Expected behavior:** The refund should be processed successfully regardless of whether the original payment was made by credit card or eCheck (ACH) **Why this happens:** - The `refund()` method in `AuthorizeAPI` builds the refund request using a `creditCard` payment payload - When the original transaction was an ACH/eCheck payment, the `creditCard` key is absent from the transaction details returned by Authorize.net - The resulting request is rejected by Authorize.net because it does not satisfy the minimum length constraint for `cardNumber` **Fix:** - Detects whether the original payment used `creditCard` or `bankAccount` from the transaction details and build the appropriate payload according to Authorize.net API documentation: https://developer.authorize.net/api/reference/index.html#payment-transactions-credit-a-bank-account opw-6359726 Forward-Port-Of: odoo/odoo#282810 Forward-Port-Of: odoo/odoo#277742
Self-order purchases for event tickets now keep the selected ticket details through checkout and use the configured ticket price when recalculating totals. This prevents prices from unexpectedly changing to the underlying product price on the payment page, keeping customer charges consistent.
Original PR description
In this commit: - Ensure event ticket information is preserved during self-order processing and use the configured ticket price when recomputing order line prices. - This prevents ticket prices from being replaced by the product price after proceeding to payment and keeps the amounts consistent across the payment page. Task:6375899 Forward-Port-Of: odoo/odoo#282530 Forward-Port-Of: odoo/odoo#275645
Point of Sale now handles sale orders with existing down payments correctly when another down payment is made. This prevents confusing positive and negative duplicate lines on POS orders, improving order accuracy for staff and customers.
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#281397 Forward-Port-Of: odoo/odoo#275653
This fix ensures electronic invoices use the correct tax category when transactions involve a supplier or customer in the EEA, such as Swiss suppliers invoicing German customers. It helps avoid incorrect exemption labels and improves compliance for ZUGFeRD/Factur-X invoice reporting.
Original PR description
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax…
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing the ZUGFeRD template into the Accounting tab of his contact) 4. Send it and see that the tag <ram:CategoryCode> is setted as E instead of G ### Cause of the issue: The logic assigning the 'G' and 'K' tax category codes was only triggered if the supplier was located within the EEA. If the supplier was outside the EEA, the code bypassed this block entirely and fell back to the default 'E' code for 0% taxes. ### Reason to introduce the fix: Update the condition to trigger when either the supplier or the customer is in the EEA. This ensures that cross-border transactions involving at least one EEA party correctly evaluate and apply the 'G' (Export outside the EU) category code. Also the case supplier not in eea with VAT filled in + customer in eea + RC tax with amount != 0 is fixed now (letter G reported instead of S). ### Documentation: [eInvoicing technical guidance document_v1.pdf](https://github.com/user-attachments/files/30831749/eInvoicing.technical.guidance.document_v1.pdf) opw-6407399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283027 Forward-Port-Of: odoo/odoo#281245
Generated ISO 20022 payment files now include the state or province and second street line from partner and employee address records. This helps banks, especially in North America, accept wire transfers when complete beneficiary address details are required.
Original PR description
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street…
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street complement (suite, unit, ...) therefore never appear in the generated file, even when they are set on the partner, and there is no way to fix it from the record. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Return the state code and street2 alongside the other address components, from the partner for the base implementation and from the employee private address for the hr one, so the payment engine can write them in the PstlAdr block. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Companion enterprise PR emitting the state in the generated file: odoo/enterprise#127958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282620 Forward-Port-Of: odoo/odoo#282518
This fix restores several point-of-sale payment flows that stopped responding correctly after an internal payment method change. It prevents pending or waiting payments from getting stuck for Mercado Pago, Cashdro, Cashmatic, Safaricom, and bank QR code payments, improving checkout reliability for stores.
Original PR description
*: point_of_sale,pos_mercado_pago,pos_cashdro,pos_cashmatic, pos_safaricom d7a627160372 renamed the client-side payment interface attached to a pos.payment.method from `payment_terminal` to…
*: point_of_sale,pos_mercado_pago,pos_cashdro,pos_cashmatic, pos_safaricom d7a627160372 renamed the client-side payment interface attached to a pos.payment.method from `payment_terminal` to `payment_interface`, moved integrations off `payment_method_type` onto `payment_provider`, and renamed the `qr_code` type to `bank_qr_code`. Several call sites were left behind and now read attributes or compare against values that no longer exist, so they silently never match. Mercado Pago calls a method straight off the missing attribute, so an incoming webhook raises a TypeError and the payment line stays pending forever. The rest degrade silently: Cashdro and Cashmatic never cancel on Force Done, Safaricom never resolves the payment promise, and Bank QR lines left in `waiting` are no longer reset to `retry` when the session restarts, leaving them stuck. Use the existing `useBankQrCode` getter for the type check rather than repeating the literal. opw-6372208 Forward-Port-Of: odoo/odoo#278977
The Uzbekistan accounting setup now classifies current-year and period profit/loss accounts correctly so they are not counted twice in the balance sheet. This improves the accuracy of the Equity section in local financial reports.
Original PR description
Accounts 8710 (Current Year Profit/Loss) and 9910 (Net Profit for the Period) were equity_unaffected, causing their balances to be picked up both by the retained earnings tag-based formula and by the current-year-earnings domain formula in l10n_uz_reports, double- counting them in the balance sheet's Equity section. This commit changes both accounts' type to Equity and adds the BS Line 0540 tag to 9910 (8710 already carried it), so their balances are captured through the tag alone. see https://github.com/odoo/enterprise/pull/128124 see https://github.com/odoo/upgrade/pull/11048 task-6361059
Repair orders under warranty can now be completed when they include service lines linked to a quotation or invoice. The related sales or invoice line is correctly set to a zero price, preventing errors and ensuring warranty services are not charged.
Original PR description
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice. Steps to replicate: - Install `repair` with demo. - Create a new repair…
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice.
Steps to replicate:
- Install `repair` with demo.
- Create a new repair order with a customer and check `Under Warranty`.
- Click on the `Services` page and add a product.
- Click on `Quote` button.
- Return to the repair order through breadcrumbs.
- Click `Confirm Repair` > `Start Repair` > `End Repair`.
Error:
```
File '/home/odoo/odoo19/community/addons/repair/models/repair_service_line.py', line 120, in _update_repair_sale_order_line
self.price_unit = 0.0
^^^^^^^^^^^^^^^
AttributeError: 'repair.service.line' object has no attribute 'price_unit'
```
Cause:
- The error was introduced after a recent improvement [PR].
- The `repair.service.line` model does not contain a `price_unit` field, which causes the error.
- The `price_unit` field is present in the related Sale Order Line or Invoice Line.
Solution:
- The price of the linked Sale Order Line or Invoice Line is now set to zero when the product is under warranty.
[PR]: https://github.com/odoo/odoo/pull/260278/files#diff-1ff5f0c96411a07c366ef6410fc4580798593205b57d5740fbb4a56259341c98R102
sentry-7620551626
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278591This update fixes how simplified Italian electronic invoices are generated, including support for virtual stamp duty and correct use of the simplified format when selected. It also prevents simplified invoices from being used for unsuitable recipients, reducing compliance errors for Italian invoicing.
Original PR description
- Added the BolloVirtuale in the Simplified invoice template - Now it's possible to force the Simplified format on exported invoice when the `l10n_it_document_type` is set to a simplified one - Factored the Italian partner recognition (_l10n_it_edi_is_italian) - Added a check on the invoice, no simplified format for non-domestic / PA partners Task [link](https://www.odoo.com/odoo/project.task/6226436) task-6226436 Forward-Port-Of: odoo/odoo#283154 Forward-Port-Of: odoo/odoo#274493
When users try to archive an accounting journal that still has draft entries, the error message now points them to the correct place where those entries can be found and handled. The journal form button was also renamed so it accurately describes that it opens journal items, reducing confusion and helping users complete the archive process.
Original PR description
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent…
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent commit, leaving no common ancestor with 18.0. A PR in that state cannot be reopened, so this one continues from a clean branch with the exact same change. The review discussion is in that PR, and the rename asked for there is included here. ### Steps to reproduce 1. Go to `Accounting > Customers > Invoices` and create an invoice on a given journal, leaving it in draft. For the clearest case, leave it with no invoice line. 2. Go to `Accounting > Configuration > Journals`, open that journal and archive it. 3. `_check_auto_post_draft_entries` raises: *"You can not archive a journal containing draft journal entries. To proceed: 1/ click on the top-right button 'Journal Entries' from this journal form 2/ then filter on 'Draft' entries 3/ select them all and post or delete them through the action menu"*. 4. Follow those steps: click the `Journal Entries` smart button on the journal form. ### Current behaviour The list comes up empty, so the user concludes the error message is wrong, while the draft entries do exist. The instructions cannot be followed: - The smart button opens `action_account_moves_all_a`, which is named **"Journal Items"** and targets **`account.move.line`**, not `account.move`. The label of the button and the name of the action it opens do not match. - That action defaults to `search_default_posted: 1`, so no draft record is listed. - Draft entries with **no line at all** — commonly created through the incoming mail alias of a journal — have no `account.move.line`, so they stay invisible in that view even after switching the filter. - The action menu of a move line list offers no way to post or delete the entries, and the action sets `create: 0`. - The filter is labelled **"Unposted"**, not "Draft". The offending entries are only reachable through `Accounting > Accounting > Journal Entries`, filtering by journal and by "Unposted". ### Expected behaviour The error should point to a view where the records blocking the archiving are actually listed and actionable. ### This PR Two changes, the validation itself is unchanged: - The error message now points to `Accounting > Accounting > Journal Entries` and uses the real filter name, "Unposted". - The smart button of the journal form is renamed to **"Journal Items"**, so its label matches the action it opens and no longer suggests it lists journal entries. This was asked for in the review of the previous PR. Targeted at 18.0 because that is where the misleading message is being hit in practice; it is identical on 19.0 and master. If a translatable string change does not qualify for the stable series, tell me and I will retarget to master. Forward-Port-Of: odoo/odoo#282956
Fixes invoice reports so returned dropshipped products no longer show incorrect lot or serial numbers. This helps customers and staff see accurate product tracking information on invoices and credit-note scenarios.
Original PR description
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print on the invoice
-> The generated PDF displays "lot1 & lot2" instead of "lot1"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 2` since the invoice is on a quantity of 2 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic (as they should be): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80
- for the last one, `is_stock_return = False` while it should not, thus the quantity is 1 instead of 0. Furthermore, it does not pass by this code:
https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/sale_stock/models/account_move.py#L79 which would make the quantity for lot2 equalled to 0 (1-1) The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 1, lot2: 0}`
The report selects both lots since it starts with lot1 (qty of 1): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6236855
Forward-Port-Of: odoo/odoo#271282
Forward-Port-Of: odoo/odoo#270599When users update analytic distributions on multiple journal items and create a new distribution model, the creation dialog now remains open so they can finish and save it. This prevents failed or interrupted bulk updates in accounting workflows.
Original PR description
When mass-editing the Analytic Distribution field on several records at once, and creating a new distribution at once, will close the creation dialog before the user could fill it in. Steps to reproduce: - Enable Analytic Accounting - Open Accounting > Journal Items - Enable the Analytic Distribution column - Select 2 journal items and click on the Analytic Distribution - Click on 'Update', fill a distribution, then click "New Model" - Confirm the multi-edit update Issue: The create Analytic Distribution model dialog closes on its own instead of staying open, so the model can never be saved. Analysis: After https://github.com/odoo/odoo/commit/12a61fa5ab7c56a42020c50c683df8ed52f1fb01, in multi-edit, save() ends reloading the list, unmounting the AnalyticDistribution widget, that closes the model dialog it just opened. opw-6405219 Forward-Port-Of: odoo/odoo#281141
Fixes several issues with light users so their role, account status, and employee confirmation indicators behave correctly. It also prevents light users from requesting app installations and adds a demo light user for easier testing and demonstration.
Original PR description
Following light users merge, a few points need to be fixed or modified: - Fix User status Search method - Unstore user role and add search method. - Fix confirmed icon in employee_user_status widget - Remove Apps icon for light users - Switching to light user role is setting the role to user back immediately. - Add Demo Light User More details in commit messages. Task-6476390
Customers editing their portal address in Morocco now receive a clear error when entering an invalid ICE identifier, instead of the save failing silently and logging a backend validation error. This improves the self-service address update experience and reduces confusion or support requests.
Original PR description
Steps: - Install l10n_ma module. - Go to Address page in portal. - Select Morocco country. - Set any random invalid value for ICE input. Issue: - It wont allow to save address and will not give any error or suggestion instead it raises validation error in logger. Cause: - Since recent [fix](https://github.com/odoo/odoo/pull/271969) invalid additional_identifier raises an error for invalid values and in portal we can't display those error directly. Fix: - Validate `additional_identifier` in validate address values and and mark those identifier as invalid field for invalid values to give proper error message and not raise validation error. Also skip `_validate_identifier` for `no_vat_validation` context in creation since we already validate those identifier values. Forward-Port-Of: odoo/odoo#279308
Fixes an accounting issue where reposting an opening journal entry after resetting it to draft could duplicate related bank statements, statement lines, and payment moves. This helps keep opening balances accurate and prevents extra cleanup work for finance teams.
Original PR description
When the Opening journal entry is reset to draft and then posted again, it duplicates the statement, statement lines, and payment moves linked to the opening balance. This commit ensure no duplicate is created task-6395990
The call debrief panel no longer shows a confusing red error when call timing details are not yet available during ringing or ongoing calls. It also avoids showing temporary speech-to-text processing files as duplicate playable audio, while still keeping real error feedback for loading problems.
Original PR description
Previously, missing start/end datetimes on the parent record displayed a bright-red error banner: "CallDebrief widget needs start and end datetime from the parent record." Since missing dates are expected during ongoing or ringing calls, this message is confusing and unappealing. The widget now silently skips timing initialization, collapsing cleanly until the call is completed. We preserve the error state logic for other actual database or loading failures so that users still receive proper feedback when those occur. Task-6478747 **Enterprise Sibling https://github.com/odoo/enterprise/pull/128185**
This fixes an inventory issue where reducing a delivery quantity could leave the wrong amount reserved when the order and operation lines used different units of measure. Businesses get more accurate stock reservations and transfer quantities, especially when products are handled in packs, dozens, or individual units.
Original PR description
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move…
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the move quantity from 2 to 1 Dozen The move line ends up with 23 Units instead of 12: the decrease of 1 Dozen is applied as 1 Unit on the line and considered fully processed. The remaining 11 units stay reserved and counted on the transfer. Convert the remaining decrease from the move unit to the line unit when taking it from a line, and the taken quantity back to the move unit when updating the remaining decrease. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278411 Forward-Port-Of: odoo/odoo#276774
This update makes Latin American check management clearer and more reliable by improving labels, list behavior, and the visibility of key check details. It also fixes how the system determines whether a check is still on hand, reducing reporting mistakes and preventing changes that could leave checks recorded in the wrong location.
Original PR description
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to…
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to Customer/Vendor depending on the context. - Display the memo and the initial payment's date on the 3rd party checks views. task-5247520 ### Commit 2: [FIX] l10n_latam_check: base checks location on a real on_hand field **Problem 1: On Hand** Whether a check was still on hand had no field of its own: it was computed based on the current_journal_id of the check, while the "On hand" filter approximated it through the payment methods of the check's current journal. The two could disagree, and neither could be searched or grouped on. Expose it as an on_hand computed field, with a compute_sql counterpart so it stays searchable. A check is On Hand if its last posted operation was registered on a cash journal. **Problem 2: Last operation** The sorting of the operations of a check was mostly relying on the payment_date then the write_date and finally the ID. For payments that are registered on the same day, the computation was often wrong as soon as an older payment was edited afterwards, which sent the check back to the journal it had already left. This commit adds a key to the sorting: we now secondly rely on the Journal Entry ID of the payment, which should always exists for posted payments with a check, and is created at posting of the payments so it somehow acts as timestamp of the posting, it also won't re-order if the payments would be reset to draft and re-posted. Finally, and even with changes above, we decided that resetting or cancelling an operation in the middle of the chain of operations should be prevented. It left the check recorded where it no longer was. Note that it is still possible to reset the whole chain at once, or the last operation(s). task-5247520
This fixes an error that could block French branch companies from activating PDP electronic invoicing when their parent company was also selected. Branches now correctly use the parent company's accounting setup, allowing the activation settings to save successfully.
Original PR description
**Steps to reproduce:** * Create a **French** parent company and a branch. * Activate **Electronic Invoicing (PDP)** for the parent company. * Switch to the branch while keeping both the **parent…
**Steps to reproduce:**
* Create a **French** parent company and a branch.
* Activate **Electronic Invoicing (PDP)** for the parent company.
* Switch to the branch while keeping both the **parent company** and the **branch** selected in the company switcher.
* Go to **Settings → French Localization → Activate Electronic Invoicing**.
* Activate **Electronic Invoicing (PDP)** for the branch.
* Select the **Participate in the pilot phase** checkbox and try to save settings.
**Observed behavior:**
* A traceback occurs with the error: `psycopg2.errors.SyntaxError: syntax error at or near ")"` on `IN ()` in the SQL query inside `_force_update_l10n_fr_f10_moves`.
**Cause:**
* `_force_update_l10n_fr_f10_moves` searches for receivable/payable accounts using `company_ids IN companies.ids`.
* A branch company has no accounts assigned directly to it — accounts belong to the parent company — so the search returns an empty list.
* Passing an empty tuple to `IN %(account_ids)s` generates `IN ()`, which is invalid PostgreSQL syntax.
**Fix:**
* Replace `('company_ids', 'in', companies.ids)` with
`('company_ids', 'parent_of', companies.ids)` in the account search
inside `_force_update_l10n_fr_f10_moves`.
* This ensures that accounts owned by a parent company are correctly
found when the given companies are branches, since branch companies
inherit their parent's chart of accounts.
opw-6394650
Forward-Port-Of: odoo/odoo#282849
Forward-Port-Of: odoo/odoo#277232DIN 5008 business documents now show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user's language settings. Footer company register details are also shown more appropriately, avoiding Germany-specific wording where it does not apply.
Original PR description
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document…
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Observed behavior (commercial register):**
* The footer always shows `HRB-Nr.:` regardless of whether the company has a commercial register entry.
* The abbreviation `HRB-Nr.:` appears even for Austrian and Swiss companies, where the commercial register number is a German-specific concept.
* In the company form view, the field is labeled generically as "Company ID" instead of "Commercial Register Number" for German companies.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Cause (commercial register):**
* The footer renders `company.company_registry` unconditionally with no country guard and no label.
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
**Fix (commercial register):**
* Remove the hardcoded `HRB-Nr.:` label from the footer and instead render `company.partner_id.company_registry_label` (which is country-aware).
* Update the duplicate contact warning message to use the country-aware label via `company.partner_id.company_registry_label`, backed by a new `_get_company_registry_labels` override in l10n_de that registers `Commercial Register Number` for `DE`.
* In the company form view (`l10n_de`), hide the generic "Company ID" field for German companies and show a relabeled instance with `string="Commercial Register Number"` instead.
opw-6392649
Forward-Port-Of: odoo/odoo#283315
Forward-Port-Of: odoo/odoo#279085This fix ensures Malta tax grid assignments are updated correctly when databases are upgraded. It prevents taxes from keeping outdated reporting grids, helping future journal entries and tax reports use the correct Maltese localization setup.
Original PR description
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids…
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids remain unchanged after the upgrade and do not reflect the modifications introduced in [1]. The tax definitions are loaded from CSV data and don't happen during upgrade or module update it did through try_loading". Since the account tags already exist in upgraded databases, the changes are not applied during module loading and the updated grid assignments are not assigned to taxes. **Fix:** Apply the grid update directly through SQL during the upgrade or module update. The change is limited to tax grid assignments and does not require a full tax reload using ``try_loading`` or ``load_data``. **Before fix:** <img width="1458" height="724" alt="image" src="https://github.com/user-attachments/assets/eaac5e3f-d551-4ec0-b282-bb39a50438f9" /> **After fix:** <img width="1240" height="583" alt="image" src="https://github.com/user-attachments/assets/74409c53-dce0-45b2-a6b5-e60f5c2d826d" /> Note: why this fix is needed because existing upgrade script do update move line grid but still tax have the old grid which is weird and will cause issue when journal entry will create. [1]: https://github.com/odoo/odoo/pull/254894/changes/8921186850e31c53072d49a5dc760192f3edb902 opw-6325845 upg-4391393 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272038
Fixed an issue where switching the AI agent to a pivot view could cause the view to crash or open without selected measures. The pivot view now waits until it is ready before AI adjustments are applied, preserving default measures when none are requested.
Original PR description
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving…
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving the `APPLY_AI_ADJUST_MODEL` bus event. However, the event could be processed while the pivot model was still executing `_loadData()`. In that case, the following sequence occurred: * `_loadData()` started and awaited. * The controller patch was executed. * The patch called `toggleMeasures()`. * `toggleMeasures()` waited for `_loadData()` to complete. * `_loadData()` finished and updated the metadata with the available measures. * `toggleMeasures()` resumed and wrote back the metadata snapshot it had taken before waiting. Since `toggleMeasures()` operates on a snapshot of the metadata, the measures populated by `_loadData()` were lost when the snapshot replaced the current metadata, leaving the pivot model without its `measures` metadata and causing the view to crash. Prevent this race condition by waiting for the pivot model initialization to complete before applying the AI adjustments. Also preserve the default active measures when the AI agent does not explicitly request any measures instead of clearing them and opening an empty pivot view. task-6384368 Forward-Port-Of: odoo/enterprise#125897
The India salary simulation now avoids running an unnecessary tax calculation when the popup opens. This prevents newly entered values from being cleared and stops misleading missing-field errors for users testing regular pay structures.
Original PR description
Steps :- - On opening the Simulation when India: Regular pay structure is selected, throws "Missing required fields" when fields are changes on form view. Fix:- - For Indian company, the TDS calculation ran in the background while opening the popup, and it was clearing the values just entered. This calculation isn't needed for a simulation, so it is now skipped. task-6392171 Forward-Port-Of: odoo/enterprise#126483
Kenyan POS receipts now generate the tax authority QR code whenever the required signature is available, instead of depending on an order status that could prevent the URL from appearing. This helps ensure customers receive receipts with the expected SCU information after validated POS orders.
Original PR description
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the…
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the l10n_ke module in 'production' mode * Make an order in POS and validate it > Observation: The receipt doesn't contain the SCU information and QR Why the fix: ------------ Based on the receipt screenshot shared on the ticket (from Odoo 19.3) we can see that some informations are shown on the ticket. The information shown are the one received from the etims api, it means the call went through and the response was received. As the qrCode URL only needs `l10n_ke_oscu_signature` to be generated, we can assume that if this field is set we can safely generate the URL and generate the QR code. https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/models/pos_order.py#L252-L256 Based on this assumption we can change the condition to return the URL or not based on the presence of `l10n_ke_oscu_signature` instead of the state of the order being `sent`. In 19.0, the receipt is showing no info at all (when 19.3 is showing some info like the signature). This is also happening because the URL was falsy. And when that is the case we do not show any SCU information https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/static/src/overrides/components/order_receipt/order_receipt.xml#L56 opw-6352120 Forward-Port-Of: odoo/enterprise#127045
This fixes Belgian payroll sick leave handling so a second long sickness period is split correctly after the first 30 days when it is not marked as a relapse. It helps ensure leave classification and payroll calculations follow the expected rules for independent sickness periods.
Original PR description
Steps to reproduce: - Create a STO for an employee of more than 30 days -> this period is split in 30 days STO and x days SGS. - Within the relapse period, create a second STO of more than 30 days and leave the relapse field empty (which is fine if the second STO is not related to the first sickness) -> the period should be split after the first 30 days just like the first STO, but it remains an STO for the whole duration. task-6296152 Forward-Port-Of: odoo/enterprise#128101
Belgian payroll now values assimilated absence periods using the employee's salary at the time of each absence, rather than applying one later salary to all periods. This ensures departure holiday attestations and December double holiday regularizations are calculated more accurately when salaries change during the year.
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 Forward-Port-Of: odoo/enterprise#122848
The Timesheet Assistant now includes time from very small events by adding it to matching larger events instead of ignoring it. This helps suggested timesheets reflect a more accurate total time for users.
Original PR description
## Previous Behavior Before this PR: When events were to small to suggestion Timesheet Assistant would completely discard these events. This lead to a suggestion haveing a lower total time than it should. ## New Expected Behavior After this PR: When an event is too small to suggest and shares its name and group with one or more larger event, the duration of the smaller event is added to the last event with the same name and groupe. task-[6452987](https://www.odoo.com/odoo/project/4105/tasks/6452987) Forward-Port-Of: odoo/enterprise#127915 Forward-Port-Of: odoo/enterprise#127167
The Timesheet Assistant no longer interrupts ongoing always-active activities, such as meetings, with away-from-keyboard entries. This gives users cleaner suggestions, more accurate away-time durations, and corrected Google Meet descriptions.
Original PR description
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet…
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet description was incorrect. ## Steps to Reproduce: 1. Generate an always-active event (e.g., join a meeting in Google Meet). 2. Generate non-key events (e.g., visit a website without an ActivityWatch rule). 3. Go AFK. 4. Generate a new non-key event. 5. The Timesheet Assistant will show three suggestions in the following order: an always-active suggestion, an AFK suggestion, and another always-active suggestion for the same activity. ## New Expected Behavior After this PR: The Timesheet Assistant now blocks the creation of AFK suggestions when the previous key event is marked as always-active. AFK event durations have been updated to ensure their values are accurate. The Google Meet description has also been corrected. task-[6431526](https://www.odoo.com/odoo/project/4105/tasks/6431526) Forward-Port-Of: odoo/enterprise#127299 Forward-Port-Of: odoo/enterprise#127028
This fix ensures salary package benefit fields can be selected correctly, including country-specific benefit fields that were previously excluded. It also prevents an error when saving public benefit field selections, improving reliability for HR salary configuration.
Original PR description
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The…
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The advantage of the whitelist is that it factored in for the allowed countries, so instead of duplicating this logic to benefit fields and implementing it in every l10n, we can check which module the field comes from.
example:
The field [`company_car_total_depreciated_cost`](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_payroll_fleet/models/hr_version.py#L62) cannot be selected as `res_field_id` when it should be possible as we see in the [data](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_contract_salary/data/hr_contract_salary_benefit_data.xml#L6), it is not whitelisted because we dont want to copy its value from a template.
2- Another fix is the inverse of the public field, there's a traceback because the selection field is always converted to a string and cannot be used to browse as is.
```py
File "/data/build/enterprise/hr_contract_salary/models/hr_contract_salary_benefit.py", line 238, in _inverse_res_field_public
record.res_field_id = self.sudo().env['ir.model.fields'].browse(record.res_field_public)
^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields.py", line 1890, in __set__
write_value = self.convert_to_write(value, records)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_relational.py", line 387, in convert_to_write
return value.id
^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_misc.py", line 115, in __get__
raise ValueError("Expected singleton: %s" % record) from None
ValueError: Expected singleton: ir.model.fields('1', '7', '3', '8', '4')
```
Forward-Port-Of: odoo/enterprise#128275
Forward-Port-Of: odoo/enterprise#127743ISO 20022 payment files now include the vendor's state or province and second address line when available. This helps prevent North American bank transfer rejections caused by incomplete beneficiary address details.
Original PR description
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but…
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but _get_PstlAdr() also needs to write them out. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Emit CtrySubDvsn when the address has a state, before Ctry as required by the element order of the PostalAddress schema, and append street2 to the street address line. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Requires odoo/odoo#282518, which makes _get_all_addr() return the state and street2. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#128021 Forward-Port-Of: odoo/enterprise#127958
Payroll validation now correctly opens any required follow-up screen, such as a wizard for missing employee information, instead of silently doing nothing. This helps payroll users understand and resolve validation blockers immediately.
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 Forward-Port-Of: odoo/enterprise#127668
Swiss payroll now uses the employee’s requested time off dates when calculating absence days for flexible schedules. This prevents a one-day leave from being counted as two days due to timezone conversion, helping keep regular wage and accident salary calculations 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 Forward-Port-Of: odoo/enterprise#127849 Forward-Port-Of: odoo/enterprise#127513
Fixed an issue where the online cart could crash after a rental product was changed back into a regular sales order by removing its rental period. The cart now only shows rental period details when the order is actually still a rental, improving checkout reliability for affected customers.
Original PR description
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install…
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install `website_sale_renting` with demo. - Open website > shop > add the product named `Projector`. - Click Ecommerce in the menu bar > Orders . - Remove the `Confirmed` filter > Click on the top order (should be containing the projector product.) - Remove the `Rental Period` and go to the cart. Error: ``` QWebError: Error while rendering the template: AttributeError: 'bool' object has no attribute 'time' Template: website_sale.shorter_cart_summary ``` Cause: - When the user removes the rental period (`rental_start_date` and `rental_end_date`), both fields are set to `False`. When the cart is opened again, these values trigger the error in [line]. - Since the rental period has been removed from the order, the order is converted to a regular Sales Order (see [PR] and its [task]). Therefore, the Rental Period should no longer be displayed. Solution: - Use `is_rental_order` to determine whether to render the rental period instead of `has_rentable_lines`, since `has_rentable_lines `only checks whether the product is rentable [1], which is determined by the product's `rental_periodicity` [2]. - `is_rental_order` is a better check here because it indicates whether the rental period is actually defined on the order [3]. [line]: https://github.com/odoo/enterprise/blob/7c80c9ffa9e7812267f2ac285e3a3fc5ca501814/website_sale_renting/views/templates.xml#L207 [task]: https://www.odoo.com/odoo/all-tasks/6003684 [PR]: https://github.com/odoo/enterprise/pull/106381/commits/56ec41d81f7536f047a1586a12ea6f6e8414b844 [1]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L140-L143 [2]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order_line.py#L61-L64 [3]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L135-L138 sentry-7663524549 Forward-Port-Of: odoo/enterprise#128084
The Uzbek balance sheet now includes unclosed profit or loss from the current year in the Equity section. This prevents the report from appearing unbalanced before year-end closing while preserving the official report line numbering.
Original PR description
The Uzbek balance sheet was unbalanced because the current year's unclosed profit/loss was not reflected in the Equity section. This commit restructures '[0540] - Retained Earnings' into an aggregate of three lines: realized retained earnings (existing tag-based formula), current year unallocated earnings, and previous years' unallocated earnings, the latter two computed from income, expense and equity_unaffected accounts, scoped to the current and prior fiscal years respectively. This keeps the balance sheet correct both before and after year-end closing, without changing the report's official line numbering. see https://github.com/odoo/odoo/pull/282779 see https://github.com/odoo/upgrade/pull/11048 task-6361059
This update fixes several usability issues in the Sign and Documents Sign flows, especially on mobile and small screens. Users can now more reliably upload, select, send, and cancel signing requests without empty menus or misaligned controls getting in the way.
Original PR description
- show the sample document button on mobile - do not open an empty signer list when there is only one signer - hide the settings menu when it is empty - allow a signer to cancel the request while signing - align the signer rows in the send request wizard - select the document instead of opening it when importing from Documents - fix the Upload button on the empty page task-6395329
The Philippine payroll module now calculates employer cost using cash earnings, employer contributions, and 13th month pay. This gives businesses a more complete and accurate view of employment costs for payroll accounting and reporting.
Original PR description
Calculate employer cost as the sum of all rules under the Cash Earnings, Employer's Contributions categories and 13th month pay. task-6371975
Employer cost totals on Hong Kong payroll payslips have been corrected so they better reflect the employer-paid amounts used in payroll reporting. This helps businesses review payroll costs more accurately, including special payments, reimbursements, expenses, and non-employee salary handling.
Original PR description
The employer cost shown on payslips was incorrect. Employer cost is now the sum of the Gross-Cash, SLSP, ERMPF, FEE, and COMP categories, reflecting cash wages, severance and long service payments, the employer's own MPF contributions, non-employee fees, and other employer-paid benefits. task-5964455
The timesheet timer now only shows entries linked to the user's active companies. This prevents users from running into access errors when editing timesheets that belong to another company context.
Original PR description
### before: get all timesheets in the timesheet systray, this cause access error when trying to edit a timesheet not inside the active company ### after: only the timesheets linked to active companies should be displayed in the timer --- task-6216931
Fixed an issue in Belgian payroll where dismissing the company car update confirmation could leave the backend unresponsive. Users can now safely cancel the prompt without needing to refresh the page, preventing disruption during payroll and DMFA workflows.
Original PR description
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian…
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian employee - Create a DMFA covering that quarter and mark it as done - Change the company car of that employee and save - Click Discard (or the cross) on the confirmation dialog onWillSaveRecord is called from within Record._save, which itself runs inside the model mutex. Awaiting record.discard() from there queued the discard behind the very save that was waiting for it, so neither promise ever settled. Since the save was dispatched through executeButtonCallback, every button of the view and of the overlay container stayed disabled, and the mutex stayed blocked for the rest of the page life, making any later save or discard hang as well. Fire the discard without awaiting it, the way account's currency form controller already does: the hook returns false, the save releases the mutex, and the queued discard then reverts the record. task-6463069
This update fixes issues in Point of Sale screens caused by a framework upgrade. Users can now type in the ticket search box without their input being reset, and order status changes are handled more reliably.
Original PR description
OWL3's useEffect takes one argument, so the OWL2 deps callback is dropped: typing in the ticket-screen search box was overwritten by the default term. From odoo/enterprise#111749 (pos_urban_piper) and #122791 (pos_enterprise). useOnChange for searchInput, which is user-writable and cannot be derived. pos_enterprise needed no effect: isStageChanging = computed(...) replaces it.
This fix corrects how negative manufacturing movements are handled in enterprise reporting. It helps keep manufacturing cost reports accurate when products or costs move out negatively, reducing the risk of misleading financial analysis.
This fixes several issues in call debriefing and VoIP transcription, including a crash when requesting a transcription, duplicate audio playback during pending transcription, and failed transcription requests caused by inconsistent audio file formats. Business users should see a smoother, more reliable call review experience with fewer interruptions.
Original PR description
Prior to this commit, clicking the "Request Transcription" button crashed the client because `t-on-click="onClickTranscribe"` was missing the `this.` prefix. This commit adds `this.` to the click handler in the template so that Owl correctly finds and calls the method on the component. task-6478747 **Community Sibling https://github.com/odoo/odoo/pull/282908**
DIN 5008 PDF documents now consistently show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user’s language settings. This prevents invoices, quotations, purchase orders, follow-ups, and field service documents from displaying confusing or non-compliant date formats.
Original PR description
* = din5008_account_followup, din5008_industry_fsm **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document layout to **DIN…
* = din5008_account_followup, din5008_industry_fsm
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
opw-6392649
Forward-Port-Of: odoo/enterprise#128453
Forward-Port-Of: odoo/enterprise#126006Fixed an issue where DHL return label creation could fail when a sales order included incoterms. The system now sends the required incoterm code correctly, helping users complete deliveries without errors.
Original PR description
Issue ----- When "return" is enabled, users get a traceback if the SO has incoterms. Steps to reproduce ----- - Set up DHL - enable return labels - Create a SO with incoterms & confirm it - Confirm the delivery > Traceback Cause ----- The request sent for the return label contains the incoterm record instead of its' code like in `dhl_rest_send_shipping` https://github.com/odoo/enterprise/blob/f6c94d4ca3ef4211a5ab00bf0b39f6a7675c8f79/delivery_dhl_rest/models/delivery_dhl.py#L371-L372 Which is not JSON serializable ----- Ticket: opw-6430371 Forward-Port-Of: odoo/enterprise#126459
Original PR description
pos*: point_of_sale, pos_loyalty, pos_hr, pos_online_payment, pos_stock, l10n_in_pos, l10n_id_pos Refactor the customer display communication to make it more efficient, decouple the terminal and…
pos*: point_of_sale, pos_loyalty, pos_hr, pos_online_payment, pos_stock,
l10n_in_pos, l10n_id_pos
Refactor the customer display communication to make it more efficient,
decouple the terminal and display sides, and avoid unnecessary requests
when no display is connected.
- Replace the effect on `pos_service` with targeted listeners on order-related events.
- Split `customerDisplayService` into two OWL plugins: `CustomerDisplayTerminalPlugin` for the PoS terminal and `CustomerDisplayPlugin` for the customer display.
- Centralize payload generation through `GeneratePrinterData` and remove the deprecated `CustomerDisplayPosAdapter`.
- Replace `device_uuid` with a `device_identifier` generated by `DeviceIdentifierSequence`.
- Use a registration route to track connected customer displays: displays announce themselves with `ADD` and `REMOVE`, while terminals use `PING` to discover displays after startup or reload.
- Skip payload generation and requests when no customer display is connected.
- Refactor customer display tests to exercise the real application flow and assert against system-generated payloads.
```mermaid
flowchart LR
POS([PosStore])
UI([Customer display UI])
subgraph Terminal["CustomerDisplayTerminalPlugin — app/plugins"]
direction TB
initT["init({ identifier, models, scale, bus, ... })"]
sendOrder["sendOrder(order)"]
build["_buildDisplayPayload()"]
send["send(payload)"]
sendOrder --> build --> send
end
subgraph DisplaySide["CustomerDisplayPlugin — customer_display"]
direction TB
initD["init({ bus })"]
onData["_onDataReceived()"]
data[("data — signal")]
onData --> data
end
POS -->|initCustomerDisplay| initT
POS -->|order or screen changed| sendOrder
UI -->|mounted| initD
send -->|"update_customer_display — bus"| onData
send -.->|"BroadcastChannel — only if the request fails"| onData
data -->|render| UI
```
Task-5911881Point of Sale customer display updates are now handled through a centralized communication component instead of depending on broader service activity. This should reduce unnecessary processing and make connected display and scale integrations more consistent across supported POS setups.
Original PR description
pos*: pos_iot, pos_mobile, l10n_eu_iot_scale_cert Customer display previously relied on an effect on `pos_service` to dispatch updates, which was inefficient and unnecessarily dependent on the full service lifecycle while only order data was required. This commit refactors and centralizes the customer display logic: - Replace effect-based updates with targeted event listeners on order-related events to reduce overhead and improve performance - Make `customerDisplayService` the single source of truth for all customer display communication (send/receive) - Standardize payload generation using `GeneratePrinterData` And remove deprecated `CustomerDisplayPosAdapter` - Replace `device_uuid` with `device_identifier` generated via `DeviceIdentifierSequence` for consistent device identification Task-5911881 Related PR: - https://github.com/odoo/odoo/pull/257781