Daily updates from Odoo
Tuesday, July 28, 2026
344 changes
11 changes
Resolved issues and error corrections
This update corrects Swedish ISO 20022 payment files so they match Swedbank's required identifiers and scheme values. It reduces the risk of bank payment files being rejected and also updates Swedish address formatting ahead of upcoming structured address requirements.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-5395736
Forward-Port-Of: odoo/enterprise#125676
Forward-Port-Of: odoo/enterprise#122119This fix prevents the timesheet assistant from crashing when away-time activity is processed without an expected unmatched group. Users can continue reviewing and categorizing time entries without interruption.
Original PR description
Before this commit, when the unmatched group is not found in events before processing afk event, a traceback occurs saying `Cannot read properties of undefined (reading 'Away (afk status 1)')` This commit moves the code checking the group key exists in `this.state.grouped` after processing afk event and before adding the afk event in unmatched group. Forward-Port-Of: odoo/enterprise#124072 Forward-Port-Of: odoo/enterprise#123452
Resetting a tax return now only removes accounting entries that were created for recoverable amounts from earlier tax returns. This prevents invoices or other reconciled entries from being accidentally deleted, protecting accounting records from unintended data loss.
Original PR description
Issue: Moves having a line reconciled to a tax return are unlinked if the tax return is reset. Steps to reproduce: - Set the tax account as reconcilable - Create an invoice for previous month and confirm it - Create a tax return for the previous month - Reconcile one of the invoice tax line to the tax return closing move. - Remove the lock date - Reset the tax return Current behavior: - all moves reconciled with the tax return are unlinked Expected behavior: - only moves comming from recoverable amount of previous tax returns should be unlinked opw-6370289 Forward-Port-Of: odoo/enterprise#123947
Fixes several issues affecting cumulative translation adjustment lines in financial reports. Trial balance and general ledger outputs now better respect horizontal groups, search filters, and fiscal-year dates, reducing the risk of confusing or incorrect report totals.
Original PR description
The engine for the cumulative translation adjustment line was fully overriding the forced options, but this key might already be present in the options, for example, when using horizontal groups. task-6418960 Forward-Port-Of: odoo/enterprise#124108
Fixed an issue that could prevent Belgian payroll users from opening the Payroll dashboard when multiple CP200 employees had recently updated contracts. The minimum wage warning now evaluates employees correctly, helping payroll teams access their dashboard reliably.
Original PR description
Opening the Payroll dashboard may crashes with an error: - Have a Belgian company with 2 or more CP200 employees having active contracts - Create or modify a contract for at least 2 of them (this marks l10n_be_computed_seniority_years as dirty for the batch) - Open the Payroll dashboard, the "Employees Under Minimum Wage" warning evaluation crashes In _compute_l10n_be_computed_seniority, the for version in cp200_versions loop was incorrectly referencing self instead of version. Since self is the full batch recordset, self.employee_id returns a multi-record set, causing ensure_one() to fail inside _get_first_version_date. task-6358718
When a Colombian electronic invoice is issued from a branch, the XML now uses the parent company's legal name instead of the branch name. This helps DIAN correctly match the invoice to the company's tax ID and reduces the risk of rejected electronic invoices.
Original PR description
The correct behavior should be to use the original company name in this specific XML tag For the DIAN, branch names will not be recognized as related to the NIT. So, when sending electronic invoices from a branch, the XML should use the name of the parent company of that branch. Ticket [link](https://www.odoo.com/odoo/project.task/6074280) opw-6074280 Forward-Port-Of: odoo/enterprise#125383 Forward-Port-Of: odoo/enterprise#115494
When equipment is manually removed from a field service shift, later edits such as changing shift times or signing in no longer add it back automatically. This helps teams keep shift equipment lists accurate while still refreshing the list when the customer is changed.
Original PR description
Issue: When a user manually removes a specific equipment (SN) from a shift's list, editing the shift times or signing in reloads the entire list, bringing the deleted equipment back. Solution: Skip reassignment if the currently selected lots (`._origin`) are a valid subset of the customer's total equipment. This preserves manual deletions while still correctly updating the list if the customer is completely changed. Task: 6346404
Spanish VAT record book exports now include taxable accounting entries created outside standard invoices and bills, such as Point of Sale session closures. This helps businesses produce more complete VAT records and reduces the risk of missing taxable POS activity in compliance reports.
Original PR description
Currently, the Spanish VAT record books (Libros Registro de IVA) only include move types associated with invoices and bills. However, miscellaneous entries (type 'entry'), such as those generated by the Point of Sale session closures or manual liquidations, also carry tax obligations and must be reflected in these reports. Steps to reproduce: - Open a POS Session - Create an order, pay and close session - Go to Accouting > Reporting > Tax report - Select Generic Tax report - Print "VAT record Books" Issue: Only invoices and bills are visible in the excel file, and not the entry generated from point of sale. However, movements that are not related to invoices should be included in the VAT books. opw-5862529 Forward-Port-Of: odoo/enterprise#125631 Forward-Port-Of: odoo/enterprise#113681
Belgian payroll withholding tax reductions now apply correctly for disabled employees, disabled spouses, and spouses with low or no income, even when there are no dependent juniors or seniors. The update helps ensure affected employees receive the correct payroll tax treatment and clarifies spouse fiscal threshold wording.
Original PR description
Prior to this commit, the reductions for disabled employees, disabled spouse, and spouse with low or no income did not apply if the employee did not have any depenedent juniors or seniors. This commit fixes that, by removing the unneeded condition, and applying the reductions for those employees. This commit also updates the text for the thresholds of the spouse's fiscal situation. task-6384236 task-6320606 Forward-Port-Of: odoo/enterprise#124803
Marketing campaigns no longer crash when a user clears the Target field while editing a campaign. This keeps campaign setup stable and avoids an unexpected error during normal data entry.
Original PR description
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` >…
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` > `Campaigns`. - Create a `new campaign` and clear the `Target` field. `KeyError: False` After the recent commit that added the recipients_count field and its computation [1], when the user removes model_id(Target), model_name is set to False [2]. The domain is then updated by a compute method, which triggers the computation of recipients_count. Since the computation only checks whether domain is set and does not verify that model_name is available, it attempts to access the model using model_name, raising the error [3]. This commit ensures that, when computing the recipient count, it also checks that model_name is set. Since model_id is a required field, once it is set, the recipient count is computed correctly based on the domain and model_name. [recent commit]: https://github.com/odoo/enterprise/commit/5485e8eaa7636c7dd0b305b4e26fb772aff6d030 [1]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L43 [2]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L33 [3]- https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L146-L148 sentry-7612724367
The timesheet assistant now lets long description fields expand so users can read the full content instead of seeing it cut off. This makes reviewing and editing timesheet entries clearer and reduces the chance of missing important details.
Original PR description
- changed the description field to expand dynamically to display long descriptions in full instead of truncating them in the assistant Task-6348575 Forward-Port-Of: odoo/enterprise#124806 Forward-Port-Of: odoo/enterprise#123428
1 change
Resolved issues and error corrections
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c
Original PR description
**Steps to reproduce:** - Enable 2FA - Change user language - Log in in another private window / device - Check the notification email of a login with another device - Email body/subject are not properly adapted to user language **Issue:** View manual rendering doesn't pass the user language. **Fix:** Add it to the context before `_render_template` and subject translation (reapply similar fix [1]). [1] https://github.com/odoo/odoo/commit/4d8d1736ca03a3d6b4e86cbc7463a79a284d1f3c opw-6042550 Forward-Port-Of: odoo/odoo#275705 Forward-Port-Of: odoo/odoo#261468
1 change
Enhancements to existing features
Comply with new provincial fiscal transparency regulations (CABA, Entre Ríos, Chubut, and other provinces still not defined) that mandate detailing Perception IIBB taxes on B2C invoices (Factura/Invoice B): - Some jurisdictions mandate a new description for IIBB perception taxes on the invoice, - We need to put the IIBB perception taxes in the special "Fiscal Transparency Regime" table, and exclude them from the standard tax table, task-6367087 Forward-Port-Of: odoo/odoo#277673
Original PR description
Comply with new provincial fiscal transparency regulations (CABA, Entre Ríos, Chubut, and other provinces still not defined) that mandate detailing Perception IIBB taxes on B2C invoices (Factura/Invoice B): - Some jurisdictions mandate a new description for IIBB perception taxes on the invoice, - We need to put the IIBB perception taxes in the special "Fiscal Transparency Regime" table, and exclude them from the standard tax table, task-6367087 Forward-Port-Of: odoo/odoo#277673
77 changes
Enhancements to existing features
The Discuss interface has been refreshed with a vertical navigation rail, clearer search and filter controls, and more readable channel rows across desktop and mobile. Channels without custom images now show consistent initials-based avatars, making conversations easier to recognize.
Original PR description
Rework the Discuss sidebar to match the new design. The tab navigation becomes a vertical icon rail on every viewport (it was a bottom bar on mobile), the "New" action and the search box share a…
Rework the Discuss sidebar to match the new design. The tab navigation becomes a vertical icon rail on every viewport (it was a bottom bar on mobile), the "New" action and the search box share a first row, and the tab filters render as pill toggles on a second row. Channel rows are restyled with rounded corners, an action-tinted hover/active state and an accent bar on the active row, replacing the global contrast() filter that read too dark on the light surface. The three surfaces now form a consistent elevation hierarchy in both light and dark mode: the rail is deepest (a faint pastel of the brand primary), the channel list sits above it, and the thread is lightest. Subchannel rows abbreviate the parent channel to its first few letters so the subthread name stays the prominent label. Channels without a custom image now get an avatar generated from the name initials over a stable pastel color derived from the record, instead of the fixed monochrome SVG. task-6392371 https://github.com/odoo/odoo/pull/276874
UrbanPiper food delivery settings are now managed in a dedicated store setup instead of being spread across each point-of-sale configuration. This makes store management cleaner and adds more flexible options for pricing, taxes, notifications, timings, and customer creation.
Original PR description
*: pos_restaurant_urban_piper, pos_enterprise, l10n_in_pos_urban_piper Introduces a dedicated `pos.urbanpiper.store` model to manage UrbanPiper store configurations for food delivery. Configuration…
*: pos_restaurant_urban_piper, pos_enterprise, l10n_in_pos_urban_piper Introduces a dedicated `pos.urbanpiper.store` model to manage UrbanPiper store configurations for food delivery. Configuration fields previously scattered across `pos.config` are migrated to this new model, giving each POS configuration its own linked UrbanPiper store record. This results in cleaner separation of concerns, easier extensibility, and a more streamlined UI for store management. **New model: `pos.urbanpiper.store`** - Replaces UrbanPiper-related fields previously stored directly on `pos.config` - Each POS config is linked to exactly one UrbanPiper store - Supports additional configuration fields without polluting `pos.config` **New features** - Provider-based pricelist support - Tax type configuration (inclusive or exclusive) - Customizable order notification sound - Preset support for managing: - Fiscal position - Store global pricelist - Store operating timings - Customer creation control ## Related - Task: `4977992` - Community: https://github.com/odoo/odoo/pull/260408 - Upgrade: https://github.com/odoo/upgrade/pull/9757
Accounting teams can now configure depreciation models and related asset accounts more flexibly, with key fields always visible and fewer restrictions during setup. Asset imports are also easier because depreciation model data and related accounts can be included directly in import templates.
Original PR description
This commit applies several improvements to the account and depreciation model. These changes are: - The `accumulated depreciation` and `depreciation expense` fields on the account form view are…
This commit applies several improvements to the account and depreciation model. These changes are: - The `accumulated depreciation` and `depreciation expense` fields on the account form view are changed to be always visible even if no depreciation model is selected. - Remove condition to limit asset creations for accounts being used as accumulated depreciation on other fixed asset accounts. It caused problems for many users trying to configure the accounts. Each country could have different configuation needs. - The depreciation model's name can now be edited while still keeping the auto-naming - The depreciation model auto-naming is slightly changed to be shorter when it's has a linear or degressive method. - The depreciation model export now includes more fields by using new export template - The asset import template has a new sheet for depreciation model data to be used to import depreciation models. Also depreciation and expense accounts can be imported directly to the asset, they are added as non-required fields to the asset template. The whole purpose is to ease asset imports as much as possible without having to pre-configure fixed asset accounts. - New button was added in the accounting import screen for importing depreciation models. task-6283929
The Discuss header no longer shows separate star and delete buttons because those actions are already available in the More menu. This reduces duplicate options and makes the interface simpler and more consistent with the Discuss team's intended workflow.
Original PR description
Remove the star and delete buttons from the Discuss header since both actions are already available from the "More" dropdown menu. This avoids duplicate actions in the UI and aligns the interface with the Discuss team's requested behavior. task-6420174 <img width="1197" height="308" alt="image" src="https://github.com/user-attachments/assets/f424e605-d4c8-4d29-9b7e-fe69b853324c" />
The appointment selection page now uses a clearer card-style layout consistent with the website appointment flow. Portal users also get a clearer preview notice, helping them understand when they are viewing appointment options before choosing one.
Original PR description
Purpose ======= Improve the look of the appointment selection page in the appointment module to match the look of the appointment selection in website appointment. Specification ============= Changing the appointment dropdown to match the website 'appointments list' layout. Moving templates from website appointment to appointment, cleaning scss rule, and remove now useless javascript interactions and test helpers. Adding a portal alert to inform that it's a preview of the appointment list selection, like it already existed after selecting an appointment type, except instead of redirecting to the selected appointment form, it redirects to the appointment list view. Inheriting the appointment template in website appointment to add the 'published' ribbon and sample images. Task-6185274
The employee time-off planning view now loads data in batches and only retrieves the relevant date range. This makes large team views much faster, reducing wait times from several seconds to about one second in key scenarios.
Original PR description
At odoo, our friendly kitchen chef needs to know who is off on any given day. To know that, they use the holiday gantt view and display all employees and check the sum. For 200+ employees working at GR2, `get_gantt_data` takes 7+ seconds `_unavailable_intervals_batch` is called for each individual version, which means it's not batched. Ultimatly, it leads to lots of sql queries that could be grouped together. With this commit, the calls are batched per calendar before: ~7s after: ~900ms-1s Forward-Port-Of: odoo/enterprise#125490 Forward-Port-Of: odoo/enterprise#124820
The time off Gantt view now offers a cleaner popup when creating multiple requests at once. It also handles multi-day and half-day selections more reliably, reducing validation errors caused by overlapping requests.
Original PR description
task-5941912
The Peru electronic invoicing module updates debit note reason options to match new SUNAT requirements effective August 1, 2026. Businesses creating Peruvian debit notes will have the new “Penalties” reason available and the existing “Other concepts” label updated for compliance.
Original PR description
Purpose: SUNAT has issued new validation rules and database updates for EDI. The changes are mandatory and is effective starting August 1, 2026. To stay compliant, the debit note reasons need to be updated when creating a debit note in Peru. A new code 13 with label "Penalties" is added to the list of reasons. Code 03 reason need its label to be updated to "Other concepts." Task [link](https://www.odoo.com/odoo/project.task/6312025) task-6312025 Forward-Port-Of: odoo/enterprise#122320
Belgian payroll now flags paid public holidays that fall within the first two weeks of economic unemployment and assigns them to the correct leave type. Payroll officers receive a warning when this split occurs, helping them review payslips and reduce payroll classification errors.
Original PR description
This change aims to grab the attention of payroll officers to the paid public holidays during the first two weeks of economic unemployment "LEAVE6665" and change the leave type to "LEAVE207" instead of "LEAVE500" Moreover, the split will be highlighted through a warning popup. Task: 6275590
Egyptian payroll rules now calculate pay more consistently using actual working days instead of a mix of fixed 30-day assumptions and working-day logic. Required employee payroll details are restored as standard employee fields, helping ensure accurate calculations and compliance exports across employees.
Original PR description
Purpose: - Some salary rules result in wrong computation as they are already handled in working days - Revert property inputs to fields as they are not optional and they need to be on all employees - Some of the calculations are based on working days and some are based on 30, we want to change that and make everything based on working days and have the user adapt the working schedule according to their needs. task-id: 6289200
Belgian payroll DMFA checks now show all validation issues and anomalies in a dedicated tab instead of stopping at the first problem. This helps payroll users review and resolve blocking and non-blocking issues more efficiently before creating declarations.
Original PR description
Currently, validation errors and anomalies on dmfa are raised one by one, making it a UX nightmare to fix the errors (you only see one at a time). Here, we refactor the code so that we have a new issues field on dmfa which computes the errors that are now defined as records of hr.payroll.warning we display this in a new tab in the form view of the dmfa. Task: 6267586
Marketing automation now processes campaign participants, activity traces, and WhatsApp-related messages in batches, improving performance for larger campaigns. The change also clarifies participant statuses and centralizes related update logic, making the feature easier to maintain and scale.
Original PR description
Improve traces and participants synchronization performance by batching operations. Introduce slicer usage so that batching is done under manageable chunk sizes. Improve whatsapp performance by batching part of the message creation process. Centralize code managing traces and participants status update, easing code understanding, maintenance and update. See sub commits for more details. Task-4224152: [marketing_automation] Performance / Scalability
Belgian payroll now offers two clear flexi contract employee types: Flexi-Employee with worker code 450 and Flexi-Worker with worker code 050. This replaces the previous generic Flexi-Job type, helping HR teams select the correct classification more easily and reduce setup errors.
Original PR description
Currently, there is two possibilities for people in flexi contracts, either they use worker code 450 or 050. In the current employee type, default flexi-job doesn't has default worker code. In this PR, expected to introduce new employee types - Flexi-Employee with worker code 450 - Flexi-Worker with worker code 050 It also removes the existing Flexi-Job employee type. This implementation simplifies HR operations by providing dedicated employee types with predefined worker codes. task: 6364410
The Dimona check button for Belgian payroll is now shown when debug mode is enabled or when the sandbox environment is open. This makes it easier for authorized users to test and verify Dimona-related employee information in the right contexts without affecting normal production use.
Original PR description
Update the check dimona button to appear if the debug mode is open or sandbox is opened Task Id : 6398635
Payroll payment export options can now be tailored by country and extended more easily. This reduces irrelevant choices in multi-country payroll setups and helps select the right default export format automatically.
Original PR description
Update the export_format field to use a callable for both the selection list and the default value. It has a few goals: - Allow to add new options without needing to update the module, for cases where it could make sense. - Allows to make the options country specific, reducing the amount of irrelevant options shown in multy countries databases. - Allow a better handling of default values, allowing to make them country specific. task-6363995
Belgian payroll now applies a quarterly cap to employer social security contributions, preventing employer contributions from exceeding the allowed limit across payslips in the same quarter. The change adds the required payroll rule, reporting support, and tests so Belgian payroll calculations and DMFA reports reflect the capped deduction correctly.
Original PR description
[IMP] l10n_be: employer contribution capping
. Quarterly employer contribution capping should be applied for Belgium.
. New salary rule parameter for capping amount
. New salary rule ONSSEMPLOYERBASICDEDUC to calculate the deduction of ONSSEMPLOYERBASIC in each payslip.
. In short, we are looking (cap_amount - total ONSSEMPLOYERBASIC this quarter)*basic_rate - previous deductions in this quarter
. By this way, you can't overflow the capped employer contribution.
task - 6279204India payroll employer cost calculations now use gross salary instead of net salary by default. This gives businesses a more accurate view of employee cost because gross salary better reflects the cost baseline before net pay deductions.
Original PR description
In this PR, for the India localization, we were using NET as the default value for employer cost computation. Instead of NET, we will now use GROSS, as it provides a more accurate representation of employer cost: Employer Cost >= GROSS >= NET. Technical - set appear_in_employee_cost_dashboard=False in India:Intern and India:Employee pay in NET salary rule. - set apprear_in_employee_cost_dashboard=True in India:Intern and India:Employee pay in Gross salary rule. task: 6323947
Saudi payroll now helps HR track employees whose wage, housing allowance, or other allowances have changed. HR managers receive a notification, and the required GOSI wage update report is available from the reporting menu for upload to the GOSI platform.
Original PR description
GOSI wage update report is needed to be uploaded to GOSI platform for each employee that changes their wage, housing allowance, or other allowances. Consequently on the change on any of these fields, a notification will be created for the HR manager and the report to be uploaded will be accessible through the reporting menu with the employees that were updated. Task: 6380424
Belgian payroll now includes the required pension and subsistence fund contribution rules for both workers and employees. This helps employers calculate and report the correct DMFA contribution codes in line with social security requirements.
Original PR description
add for Workers → 826 & 827 For employees → 836 & 837 rules depending on Source: https://www.socialsecurity.be/employer/instructions/dmfa/fr/latest/instructions/special_contributions/other_specialcontributions/subsistenceprotectionfunds.html and add it in the dmfa Task Id: 6259626
Belgian payroll now records the fiscal month and quarter used for 274.xx withholding tax declarations and carries that information into related accounting journal items. This makes it easier to reconcile payroll taxes when declarations are settled in a different period than the work performed.
Original PR description
**Why:** In Belgian payroll accounting, taxes can legally be declared and settled in a month or quarter other than the one in which the actual work was performed. Currently, this mismatch makes it difficult to reconcile financial journal entries with the official 274.xx withholding tax forms. **What:** - Added fiscal_month and fiscal_quarter fields to track the 274.xx tax declaration periods. - Extended the payroll journal entry mapping to pass this fiscal period information directly down to the generated account journal items. task-6233232
This update makes BioTime attendance integration easier and safer to use by hiding related menus until setup is complete and improving how punch records are processed. It also improves time conversion, attendance deletion handling, and adds tests to reduce errors in daily attendance workflows.
Original PR description
- Hide the Transactions/Terminals menus and block their views until BioTime is configured; Test Connection reloads so the menus surface. - Convert BioTime punch times to UTC using the employee timezone. - Reset and flag linked transactions when their attendance is deleted, and keep the guard against deleting processed-and-linked ones. - Replace the cog server action with Fetch/Process/Re-Fetch list-header buttons; allow editing punch_type when the fetched value is unsupported. - Compute processing_note from the transaction state instead of writing it ad hoc across methods. - Add shared _notification and _mark_processed helpers and drop dead code (unused params, unreachable guards, redundant cache clearing). - Add tests covering the processing, sync, and access-gating paths. Task-6181807
Belgian payroll declarations can now include an employee's risk class when one is defined. This helps produce more complete DMFA filings and reduces the need for manual adjustments or missing declaration data.
Original PR description
The `ActivityWithRisk` tag is currently disabled by hardcode. This commit populates the tag with the value of the employee's risk class, if any. TaskID: 6409073
The payroll dashboard no longer shows an invalid language warning for Belgian payslips. Instead, it now warns users when the DMFA work location language is missing, helping payroll teams fix the setting that matters for official payslip delivery.
Original PR description
Currently, Payslip is sent both in employee language and the DMFA work location language. This happen to make sure the payslip is sent in one of the official language. In this PR, expected to improve the warning that appears in Payroll Dashboard. The specifications required to: - Remove the warning about "Invalid Language" - Add a warning regarding the DMFA work location if the language is not set task-6377966
Payroll localization modules are now installed through Odoo's standard country-based auto-install process instead of a later setup hook. This reduces upgrade surprises and keeps payroll localization status more consistent during installations and updates.
Original PR description
Previously, a post-init hook was used in `hr_payroll` to install `l10n_XX_hr_payroll` modules for each country where a company is located. This could lead to issues and unexpected behavior during upgrades as this is run later in the process. Modules installed by the hook were considered as `uninstalled` until the `hr_payroll` was loaded. However, this auto_install behavior is now fully handled by the `auto_install` + `countries` mechanism in the manifests. The hook can then be safely removed. All the `l10n_XX_hr_payroll` modules where already using the configuration `auto_install: ['hr_payroll']` with `countries: ['XX']`, no change is needed in those modules. Only `l10n_us_hr_payroll` was still using that hook since it had a dependency on `l10n_us`. This was fixed in a [dedicated PR]. [dedicated PR]: https://github.com/odoo/enterprise/pull/120279
Payroll now supports optional categories on time off types, letting businesses add extra classifications when creating time off and use them in payroll calculations. Belgian premium pay rules are being moved to this more flexible approach, alongside a correction to non-recurring benefit contribution calculations.
Original PR description
Allowing to define optional categories on time types, which can be optionally added on time off creation. Migrating the Belgian premium pay to utilise this system. task-6297699
Document-related counters now update automatically when attachments are added or removed, so users see accurate information without manually reloading. This improves reliability for records that use document management and adds test coverage to protect the behavior.
Original PR description
This commit enables the chatter to automatically trigger a reload of the stat buttons whenever an attachment is added or removed from a model inheriting `documents.documents_mixin`. To achieve this at the frontend level, a new computed attribute was added to the `mail.thread` store to serve as a marker, allowing the chatter to detect the mixin's presence and adjust its reload behavior accordingly. Tests in `test_documents_full` have been updated to ensure the bridge logic correctly handles document creation and deletion. Related-PR: https://github.com/odoo/odoo/pull/265280 Task-6148224
Resolved issues and error corrections
This update replaces shared editable defaults with safer fixed values in record search settings across many Odoo Enterprise modules. It reduces the risk of rare cross-record side effects and prepares the codebase for stricter automated quality checks, with no expected change to day-to-day user workflows.
Original PR description
Mutable default values share state across all instances of the class. This can lead to bugs when the attributes are changed in one instance, as those changes will unexpectedly affect all other instances.[^1] Most `_rec_names_search` are defined as lists, but could be defined as immutable tuples instead. Found using the linter at odoo/odoo#217724. This linter will be merged only after all existing findings are resolved. This merge contains 2 commits: 1. The execution of the `tuple-rec_names_search` upgrade-code script. 2. The fixes to address the (true/false)-negatives of the script. task-6396049 [^1]: https://docs.astral.sh/ruff/rules/mutable-class-default/
This fix removes an outdated setting from the FedEx delivery integration setup. It helps keep the shipping connection logic consistent after a previous change, reducing the chance of confusion or minor configuration issues.
Original PR description
Follow up of 6b5d4eb which forgot to remove the now unused `make_return` key. ----- Ticket: opw-6101620
This update adjusts several scheduling, map, subscription, and WhatsApp-related screens to work correctly with the newer interface framework rules. It prevents missing buttons or broken popovers in Gantt and map views while keeping the change internal and low risk for users.
Original PR description
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.…
Follow-up to the community change that makes the owl3 compatibility layer throw on `static defaultProps`. Owl 3 ignores that attribute; defaults must go through `useProps(...).optional(default)`.
Remove the remaining `static defaultProps` and fold the defaults into the props schema:
- web_gantt: GanttPopover -> `props = useProps(ganttPopoverProps)`, defaults become `.optional(() => ...)`. Export `ganttPopoverProps` (props is now an instance field, so `GanttPopover.props` no longer resolves).
- web_map: MapPopover -> `props = useProps({...})`.
- whatsapp phone_field: the `patch(PhoneField, { defaultProps, props })` augmented dead statics; augment the exported `phoneFieldProps` schema instead, folding `enableWhatsAppButton: true` into `.optional(true)`.
Fix consumers broken by `props` becoming an instance field:
- appointment: AppointmentGanttPopover built its schema from `GanttPopover.props.concat(...)`; build on the exported `ganttPopoverProps`.
- sale_subscription: the `patch(Product, { props })` override augmented the now-dead static `props`; augment the exported `productProps` schema instead.This fix prevents leftover collaboration test activity from affecting an unrelated Knowledge tour. It improves build reliability by avoiding misleading errors during automated validation, with no expected change for end users.
Original PR description
This aims to fix Runbot build error #937788 ([1]). A collaboration error was thrown during a tour which makes no use of collaboration. This makes sure the bus from the previous test doesn't persist when running this tour so it doesn't interfere. [1]: https://runbot.odoo.com/odoo/runbot.build.error/937788 Forward-Port-Of: odoo/enterprise#125509
AI-assisted record creation and updates now handle database validation failures as normal retryable errors instead of causing unrecoverable crashes. The change also improves access to required model information so the AI agent can complete more business flows reliably.
Original PR description
Prior to this commit, the create and update tool calls could cause an unrecoverable error if the model tried to use values which were causing an SQL constraint to fail. With this commit, we add a try..except block with a savepoint to treat the SQL constraint errors as regular errors, ensuring that the model is able to retry if it misses a check. task-6196137 Forward-Port-Of: odoo/enterprise#125226 Forward-Port-Of: odoo/enterprise#121607
Uploading a document no longer causes an error when Auto Sort immediately moves it to another folder. This keeps the Documents workflow stable for users, with no visible change when the moved file is no longer in the current folder.
Original PR description
When Auto Sort is enabled, an uploaded document can be moved to a different folder as part of the sort. The subsequent model reload only fetches records for the current folder to select/scroll to the new record. But, the new document's is absent from `env.model.root.records`. `newRecords` ends up empty, making `newRecords[0]` undefined, which then crashes accessing record.resId. To fix this, we just return early because if the record isn't in the current folder, there's nothing to select or scroll to anyway, so returning early here doesn't change anything visible behavior, it just avoids the crash. Steps to reproudce: 1.Go to Documents. 2.Go to Company->Inbox 3.Go to the gear icon and make sure the "Auto Sort" is enabled with "Move to folder" 4.Add a new document that's sortable. 5.You'll get the error. opw-6281558 Forward-Port-Of: odoo/enterprise#121069
Users with IoT access but without Point of Sale access can now enable the LNA setting on IoT box records without seeing an access error. This removes an unnecessary permission-related interruption and helps IoT administration tasks run smoothly.
Original PR description
Before this commit, if a user who has IoT permissions but not POS permissions tries to enable LNA on an IoT box record, they will receive an Access Error. After this commit, a `sudo` is added to the `onchange` handler fixing the issue. task-6392548 Forward-Port-Of: odoo/enterprise#124656
Belgian EC Sales List PDF and XML exports now use the correct foreign VAT number when a company reports for Belgium from another country. This helps prevent incorrect tax declarations and keeps the exported compliance documents aligned with the fiscal position settings.
Original PR description
### Issue before this commit: When a company generates an EC Sales List for a foreign country (e.g., a Luxembourgish company running a Belgian report), the exported XML and PDF files incorrectly…
### Issue before this commit: When a company generates an EC Sales List for a foreign country (e.g., a Luxembourgish company running a Belgian report), the exported XML and PDF files incorrectly display the company's primary domestic VAT number instead of the foreign VAT number defined in the fiscal position in the tag DeclarantReference. ### Steps to reproduce the issue: 1. Download Accounting and l10n_lu 2. Switch to LU company 3. Go to Fiscal Positions in settings and create the Belgian position (insert country as Belgium and Foreign Tax ID as BE0477472701) 4. A pop up will appear saying: Click to create the taxes for this country. so click there to create the taxes 5. Go to Invoices and create a new invoice and be sure that: 1. be sure the customer has a VAT number in their profile 2. in tab Other Info the Fiscal Position is set to Belgium 3. the tax applied is 0% EU S (BE) 4. date of invoice is in June 6. Open the tax return in 1 July 7. Open EC Sales List June 2026 (BE) and mark as reviewed all the lines 8. Click on Validate 9. Open the XML and PDF file created and see that the tag DeclarantReference is wrong because it reports the data of LU company instead of BE company ### Cause of the issue: The `export_to_xml_sales_report` method relied on legacy code (company.partner_id.vat) to fetch the VAT number. It failed to use the centralized `get_vat_for_export(options)` method, thereby completely bypassing the foreign VAT logic correctly implemented in other tax reports. ### Reason to introduce the fix: To ensure tax compliance by appling the correct VAT number from the foreign fiscal position. opw-6170447 Forward-Port-Of: odoo/enterprise#125210 Forward-Port-Of: odoo/enterprise#124698
Envia shipping rate requests now send insurance details in the format expected by the carrier API. This ensures customers receive accurate delivery quotes when insurance is enabled on an Envia delivery method.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#124923 Forward-Port-Of: odoo/enterprise#124700
The salary attachment form now shows the refund option again, matching the data already stored in the system. This helps payroll users correctly identify salary attachments that should be treated as refunds without relying on a separate wizard.
Original PR description
In an old PR (https://github.com/odoo/enterprise/pull/109195) the is_refund field was removed from the salary attachment view, although the field itself was not removed from the db. In a later PR (https://github.com/odoo/enterprise/pull/114188) the field was removed from the database but later reverted (https://github.com/odoo/enterprise/pull/123728). As it stands now, the field is in the database and is present in the view of a wizard but not in the standard form view of the salary attachment. This PR is reintroducing it. Task: 6415857 Forward-Port-Of: odoo/enterprise#125420
The U.S. accounting reports now handle deleted Profit and Loss summary lines without showing an error. This prevents interruptions when users customize report layouts and keeps the report accessible.
Original PR description
## Steps to Reproduce: 1. Install the Accounting module with demo data. 2. Enable developer mode. 3. Go to Reporting > Profit and Loss. 4. Click Configuration and delete the 'Gross Profit' line. 5. Return to the report. ## Error: `ValueError: External ID not found in the system: l10n_us_reports.pl_gross_profit` ## Cause: The report assumes the summary lines always exist and tries to fetch XML IDs. If any of these lines has been deleted, looking up will raises an error. ## Fix: Only apply the bold class to summary lines whose XML IDs are available. sentry-7601831925 Forward-Port-Of: odoo/enterprise#125200 Forward-Port-Of: odoo/enterprise#124011
Belgian payroll now updates an employee's work location details when DMFA work address settings are added or changed. This ensures payroll fields such as regional tax and reduction options appear correctly for eligible employees.
Original PR description
[FIX] l10n_be_hr_payroll: fix stale location unit
Bug reproduction:
1 - L10n_be -> belgium company
2 - create employee and assign work address My Belgium Company
3 - Payroll settings -> Work address DMFA codes -> add My Belgium Company to there -> Competence: Wallonia
4 - Go back to employee -> payroll tab -> In taxes & reduction section you need to see Impulsion Plan field.
Bug cause:
1 - Right now, version's location_unit changes only address_id is changed
2 - When new location_unit is added or when location_unit is edited, it does not reflect to version's location.
Bug solution:
1 - In L10n_BeDmfaLocationUnit model, in create and write functions I'm adjusting the location_units of the affected versions.
2 - Since location_unit is fixed, l10n_be_working_region is fixed as well.
task - 6355995
Forward-Port-Of: odoo/enterprise#122623This update prevents Swiss payroll processing from failing when a related payroll rule has been archived. It helps payroll teams continue monthly value handling without unexpected system errors caused by inactive rules.
Original PR description
Forward-Port-Of: odoo/enterprise#103677
Audit reports now refresh the number of invalid records when a check is reviewed successfully. This prevents users from seeing outdated anomaly counts after a check has been corrected, improving confidence in audit cycle results.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177 Forward-Port-Of: odoo/enterprise#125491 Forward-Port-Of: odoo/enterprise#119227
French VAT declarations now handle SIRET numbers even when users enter spaces, reducing failed submissions. The update also checks bank account number formatting and warns users when the information may be incorrect before sending.
Original PR description
This commit resolves an issue where VAT declarations failed when the provided SIRET number included spaces. Since check_siret verifies the format, we now strip all spaces from the input. Additionally, this commit introduces a validation for bank account numbers, ensuring that we warn the user if the account number is wrongly formatted. task-6253745 Forward-Port-Of: odoo/enterprise#125467 Forward-Port-Of: odoo/enterprise#120689
Users with manufacturing rights and sales access limited to their own documents can now edit manufacturing orders created from rental-related sales flows without hitting an access error. This prevents unnecessary work stoppages while preserving the existing sales order visibility restrictions.
Original PR description
### Steps to reproduce: - Ensure `sale_stock_renting` is installed - Enable Multi-Steps Routes > Unarchive MTO - Create a product P with a BoM and the routes MTO + manufacture - Create anc confirm a…
### Steps to reproduce: - Ensure `sale_stock_renting` is installed - Enable Multi-Steps Routes > Unarchive MTO - Create a product P with a BoM and the routes MTO + manufacture - Create anc confirm a sale order for A unit of P - Log in with an other user with with mrp User rights and sales User: Own Documents Only (he should not have access to the SO) - Open the MO, add a component line and save #### > Access Error: Blame the following rule: - Personal Order ### Cause of the issue: Writing on the `move_raw_ids` will trigger a call of the `_autoconfirm_production` in order to confirm the newly created move: https://github.com/odoo/odoo/blob/e447f4849056a0aab35966fb6ba595ebaadb79ab/addons/mrp/models/mrp_production.py#L990-L991 https://github.com/odoo/odoo/blob/e447f4849056a0aab35966fb6ba595ebaadb79ab/addons/mrp/models/mrp_production.py#L1422-L1423 During this confirmation process, one calls the `_merge_moves` method in order to merge this new move (if relevant) to any already existing one. https://github.com/odoo/odoo/blob/e447f4849056a0aab35966fb6ba595ebaadb79ab/addons/stock/models/stock_move.py#L1575-L1576 Now, the issue is that, `sale_stock_renting` module overrides the method `_prepare_merge_moves_distinct_fields` determining the fields relevant to the merge by requiring a read access to the `is_rental_order` compute field of the `sale_order` linked to the MO: https://github.com/odoo/enterprise/blob/b66097122ba3a758734ac6fb2b26579c35cb72c2/sale_stock_renting/models/stock_move.py#L34-L40 However, due to the 'Personal Orders' ir.rule, the user does not have a read access to this record: https://github.com/odoo/odoo/blob/e447f4849056a0aab35966fb6ba595ebaadb79ab/addons/sale/security/ir_rules.xml#L44-L49 Community: https://github.com/odoo/odoo/pull/271017 opw-6275658 Forward-Port-Of: odoo/enterprise#121845 Forward-Port-Of: odoo/enterprise#121135
The AI-powered SEO autofill now generates page titles and metadata in the website page's language instead of the user's personal language. This prevents multilingual websites from receiving SEO content in the wrong language, improving consistency for visitors and search engines.
Original PR description
The SEO "Fill with AI" autofill used the user's language for generation. On a website whose language differs from the user's, the generated seo metadata was therefore in the wrong language. This commit fixes this by using the page language instead. Forward-Port-Of: odoo/enterprise#123786 Forward-Port-Of: odoo/enterprise#123447
This fix prevents an error that could occur when multiple equity transactions are processed at the same time. It helps ensure equity transaction calculations complete reliably without interrupting users.
Original PR description
When the ``_compute_security_price`` method is called on multiple records, a traceback will appear. Traceback: ```py ValueError: Expected singleton: equity.transaction(1, 2) ``` https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/equity/models/equity_transaction.py#L218 The method filters newly created records using ``self._origin.id``. Since ``self`` is the whole recordset, accessing ``self._origin.id`` on multiple records raises a singleton error. sentry-7626410485 Forward-Port-Of: odoo/enterprise#125307
Fixed an issue where Avalara-related fields could be hidden on Canadian contacts when working with a US company. This ensures users can see and manage the correct Avalara tax information for cross-border contacts.
Original PR description
**Steps to reproduce:**
- Install Accounting and account_avatax
- Use a US company (by default)
- Create a contact with Canada as country
**Issue:**
In "Sales & Purchase" tab, all the fields from avatax module are not displayed (i.e. "Avalara Code", "Avalara Partner Code", "Avalara Exemption").
**Cause:**
The `invisible` property of those fields is using `fiscal_country_codes` char field.
If no company is set on the record, `fiscal_country_codes` will contain the country code of the selected companies in addition to the country code of the record.
In this case, the value of `fiscal_country_codes` will be `US,CA` string, which triggers `fiscal_country_codes not in ('US', 'CA')` invisible condition.
opw-6328395
Forward-Port-Of: odoo/enterprise#125543
Forward-Port-Of: odoo/enterprise#124619Accounting users no longer see a technical error when running auto reconciliation with no bank statement lines available. Instead, the system shows a clear warning, helping users understand that there is simply nothing to reconcile.
Original PR description
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To…
Currently, an error occurs when user tries to reconcile when there are no bank statements to reconcile. Steps to replicate: - Install `accountant` with demo. - Open Accounting and Click `To Reconcile` on the Bank Journal. - Go to the list view > Select all > From the Cog menu > Reset to draft. - Again select all and delete all the statement lines. - From Cog menu click on `Run Auto Reconciliation` > Run. Error: ``` SyntaxError: syntax error at or near ')' LINE 44: WHERE st_line.id IN () ``` Cause: - Error occurs because the [search] returns no results and the method `_try_auto_reconcile_statement_lines()` is called on an empty recordset. - Later in the flow the function `_partner_mapping()` [1] is call which makes the `self.ids` as empty tuple [2] this causes the query to have a syntaxerror. Solution: - When there are no statement lines to reconcile we show a warning notification. [search]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/wizard/bank_rec_auto_reconcile_wizard.py#L21-L27 [1]: https://github.com/odoo/enterprise/blob/ec408cb9a569f321afc99f4065a7a0f545d4faf4/account_accountant/models/account_bank_statement.py#L427 [2]: https://github.com/odoo/enterprise/blob/1516209ee077cda03155686d1377eb70080538f1/account_accountant/models/account_bank_statement.py#L620 sentry-7615011817 Forward-Port-Of: odoo/enterprise#124804
This fixes an error that could occur when users loaded more partner-grouped trial balance lines for Colombian reports. The trial balance now handles empty column information correctly, so users can continue reviewing report details without interruption.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124506 Forward-Port-Of: odoo/enterprise#124102
Fixed an issue where very large sales commission achievement records could not be opened because their identifiers were not handled correctly in the browser. Users can now access these records without seeing an erroneous “record does not exist” message.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#123757 Forward-Port-Of: odoo/enterprise#113701
This fix prevents errors when trashed Knowledge articles are cleaned up if they are linked to Annual Reports. The cleanup now also removes the related annual report records, avoiding failed background jobs and keeping accounting review data consistent.
Original PR description
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install…
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install ``accountant_knowledge`` module - Go to Accounting > Review > Annual Report > Create a new annual report - Go to Knowledge > Open the knowledge article linked to the annual report > Send to Trash - Run the ``Base: Auto-vacuum internal data`` cron Traceback: ```py ForeignKeyViolation: update or delete on table "knowledge_article" violates foreign key constraint "audit_report_knowledge_article_id_fkey" on table "audit_report" DETAIL: Key (id)=(67) is still referenced from table "audit_report". ``` https://github.com/odoo/enterprise/blob/04cce2e400ce2e412f28aa1849078a7c40ff0e2c/knowledge/models/knowledge_article.py#L1069-L1070 The garbage collector deletes trashed knowledge articles that match its domain. Since this domain also includes articles linked to Annual Reports, the cron attempts to delete records that are still referenced by annual report, resulting in a foreign key violation error. Solution: Ensure linked audit reports are also deleted during knowledge article garbage collection. sentry-7488793071 Forward-Port-Of: odoo/enterprise#125525 Forward-Port-Of: odoo/enterprise#121189
This fix restores the validation flow for Indian GSTR tax returns after a related screen layout change caused the return view to break. Businesses using Indian tax reporting can continue validating GSTR returns with the expected workflow and button behavior.
Original PR description
Fixed the broken view for indian tax returns due to parent view refactor. Update the Indian GSTR return workflow to: - adapt the kanban button inheritance to the new view structure, - preserve the custom GSTR Validate button independently of unresolved checks, - Keep the GSTR-specific validation workflow unchanged. - remove indian loc specific validate button instead use from parent. - some code cleaning. task-6365198 Forward-Port-Of: odoo/enterprise#123207
This fix ensures Brazilian Avalara tax requests keep important customer tax settings even when their values are blank or false. It prevents Avalara from choosing the wrong CFOP code, helping invoices receive the correct fiscal classification.
Original PR description
## Steps to reproduce: 1. Install `l10n_br`, `l10n_br_avatax`, and `l10n_br_edi_fiscal_reform`. 2. Ensure that Demo mode is activated if not on Runbot. 3. Navigate to Contacts, then click into "BR…
## Steps to reproduce:
1. Install `l10n_br`, `l10n_br_avatax`, and `l10n_br_edi_fiscal_reform`.
2. Ensure that Demo mode is activated if not on Runbot.
3. Navigate to Contacts, then click into "BR Company Customer Estimated Profit".
4. Duplicate this contact, then set the following fields:
1. Tax Regime set to individual
2. ICMS Taxpayer Type set to Non-Taxpayer
5. Swtich to the BR Company and go to Accounting / Configuration / Settings.
6. Set up a Sandbox Avalara account and enable logging payload responses.
7. Navigate to Accounting > Customers > Invoices.
8. Create an invoice with:
1. Customer set to the copy created earlier.
2. Operation Type set to Sale of Goods
3. Document Type set to 55
4. Payment Method Brazil set to Money
5. Presence set to Present
6. One sales order line with:
1. Regular Consumable Product
2. quantity set to 1
3. price set to 100.0
9. Confirm the invoice.
10. Navigate back to Accounting > Configuration > Settings to view the response from Avalara. The customer will have the CFOP 6102 instead of CFOP 6108.
Explanation:
PR #97845 introduced `_l10n_br_deep_clean_dict()` to remove falsy values and empty dictionaries from the payload we send to Avalara. This fix was applied as broadly as possible to prevent excessive if statements.
However, if the falsy values in taxSettings of the customer are not communicated, Avalara will assign the customer to an incorrect CFOP.
opw-6085964
Forward-Port-Of: odoo/enterprise#124730
Forward-Port-Of: odoo/enterprise#120783The project forecast view was updated so its subtask button correctly connects to the current subtask action. This prevents a small interface mismatch and helps users access subtasks reliably from project task views.
Original PR description
Issue --- The inherited xpath still targets the old action-based subtask button Fix -- Update the inherited xpath to target action_open_subtasks. task-5966684 Forward-Port-Of: odoo/enterprise#124721 Forward-Port-Of: odoo/enterprise#123035
The Belgian payroll report now calculates IPA reductions using the proper salary components instead of the full taxable amount. A dedicated IPA tab makes these lines easier to review, helping payroll teams produce more accurate 274xx declarations.
Original PR description
-add tab for IPA in 274xx sheet and add new field `line_ipa_ids` to display them in the new tab -fix the old calculations for the IPA where previously was equal to total_taxable_amount but now based on all salary components subject to ONSS salary components that are taxable but no ONSS travel expenses (except bike expenses) Task Id: 6333064
This fixes where Mexican CFDI invoice fields are placed so they remain visible even when other localization modules are installed. It prevents the CFDI Origen field from disappearing on Mexican invoices due to layout changes from another country-specific module.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
This update keeps planning field service activity tracking working with the latest mail tracking changes. It is a small internal compatibility fix that helps ensure logged updates continue to use the correct notification category.
Original PR description
Rename `_track_subtype` to `_track_log_get_default_subtype` to align with the updated mail tracking. Related Commit https://github.com/odoo/odoo/pull/248505/changes/9c1ce65cdd924b50df3eeef5c69cac110d1eb26b Forward-Port-Of: odoo/enterprise#125666
This fix prevents an intermittent error when the signing document preview is closed or removed while still loading. It improves stability in the Sign app and helps keep automated checks from failing unexpectedly.
Original PR description
Due to a race condition, in the PDFIframe sometimes the Iframe gets detached before we access it and we therefore have this.root.defaultView = null. Since when the Iframe is detached we don't really care about defining the eventBus, we can fix the problem related to its assignation by first checking the value of this.root.defaultView and only continuing in case it has one. This PR fixes a runbot error. Runbot Error: 233524 Forward-Port-Of: odoo/enterprise#124512
Ecuador branch users can now create customer invoices without being blocked by an access error. The fix allows the system to identify the journal country correctly in parent-child company setups, keeping normal accounting workflows available to authorized branch staff.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This update fixes an unstable automated test in Web Studio that could fail unpredictably. It helps keep the quality checks reliable so future changes can be validated with fewer false alarms.
Original PR description
runbot-error-940371 Forward-Port-Of: odoo/enterprise#125319
This fix ensures Belgian payroll structures keep their accounting journal settings when a new Belgian company or branch is created. It prevents missing payroll accounting configuration, reducing manual cleanup and helping payroll setup work correctly for new entities.
Original PR description
Steps to reproduce: 1. A structure related to BE, and set journal_id. 2. Create a new BE company or branche of the existing company. 3. Go to the created structure, the journal_id is empty. Root cause: After creating a company, _configure_payroll_account should be triggered to finish the configuration. Setting the journal_id for the existing structures (with the same company country) is part of that configuration. The method responsible to call the configuration, is _load_payroll_accounts in account_chart_template.py (hr_payroll_account), and it should call the following method: _configure_payroll_account_generic_coa. This method was deleted in master and that was the problem. task-6394082
AI chat now continues to suggest reopening the most relevant previous conversation even after the user reloads the page. This makes it easier for users to resume recent work while avoiding duplicate prompts when that chat is already open.
Original PR description
Purpose: -------- When launching an AI chat, users can be suggested to reopen the latest non-empty chat matching the same interface key and record. This suggestion used to rely on chats already present in the frontend store, so it was lost after a page reload. With this commit, the suggested channel is selected by the backend whenever the AI channel is added to the store and included in its channel data. This keeps the suggestion available after a page reload while hiding it when the previous chat is already open, but not when it is minimized. Task-6354153 Forward-Port-Of: odoo/enterprise#123044
Belgian payroll calculations for CCT90 non-recurring benefits have been updated so the ONSS contribution is always applied when due, regardless of thresholds. This improves payslip accuracy and helps businesses remain compliant with Belgian payroll rules.
Original PR description
- splitted social contribution into 2 rules - made ONSS Non_recurring Benefit Contribution always due regardless of any threshold task-id: 6358022
Belgian payroll now applies the correct withholding tax exemption cap for bachelor-level research staff based on company size. This ensures payroll deductions and employee-level exemption amounts are accurate and transparent when legal caps apply.
Original PR description
Before, the bachelor exemption was hardcoded at 25% for every company, the doctor/master total never flowed into the deduction, and each employee's exempted amount in the Bachelors tab showed the raw uncapped number even when the cap applied. Now the cap is 25% for big companies and 50% for small ones, set through a salary rule parameter and defaulting to 25% when company size is not set. Each employee's amount is scaled down proportionally when the cap kicks in, so the Bachelors tab always shows what they actually get, and the total deduction reflects it correctly. task-6241566
This fix ensures existing tax returns are updated when their return workflow changes, preventing invalid old statuses from causing errors. It helps businesses avoid crashes during upgrades or configuration changes, especially when a final status such as paid is removed from the workflow.
Original PR description
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only…
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only accepts "review" and "submit" stages, not "paid" anymore 4) Go to the list of returns, remove the TODO filter => traceback The problem is here that the existing returns don't recompute their state when the workflow of the type is modified. In some cases, this is fine, but it others, it's annoying. In our example, the terminal state changed, so all the returns in that terminal stage should change their state to the new terminal one. "paid" is not an accepted value anymore, it should become "submitted". Moreover, when the workflow is changed, the selection field actually containing the state must also change. As it is, it seems to work because "state" of account.return is stored, but the value it's based on (the workflow field) won't be consistent with it. It's not annoying now, but those inconsistencies could become a big source of trouble in the future (we know that from experience ... I'm looking at you, version 8 ! è-é). This issue typically happens at upgrade. We had cases in FR and AE already. We solve that by a generic override of the write to sort things out when such change needs to happen. An upgrade PR will also be done to adapt the script so that we eventually solve the inconsistencies on dbs that have already migrated to 19.0. Forward-Port-Of: odoo/enterprise#124934 Forward-Port-Of: odoo/enterprise#124144
Changing a pricelist on a subscription order now correctly refreshes the related pricing calculations. This helps prevent incorrect subscription prices or totals after sales teams update pricing terms.
This update fixes an unreliable automated test in Web Studio that could fail unpredictably. It helps keep validation runs stable so development teams can detect real issues faster and avoid delays caused by false test failures.
Original PR description
Forward-Port-Of: odoo/enterprise#125273
Payroll module upgrades are now protected from a crash that could happen when optional payroll warning checks ran too early. This helps businesses complete payroll updates more reliably without being blocked by missing temporary setup data.
Original PR description
task-6345962 Forward-Port-Of: odoo/enterprise#122247
This fix ensures cumulative translation adjustment lines in accounting reports respect filters, horizontal groupings, and the correct reporting dates. Businesses get more reliable trial balance and ledger outputs, especially when comparing multiple companies or fiscal years.
Original PR description
The engine for the cumulative translation adjustment line was fully overriding the forced options, but this key might already be present in the options, for example, when using horizontal groups. task-6418960 Forward-Port-Of: odoo/enterprise#125725 Forward-Port-Of: odoo/enterprise#124108
Belgian payroll withholding tax reductions now apply correctly for disabled employees, disabled spouses, and spouses with low or no income even when there are no dependent children or seniors. This helps ensure affected employees receive the correct payroll tax treatment and updates related spouse income threshold wording.
Original PR description
Prior to this commit, the reductions for disabled employees, disabled spouse, and spouse with low or no income did not apply if the employee did not have any depenedent juniors or seniors. This commit fixes that, by removing the unneeded condition, and applying the reductions for those employees. This commit also updates the text for the thresholds of the spouse's fiscal situation. task-6384236 task-6320606 Forward-Port-Of: odoo/enterprise#124803
Electronic invoices sent from Colombian branches now use the parent company name in the required DIAN XML field. This helps DIAN correctly match invoices to the company tax ID and reduces rejection risk for branch-issued invoices.
Original PR description
The correct behavior should be to use the original company name in this specific XML tag For the DIAN, branch names will not be recognized as related to the NIT. So, when sending electronic invoices from a branch, the XML should use the name of the parent company of that branch. Ticket [link](https://www.odoo.com/odoo/project.task/6074280) opw-6074280 Forward-Port-Of: odoo/enterprise#125529 Forward-Port-Of: odoo/enterprise#115494
Belgian payroll now calculates the special social contribution using the correct quarterly rates and applies it to additional payslip types such as 13th month and termination holiday pay. This improves payroll accuracy for employees with specific family situations and for departures involving notice period compensation.
Original PR description
The special social contribution (CSSS) is a quarterly tax, with quarterly rates, that is paid monthly, with small advances. The CSSS was only computed with the monthly rates, not using the correct…
The special social contribution (CSSS) is a quarterly tax, with quarterly rates, that is paid monthly, with small advances. The CSSS was only computed with the monthly rates, not using the correct rates for couples with a spouse without revenue, and defaulting to outdated rates if none were given. I fixed it to use quarterly rates when needed (i.e.: at the last month of the quarter, or for any payslip whose quarter already has a validated/paid payslip at the end of the quarter), to get the correct amount at the end of the quarter. The payslip line was also missing in the 13th month, and termination holiday (N and N-1) payslips. As they are subject to the CSSS. If the employee does not respect fully his notice period, then his IRC (which is the leftover salary he receives in his termination fees) should be split per quarter left of the notice period, then its CSSS should be computed as if the employee continued to work. It was not possible to test the IRC from the UI, as scheduling a notice period without respect would always reset `l10n_be_notice_period_theoretical_end` to `False`. The bug was to fix the computed spaghetti by splitting the `_compute_departure_date()` into two different computes. The parameter values for the were esoteric 2d/3d arrays that would sometimes mix the employee status. Since, as per the POs, I only have to worry about master for the Belgian Payroll, I have changed, split and renamed the parameter values to better fit the use case. DMFA tests are a pain to edit, and a hit to my mental health when realizing that I have to rechange all the `expected_dict` by hand each time I rebase. So I extracted the variable fields from the dict, and made a function that helps us to easily compare the issue to avoid wasting hours, or even days trying to adjust the tests. I also added some variables in the dict, as some fields (e.g.: `OccupationUserReference`) would change depending on the employee/version id, which can change if the test is ran twice, as the rollbacks do not rollback autoincrement indexes. So dmfa tests would fail if we ran it more than once without dropping the db The MISC ONSS account was removed from test_payslips_validation as the payslip was in december (the M.ONSS was 0 euros as the total gross wage was too low for the quarter) For the account move line tests, the table comment seemed outdated (as if the table was not modified but variables did). I deleted them as they also seemed to be duplicate work to do. Also, `_validate_move_lines()` would just iterate over a given array and raise if the move lines would not be the same order as the given array. `payslip.move_id.line_ids` does not seem to have a defined business order, so I made it so that id does not fail if the recordset order is different than the given array order I also made two changes to the common localdict function: - remove the `prev_` prefix to the keys, as it was wrong (the key can also contain payslips in the future) - Changed the logic so that it reuses yearly payslips when possible task-6068542
WhatsApp conversation headers now use the correspondent's uploaded photo instead of a generated initials icon when one is available. This makes the chat header match the member list and gives users a more consistent, recognizable experience in Discuss.
Original PR description
Unlike live chat, WhatsApp did not override channel avatar generation. The generic implementation therefore always generated an initials SVG for the channel. This gave the channel its own avatar cache key and prevented the client-side avatar URL from falling back to the correspondent's uploaded photo. As a result, the partner photo appeared in the member list but not in the Discuss header. Override WhatsApp avatar generation to return no channel avatar when the WhatsApp partner has an uploaded image. The existing client-side logic then falls back to the correspondent's avatar URL. Before: <img width="653" height="179" alt="image" src="https://github.com/user-attachments/assets/9ec5bf86-bce4-4c5b-b2ba-b09c9b6c8282" /> After: <img width="478" height="203" alt="image" src="https://github.com/user-attachments/assets/f3318257-113a-4652-9f76-522ed60e3b80" /> task-6425285
Features or functions removed from Odoo
Point of Sale receipts will no longer include extra payment terminal receipts for Worldline, Six, and Tyro terminals. This keeps customer receipts shorter and avoids duplicate or unnecessary payment details while preserving payment processing.
Original PR description
This PR removes the terminal receipts which were until now added to Point Of Sale receipts. This is removed for 1) Worldline 2) Six 3) Tyro see https://github.com/odoo/odoo/pull/278393 task-6416813
Code cleanup and technical improvements
This update simplifies how the Social app handles translated text in comment streams. It is an internal cleanup that keeps behavior the same while making the code easier to maintain.
Original PR description
This commit removes a `env._t`. `_t` is env independant.
The UrbanPiper point of sale integration was updated as part of Odoo's Owl 3 migration. This keeps the module aligned with the newer platform framework and helps preserve stability without changing business functionality.
Original PR description
As part of the Owl 3 migration, this pr aims to replace onWillUpdateProps hook with the appropriate Owl 3 alternatives.
This update modernizes internal grid and Gantt view code by replacing deprecated frontend tools and cleaning up related documentation. Users should not see functional changes, but the work helps keep timesheet, planning-style grid displays, and Gantt views easier to maintain and evolve.
Original PR description
See commit messages for details. Intended merge method: `rebase-ff`
This refactor updates several Enterprise modules to use the current web framework reference system after older compatibility mechanisms were removed. It helps keep AI, Knowledge, Planning, Spreadsheet, Stock Barcode, and Map features maintainable and aligned with the latest platform architecture, with no intended change to business workflows.
Original PR description
The `t-custom-ref` directive and the compat `useRef` / named-ref mechanism were removed from the web compatibility layer. Migrate the last enterprise usages to native Owl 3 `t-ref` + signals,…
The `t-custom-ref` directive and the compat `useRef` / named-ref mechanism were removed from the web compatibility layer. Migrate the last enterprise usages to native Owl 3 `t-ref` + signals, following the community removal patterns.
t-custom-ref -> native t-ref:
- ai: readonly_voice_transcription, voice_transcription
- knowledge: embedded_clipboard, readonly_foldable_section (editableDescendants -> `t-ref="this.editableDescendantRefs.<name>"`)
- web_map: map_popover (rootRef signal field)
- spreadsheet_edition: calendar_button (buttonRef signal + resolveRefEl)
- planning: planned_date_range_with_allocated_hours (xpath selector now matches the migrated `web.DateTimeField` root `t-ref`)
compat useRef -> signal refs:
- stock_barcode: StockBarcodeFormRenderer used `useRef("compiled_view_root")`; FormRenderer now owns `rootRef = signal.ref()` (bound by the form compiler), so use the inherited `this.rootRef` and read it through resolveRefEl.
- web_map: MapCard used `useRef("root")`; use the `this.rootRef` signal it inherits from Card (bound in Card's template).Miscellaneous changes
Forward-Port-Of: odoo/enterprise#124569 Forward-Port-Of: odoo/enterprise#124221
Original PR description
Forward-Port-Of: odoo/enterprise#124569 Forward-Port-Of: odoo/enterprise#124221
10 changes
Enhancements to existing features
Australian payroll now applies the required superannuation contribution limit in the relevant salary rule. This helps employers stay compliant with ATO rules, including the updated Super Guarantee calculation from 1 July 2026.
Original PR description
Added superannuation limit to the QE rule. Task-6221399
Resolved issues and error corrections
Accrual report totals now show the correct amounts when users group purchase or sales accounting data by dates. This prevents misleading zero totals in grouped views, helping accounting teams review bills to receive and related accruals accurately.
Original PR description
Currently, when users group accrual reports by dates, aggregated computed fields are not calculated correctly. As a result, values such as the total amount may be displayed as zero even when the…
Currently, when users group accrual reports by dates, aggregated computed fields are not calculated correctly. As a result, values such as the total amount may be displayed as zero even when the grouped records contain non-zero amounts.
## Steps to produce:
- Install Purchase and Accounting
- Create a product `Energy drink Sample` with cost 10$
- Create and Confirm a PO with the energy drink sample with vendor as `Administrator`
- Set `Received` as 1.
- Go to Accounting > Review > Bill to Receive
- Search Filter> Remove vendor grouping > Use Custom Group `Order Date`
- Expand the group
## Observed Behavior
Although the grouped lines contain an amount of 10 dollars, the aggregated total displayed in the sum remains zero.
The total should reflect the combined value of the grouped lines.
## Root Cause:
This issue occurs because opening the view triggers `_read_group_for_accrual`, which overrides the `_read_group` method on purchase order lines. The purpose of this override is to support grouping on computed fields that are not stored in the database such as `amount_to_invoice_at_date (Amount)`, `qty_received_at_date (Received)`.
When `_read_group_for_accrual` is executed, it delegates grouping for non-computed fields to the parent `_read_group` implementation, as shown at [1].
The parent method returns results in `res` similar to:
```
[(datetime.datetime(2026, 6, 1, 0, 0), 1.0, 10.0, 1)]
```
During iteration over res at [2], the code uses `group[0]` as the grouping key. In this example, group[0] is `datetime.datetime(2026, 6, 1, 0, 0)`, which represents the granularity date
(e.g., the first day of the month when grouping by month).
However, `records_by_group` is keyed by the actual purchase order line order dates rather than the granularity dates returned by `_read_group`. For example:
```
{datetime.datetime(2026, 6, 12, 0, 0): purchase.order.line(1,)}
```
As a result, the lookup performed using the granularity date (`datetime.datetime(2026, 6, 1, 0, 0))` does not find a matching entry in `records_by_group`. Consequently, records falls back to an empty `purchase.order.line()` recordset.
Later, at [3], the aggregation logic computes totals using this empty recordset. Since the required fields are evaluated on an empty set of records, the aggregated values are computed as zero.
This ultimately causes the method to return a total value of zero
[1]-
https://github.com/odoo/enterprise/blob/eeea1377a7d36d11e140c44dee30a45228e7b4a6/account_accountant/models/analytic_mixin.py#L9-L24
[2]-
https://github.com/odoo/enterprise/blob/eeea1377a7d36d11e140c44dee30a45228e7b4a6/account_accountant/models/analytic_mixin.py#L40-L42
[3]-
https://github.com/odoo/enterprise/blob/eeea1377a7d36d11e140c44dee30a45228e7b4a6/account_accountant/models/analytic_mixin.py#L44-L47
## Solution:
The issue can be resolved by grouping records using the same date granularity specified in the groupby, rather than using the field values.
By aligning the grouping logic with the granularity returned by `_read_group` (for example, grouping by the first day of the month when using monthly grouping ), the keys in `records_by_group` match the values returned in `res`. As a result, the corresponding records are correctly retrieved during aggregation.
This ensures that the aggregation is performed on the appropriate purchase order lines instead of an empty recordset, allowing the computed totals to be calculated correctly.
[opw-6261225](https://www.odoo.com/odoo/project/49/tasks/6261225)Fixed an issue where one malformed incoming Chilean electronic tax document could repeatedly stop mailbox processing. The system now handles missing recipient tax ID information gracefully, so other emails can continue to be processed.
Original PR description
### Problem `Mail: Fetchmail Service` cron aborts with `AttributeError: 'NoneType' object has no attribute 'upper'` in `l10n_cl_edi/models/fetchmail_server.py::_process_incoming_customer_claim` when…
### Problem
`Mail: Fetchmail Service` cron aborts with `AttributeError: 'NoneType' object has no attribute 'upper'` in `l10n_cl_edi/models/fetchmail_server.py::_process_incoming_customer_claim` when an incoming customer claim DTE has no `<RUTRecep>`:
```python
dte.findtext('.//ns0:RUTRecep', ...).upper() or
dte.findtext('.//ns0:RutReceptor', ...).upper()
```
`findtext()` returns `None` when the tag is missing, so `.upper()` blows up before the `or` fallback can run. Once the cron hits such a message it re-crashes on every subsequent run and blocks the whole mailbox until the offending mail is deleted.
### Fix
Guard each `findtext(...)` with `or ''` so the `or` chain actually falls through. Empty `partner_vat` is already handled by the existing "Partner … has not been found" branch a few lines below.
### Traceback (Odoo 19)
```
File "/mnt/extra-addons/enterprise/l10n_cl_edi/models/fetchmail_server.py", line 285, in _process_incoming_customer_claim
dte.findtext('.//ns0:RUTRecep', namespaces=XML_NAMESPACES).upper() or
AttributeError: 'NoneType' object has no attribute 'upper'
```
### Ticket
No ticket open for this but opw-5257481 is related.Barcode users can no longer add unreserved products by scanning when extra products are not allowed, including after leaving and reopening a transfer. The fix also keeps the Add Product option available for immediate delivery transfers so staff can complete valid workflows without bypassing inventory rules.
Original PR description
This [PR] made sure it was not possible to scan unreserved products when `allow_extra_product` was disabled, even when exiting and re-entering a transfer. It worked under the assumption that an immediate transfer always stays in draft, which is wrong for deliveries. The 2nd commit of this PR partly address this issue by allowing the user to add multiple products with the "Add Product" button when the transfer is immediate. While working on this issue, we encountered a bug in the scanning prevention that should have been caught by a tour but was not. This is fixed in the 1st commit. More details in the commit messages. [PR]: https://github.com/odoo/enterprise/pull/123793
Rental products linked to planning services can no longer be increased in the cart beyond their available capacity. The same availability check is also applied when customers change rental dates, helping prevent overbooking and fulfillment issues.
Original PR description
From the cart, it is possible to increase the amount ordered of a rental product that synchronizes shifts depending on a specific service Steps to reproduce: 1. Install website_sale_renting_planning…
From the cart, it is possible to increase the amount ordered of a rental product that synchronizes shifts depending on a specific service Steps to reproduce: 1. Install website_sale_renting_planning module 2. Go to Rental > Products and create a new product "test" with Sales enabled, Product Type "Service", Plan Services enabled as "Developer", in the Sales tab, enable Is Published and in the Rental prices tab, create a pricing for Daily period 3. In the General Information tab, click on the internal link to "Developer" 4. Enable Sync Shifts and Rental Orders 5. Go to the eCommerce website and search for product "test" 6. Add as much product "test" to the cart as possible (the quantity is limited) 7. Open the cart 8. You can increase the amount of the product regardless of its availability Issue: We don't check the renting availabilities to limit the maximum quantity of the product Solution: Check that the new quantity of the product is available in `_verify_updated_quantity` for the specified dates. We also need to check the availability of the product when we modify the rental dates opw-6274035
This fix prevents branch-level users in Ecuadorian companies from being blocked by an access error when creating customer invoices. It keeps invoice creation working in parent-branch company setups by safely retrieving the needed country information from the journal.
Original PR description
Steps to reproduce: - Install `l10n_ec` module - Create one branch of the EC company - Give user(not admin) access to company branch and login with user - Go to Accounting > Customers > Invoices - Click New > AccessError Cause: This error occurs because the user is working within a branch of the main company. The code tries to access the journal’s company, which is set to the parent company. As the user does not have access to the parent company, fetching the country code fails. Solution: In some cases, strict company access rules cause `AccessError` and block normal flows, especially with parent–child company setups where a child needs data from the parent. To ensure smooth processing, we use a related field on the journal to retrieve the country code without directly accessing the company. opw-6087460 Forward-Port-Of: odoo/enterprise#113901
This fix ensures Mexican CFDI fields are placed in the correct invoice header area regardless of which localization modules are installed. It prevents the CFDI Origen field from disappearing on Mexican invoices when the Colombian EDI module is also present.
Original PR description
The CFDI fields used //sheet/group//group[last()], which targets the last group by position. Once l10n_co_edi adds its group after header_right_group, the fields land in it instead, and it is invisible unless country_code is CO, so CFDI Origen disappears on MX invoices. Use //group[@id='header_right_group'], like l10n_co_edi already does, so placement no longer depends on what modules are installed. Task Adhoc side: 67269 Forward-Port-Of: odoo/enterprise#124545
Sendcloud deliveries now handle partial quantities, such as products sold by weight, without being rejected for mismatched declared item weights. This helps international shipments go through correctly when only part of a unit is delivered.
Original PR description
Issue ----- International deliveries for fractions of items (eg 500g of a product sold by kg) are rejected by Sendcloud. Steps to reproduce ----- - Setup Sendcloud - Fedex international - Create a…
Issue ----- International deliveries for fractions of items (eg 500g of a product sold by kg) are rejected by Sendcloud. Steps to reproduce ----- - Setup Sendcloud - Fedex international - Create a product - weight: 1kg - valid hs code - Create a contact (outside EU if the company is in EU) - Deliver 0.5 of the product to the contact > Error "... parcel not returned from Sendcloud" Cause ----- Sendcloud returns he folloing error: > "The total weight for declared items exceeds the total weight set for the shipment." This is because the `weight` set on the shipment https://github.com/odoo/enterprise/blob/99a13453cac8a7a4677cef3df8896329c90c9e99/delivery_sendcloud/models/sendcloud_service.py#L449-L464 corresponds to the weight of the package, whereas the weight set on the description of the product in `parcel_items` corresponds to the weight of one "full" unit of the product. https://github.com/odoo/enterprise/blob/99a13453cac8a7a4677cef3df8896329c90c9e99/delivery_sendcloud/models/sendcloud_service.py#L327-L335 We cannot change the quantity in `parcel_items` to match the actual delivered one because the field should be an integer. https://sendcloud.dev/api/v2/parcels/create-a-parcel-or-parcels#body-one-of-0-parcel-parcel-items-items-quantity The price is also off, because it gets taken from the `move_line`, so it reflects the price of the actual quantity and not a "full" item. https://github.com/odoo/odoo/blob/208a8a6a5adb8ec1f2710453c2ee3b54c55a9f1e/addons/stock_delivery/models/delivery_carrier.py#L235 Note that this issue is common to **all UoM types**. Solution ----- Since we cannot change the quantity, we can instead adapt the description and weight sent in `parcel_items`. For example, sending 300g of sugar, we would send - description: "Sugar (0.3 kg)" - weight: "0.300" ----- Ticket: opw-6346330
Guatemalan credit notes now reference the original invoice's commercial issue date instead of a technical certification timestamp. This helps ensure the documents meet SAT validation requirements and reduces the risk of rejected credit notes.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409 Forward-Port-Of: odoo/enterprise#124794
Follow-up reports could fail to send in some databases when a customer follow-up setting was unavailable. The change ensures that setting is only used where the related follow-up exclusion feature is installed, preventing the error and keeping payment reminder workflows working.
Original PR description
https://github.com/odoo/enterprise/commit/65008de60589fbda924041e35bb34e33d84eb13d introduced a filter based on the `no_followup` field that is not present in every databases, since it was introduced in stable alongside with the `account_no_followup` module. This lead to an AttributeError when trying to send the followup report. This commit adds helpers to be able to use this field only in account_no_followup opw-6310602 Forward-Port-Of: odoo/enterprise#125148