Daily updates from Odoo
Monday, June 1, 2026
150 changes
20 changes
New functionality added to Odoo
This update implements French electronic invoicing reporting (Flux 10) to comply with new tax regulations. It handles B2C and international B2B transactions, ensuring accurate tax data is reported to the French authorities on a periodic basis. Enhanced security measures, including 2FA and KYC, are also included.
Original PR description
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B…
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B and the B2C. This creates two complementary obligations: - **E-invoicing** for domestic B2B transactions, where the invoice itself is exchanged through the PA/Peppol flow. - **E-reporting** for transactions outside that domestic B2B scope, mainly B2C and international B2B, where transaction and payment data must be reported to the tax administration through Flux 10 (period-based). ## Scope Domestic B2B remains handled by the existing e-invoicing flow, because the invoice exchange already carries the required structured information. Flux 10 is introduced for transactions that must be reported separately: - B2C transactions, where there is no buyer-side e-invoice exchange. - International B2B transactions, where the counterparty is outside the French domestic B2B mandate. - Payment reporting when VAT exigibility depends on collection. The reporting is period-based and keeps transaction reports separated from payment reports, because they answer different legal obligations and follow different timelines. ## Corrections and Lifecycle Flux 10 supports both: - **Initial reports**, for the first declaration of a period. - **Rectificative reports**, when already reported data must be corrected or completed. This distinction is needed so corrections remain traceable instead of silently mutating a report that may already have been transmitted. ## Security and Eligibility This PR also enforces stronger safeguards before using PDP/PA services. - **2FA is required** because PDP/PA actions expose regulated fiscal flows and should not be available from a simple password-only login. Email-based 2FA is available as a fallback when users have not configured an authenticator app. - **KYC is introduced** because a company must be identified and validated before Odoo can transmit documents or reports on its behalf through the PDP/PA infrastructure. Together, these changes make the French PDP/PA flow usable not only for invoice exchange, but also for the wider e-reporting obligations required by the French reform. Task-4603708 Forward-Port-Of: odoo/odoo#239576
Enhancements to existing features
This update streamlines KPI data retrieval across our servers by using a simplified SQL approach. Previously, each database required a separate registry load, which was slow. Now, KPIs are fetched using a new API endpoint with database credentials, improving performance and efficiency.
Original PR description
In order to improve speed of KPI retrieval on servers hosting many databases, we need to avoid loading a registry for each of them. With this commit, we introduce a route /kpi/summary that accepts a list of credentials in the form of pairs of database name and API key. The API key needs to be local to the database. Modules providing KPIs need to declare a method named `get_kpi_summary` in a file named `models/kpi_provider.py`, and it will return the exact same structure as the previous API `kpi.provider:get_kpi_summary`. The existing ORM-called methods now call the SQL version in order to avoid divergences in the future. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/odoo#267347 Forward-Port-Of: odoo/odoo#258050
Resolved issues and error corrections
This update enhances Odoo's ability to receive invoices with additional Peppol fields, addressing a previous limitation. Now, users can fully receive compliant invoices when they've already configured these extra fields using Odoo Studio. This ensures greater adherence to industry standards and simplifies invoice processing.
Original PR description
Currently, Odoo allows sending invoices with additional Peppol fields, but didn't support the receiving. This limitation prevents users from receiving fully compliant invoices. After this commit, users will be able to receive these extra fields if they already created them using Studio. task-6033667 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267071 Forward-Port-Of: odoo/odoo#262065
This update fixes an issue where the 'To Schedule' task default wasn't maintained when navigating the planning calendar using the previous/next arrow buttons. Previously, users would lose the context of the task they were scheduling. Now, the system correctly retains the task's default values when switching between weeks in the calendar view, ensuring a smoother scheduling experience.
Original PR description
Issue: ---------------------------------------- The default values aren't kept when using the previous/next arrows in planning calendar view. Steps to reproduce:…
Issue: ---------------------------------------- The default values aren't kept when using the previous/next arrows in planning calendar view. Steps to reproduce: ---------------------------------------- - Go on a Project task - Click the "To Schedule" button - Switch to calendar view - If we create now, the new slot will have the task as default value - Click the arrow to switch to next week - If we create there will be no default values Cause: ---------------------------------------- Since 7b844902e5c3a7aeedda6cc2be61366caad2d144 the context is lost when using the arrows. When switching to calendar view `load()` is called with the context in the params: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/web/static/src/model/model.js#L163-L164 But when using the arrows, it is called with only a date: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/web/static/src/views/calendar/calendar_controller.js#L426 So `...params.context,` is empty, and the context is only `hide_planned_dates: true,`. Solution: ---------------------------------------- If no context is specified in params, we use the one in `this.meta` to allow changing the context by giving it in the params but keeping the previous context when it's not given. opw-6211055 Forward-Port-Of: odoo/enterprise#118527
This update fixes an issue where the calculation of the gross total on invoices with both line and global discounts was incorrect. The change ensures accurate gross total calculations, particularly when global discounts are applied, leading to more reliable financial reporting. This resolves a discrepancy in the final invoice amount.
Original PR description
Problem: When both line discounts and global discounts are applied on a product in an invoice, the method `_add_and_round_raw_gross_total_excluded_and_discount` does not return the exact…
Problem: When both line discounts and global discounts are applied on a product in an invoice, the method `_add_and_round_raw_gross_total_excluded_and_discount` does not return the exact raw_gross_total_excluded before the modification done by other AccountTax helper methods, such as dispatching and squashing global discount lines. Current Behavior: The calculation is done in the wrong order of operations. For example, there is an invoice for Product A valued at $100 with a discount of 10% and a global discount of $10. The raw_total_excluded will be $80 after the both discounts. The discount_factor is based on only the line discount of 10%. The formula of the current calculation for raw_gross_total_excluded is: (raw_total_excluded / (1 - (line_discount / 100))) - global_discount = (80 / 0.90) - (-10) = 98.889 This does not equal the expected outcome of $100. Expected Behavior: Based on the previous example, the formula for the calculation should be: (raw_total_excluded - global_discount) / (1 - (line_discount/100)) = (80 - (-10)) / 0.9 = 100 The global discount needs to be added back to the raw_total_excluded to get the line discounted amount in order to divide by the discount_factor to gain the expected raw_gross_total_excluded before taxes and discounts. Steps to reproduce the issue: - Bug was encountered when implementing a global discount solution for l10n_co_dian. - Create an invoice with a product line and in-line discount and another line for global discount - Setup the base lines for the invoice and attempt the following: - _dispatch_global_discount_lines - _squash_global_discount_lines - _add_and_round_raw_gross_total_excluded_and_discount opw-5412446 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266584 Forward-Port-Of: odoo/odoo#262137
This update fixes an issue where employees on flexible schedules were incorrectly flagged for overtime. The change adjusts how overtime rules calculate hours worked, now accurately considering the employee's flexible calendar hours and any scheduled absences. This ensures accurate overtime calculations for all employees.
Original PR description
**Steps to reproduce:** - Create a flexible 32h/week calendar (8h/day, 4 days) - Assign it to an employee with the Default Ruleset - Create attendances: 8h on Monday, Tuesday, Friday, and Saturday…
**Steps to reproduce:** - Create a flexible 32h/week calendar (8h/day, 4 days) - Assign it to an employee with the Default Ruleset - Create attendances: 8h on Monday, Tuesday, Friday, and Saturday (32h total, matching the weekly budget) - Select the list view and go to the month of the attendances - Employee shows 16:00 Worked Extra Hours (8h on Fri + 8h on Sat) **Cause:** `resource.calendar._attendance_intervals_batch` generates work intervals for flexible calendars by front loading the weekly hour budget onto the first days of the week (Mon 8h, Tue 8h, Wed 8h, Thu 8h for a 32h calendar), But days beyond the budget (Fri, Sat, Sun) get zero hours. The two overtime rule paths relies on these synthetic intervals: 1) The quantity rule: `_get_daterange_overtime_undertime_intervals_for_quantity_rule()` computed `expected_duration` by intersecting the synthetic schedule with each day. For Fri/Sat the intersection was empty (expected = 0) -> all worked hours counted as overtime. https://github.com/odoo/odoo/blob/b31fd6816521ff43fb3a9ec37e79e9a9d628d357/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L302-L304 **update** solved by: https://github.com/odoo/odoo/pull/265120/changes/94d4bfffa053cd78ce07ff07ab14b53e8d931053 2) The timing rule: `_get_rules_intervals_by_timing_type()` derived "work_days" from the synthetic schedule and inverted them to get "non_work_days". (Fri, Sat, Sun) were classified as non-working days, therefore, any attendance on those days triggered full overtime. https://github.com/odoo/odoo/blob/b31fd6816521ff43fb3a9ec37e79e9a9d628d357/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L421-L433 **Solution:** For flexible calendars in the overtime rule consumer: - Quantity rules: read expected hours directly from the calendar's `hours_per_day` / `hours_per_week` instead of the synthetic schedule intervals, subtracting any leaves in the period - Timing rules: treat the entire attendance date range (minus leaves) as potential work days, so that `non_work_days` is empty for flexible employees (they can work any day of the week) opw-6067063 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265976 Forward-Port-Of: odoo/odoo#263840
This update resolves an issue where reimbursed sales orders (paid via credit notes) continued to incorrectly impact customer credit limits. The fix adds a 'closed invoicing' flag to sale orders, preventing them from being considered for credit limit calculations once invoicing is finalized. This ensures accurate credit limit tracking for customers.
Original PR description
### Issue: When a Sale Order is delivered but later reimbursed (e.g., via a credit note without a return), it is still considered as to invoice As a result, it continues to impact the partner’s…
### Issue: When a Sale Order is delivered but later reimbursed (e.g., via a credit note without a return), it is still considered as to invoice As a result, it continues to impact the partner’s credit limit ### Cause: Sale Orders remain included in the `credit_to_invoice` computation even when invoicing is manually considered finished There was no way to exclude such orders from the credit limit calculation ### Fix: Use the `invoicing_closed` field to mark Sale Orders as fully processed When set, the order is excluded from the credit limit computation ### Steps to reproduce: - Install `sale_management` - In Settings, enable Sales Credit Limit (default: 3000) - Create, confirm, and deliver a Sale Order for a new customer (any product, price: 2000) - Duplicate the Sale Order → a credit warning is displayed - Go back to the original Sale Order and use Close Invoicing from the gear menu - Return to the duplicated Sale Order The warning disappears as the closed order is no longer included in the credit computation ### Note: For a complete business scenario, refer to the steps described in the related ticket opw-6013369 Forward-Port-Of: odoo/odoo#262720
This update resolves an issue where appointment calendars wouldn't display available slots correctly when appointments started in a future month. The fix ensures that the calendar accurately reflects available slots, regardless of when the appointment's booking range begins. This prevents users from seeing 'no slots available' messages when appointments are scheduled in the future.
Original PR description
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots:…
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots: https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L833 For a punctual appointment whose Allow Bookings range starts in a future month, the first displayed month is start_datetime.month, so the (month, year) tuple doesn't match the month the visitor is looking at. The model fills an empty month and the recovery loop refills the first displayed month (where slots actually live): https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L973-L988 The calendar the visitor just navigated to comes back empty. Compute the navigation base from start_datetime when it lies in the future and keep datetime.now() otherwise. month_id is added on top of that base so it always matches the displayed month index. Introduced by https://github.com/odoo/enterprise/commit/664857dd2c4ae2bc0dde8f44cb94136659ed2fe2 Steps to reproduce: 1. Open the Appointments app 2. Open an appointment type and set Schedule to Weekly and Allow Bookings to On specific dates with a range starting in a future month (for example 1 September to 31 December) 3. Save and click the Preview button in the header 4. Pick a staff member to reach the calendar 5. Click the right arrow to navigate to the next month => the next month shows "Sorry, we have no more slots available for this month" opw-6206293 Forward-Port-Of: odoo/enterprise#117283
This update resolves a performance issue affecting the Odoo web client, specifically within the account module. By restructuring CSS selectors, the system now renders faster, leading to a smoother user experience. This change focuses on optimizing how the application responds to user interactions.
Original PR description
This commit moves the span selector inside one of its parent styling selector block. This avoids the browser to check for any span and look for pseudo-classes :where and :has to compute its style, which caused unexpected slowlness in the webclient. Now, the browser firstly checks for the parent class, and then look for the more complex selectors present below. There are less occurence of the selector inside the component, and it is no longer global. Forward-Port-Of: odoo/odoo#266931
This update resolves an issue where Odoo was generating incorrect CFDI (Mexican electronic invoice) XML files when using a specific cash rounding strategy. The fix ensures that cash rounding amounts are properly handled according to SAT regulations, preventing XML rejection errors and ensuring compliance. This improves the accuracy of invoices for Mexican customers.
Original PR description
When using the 'add_invoice_line' cash rounding strategy, Odoo adds a journal line with display_type='rounding'. This line has no product and therefore no ClaveProdServ, causing PAC to reject the XML with error 301. Per SAT regulations, cash rounding is not a valid CFDI concept. The CFDI must report the pre-rounding amounts (e.g. 99.80); the rounding difference (e.g. 0.20) belongs only in the journal entry on the accounting side. opw-6024078 Forward-Port-Of: odoo/enterprise#117400 Forward-Port-Of: odoo/enterprise#112633
This update fixes an issue where inventory value calculations were inaccurate when a warehouse location was archived. Previously, archived locations weren't properly considered when determining the total value and average cost of inventory. This change ensures that all inventory, including items in archived locations, is accurately reflected in valuation reports.
Original PR description
When a receipt dest location or delivery source location get archived, the corresponding move may not be taken into account when computing the total_value / avg_cost at date. OPW-6099192 --- ### Test…
When a receipt dest location or delivery source location get archived, the corresponding move may not be taken into account when computing the total_value / avg_cost at date.
OPW-6099192
---
### Test result without fix
```
2026-04-23 06:30:34,016 10516 INFO oes_test_19 odoo.addons.stock_account.tests.test_stockvaluation: Starting TestStockValuation.test_archived_location_valuation ...
2026-04-23 06:30:34,255 10516 INFO oes_test_19 odoo.addons.stock_account.tests.test_stockvaluation: ======================================================================
2026-04-23 06:30:34,255 10516 ERROR oes_test_19 odoo.addons.stock_account.tests.test_stockvaluation: FAIL: TestStockValuation.test_archived_location_valuation
Traceback (most recent call last):
File "/home/odoo/Odoo/src/19.0/odoo/addons/stock_account/tests/test_stockvaluation.py", line 3326, in test_archived_location_valuation
self.assertEqual(self.product_avco.with_context(to_date=date_1).avg_cost, 10)
AssertionError: 20.0 != 10
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#264694
Forward-Port-Of: odoo/odoo#260922This update resolves a bug that caused the system to crash when signing salary contracts with a company car option in the configurator. The fix ensures the system correctly handles different contract scenarios, preventing errors and improving stability for users. This change impacts the Belgian payroll functionality.
Original PR description
Before this commit, signing a salary contract in the configurator with a company car selected could crash on the cp200_employees_salary_company_car (ATN.CAR) rule with KeyError('origin_version_id'), because the Belgian _get_period_contracts() accessed self.env.context['origin_version_id'] directly whenever salary_simulation was set, while hr_version_context injects salary_simulation=True without that key.
After this commit, the lookup uses .get() and falls back to the default behavior so the rule evaluates safely.
task-6240418
Forward-Port-Of: odoo/enterprise#118392This update streamlines the calculation of offer fields related to employee contracts, preventing unnecessary recomputations and ensuring accurate updates. Additionally, a recent change was corrected to properly handle payroll flows, ensuring consistent offer field visibility across all versions.
Original PR description
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced…
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced an unnecessary dependency chain: ``` contract_start_date -> employee_version_id -> contract_template_id -> wages and other offer fields ``` As a result, updating `contract_start_date` invalidates and recomputes the whole chain, even when `employee_version_id` does not actually change. In addition, offer fields were coupled in a single compute, causing unrelated fields to be reset to template values when only one field required recomputation. **Fix:** - `contract_template_id` compute now depends on `employee_id` instead of `employee_version_id`, and directly uses the employee's `version_id`, breaking the chain while preserving default behavior. - The offer fields computations were also split to avoid unintended recomputations and field resets. - Simplified `_get_version` by always copying values from the template to the currently active version. --- **Additional fix:** The `is_hr_payroll` context flag is used to distinguish payroll vs recruitment flows when creating an offer with both `employee_id` and `applicant_id` unset. A recent change in [Task #6094737](https://www.odoo.com/odoo/project/1251/tasks/6094737) did not account for this flag, causing both fields to be hidden when opening the form from Payroll (a new feature added in saas-19.3). This is fixed by properly considering `is_hr_payroll`, restoring consistent behavior across all versions. Task: 6158245 Forward-Port-Of: odoo/enterprise#115408
This update resolves an issue where branch users without access to a parent company couldn't create transactions in the parent company's currency journals. The fix ensures accurate currency conversion by temporarily elevating permissions during the transaction process, allowing branch users to manage transactions in parent company accounts.
Original PR description
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps…
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps to Reproduce:** - Make a branch of "My Company (San Francisco)" - Set user "Marc Demo" to only have access to the branch - Add a new bank journal set to "EUR" currency - Switch to Marc Demo - Try to add a transaction in the new bank journal **Root Cause:** When a transaction is created, Odoo determines the amount in company currency by converting it from the foreign currency. The method to convert currency uses "with_company()" to use the company's rates, but the allowed companies of the branch user does not have access to the parent company, causing an access error. **Solution:** Call the currency conversion with sudo() to ensure access to the relevant companies. Ticket [link](https://www.odoo.com/odoo/project.task/6186901) opw-6186901 Forward-Port-Of: odoo/odoo#263968 Forward-Port-Of: odoo/odoo#263425
This update resolves an issue where adjusting wages for employees below the minimum wage would unexpectedly terminate and restart their contracts. Now, when 'Adjust Wages' is clicked, a new, effective version is created within the existing contract, maintaining the original contract dates and minimum wage information. This ensures accurate payroll processing and avoids unnecessary contract changes.
Original PR description
Before this commit, clicking 'Adjust Wages' on the 'Employees Under Minimum Wage' warning terminated the active contract (setting contract_date_end to yesterday on the previous version) and started a brand new contract today. After this commit, the action creates a new effective-dated version within the active contract: it inherits the same contract_date_start and contract_date_end, and the minimum wage is written on it. task-6217548
This update corrects an error in the Peru - Accounting Reports module that was causing SUNAT to reject electronic reports. Specifically, the report was incorrectly including too much data in field 8 of the DAM document, leading to rejection. The fix ensures the correct 3-digit customs dependency code is used, aligning with SUNAT regulations.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
This update resolves a problem where UPS delivery confirmations were failing for shipments to locations outside of the USA, Canada, and Vietnam. The fix ensures that province codes are limited to 5 characters, aligning with UPS API requirements and preventing errors during shipment validation.
Original PR description
Issue ----- Users cannot confirm shipments depending on the destination's province. Steps to reproduce ----- - Set up UPS - Create a contact in Philipines - Province: Cebu - Create a delivery - Validate the delivery > Error message Cause ----- Codes can only be 5 characters long, as per the API https://developer.ups.com/tag/Shipping?loc=en_US#operation/Shipment According to the doc, the field is only useful for USA, Canada and Vietnam. ----- Ticket: opw-6149404 Forward-Port-Of: odoo/enterprise#117203
This update addresses a potential issue where the system struggled to reliably retrieve IAP VIES identifiers, impacting accurate VAT calculations. The fix includes improved testing and synchronization to ensure data consistency and prevent errors, particularly related to webhook token validity.
Original PR description
- Avoid race condition while getting the IAP VIES identifiers - Clarify to which state the Intra-Community value has been updated - Increment validity of the webhook_token while waiting for a push update - Add more tests, especially for the controller and the cron - Remove no-longer-relevant tests task-none Forward-Port-Of: odoo/odoo#266925 Forward-Port-Of: odoo/odoo#260440
This update ensures our KSeF vendor bill download cron job continues to run smoothly even if some XML files are corrupted. Previously, a single error would halt the entire process. Now, errors are logged, and the cron job successfully processes the remaining valid invoices, preventing data loss and improving efficiency.
Original PR description
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file…
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file is missing something that is expected, the parser raises a UserError. This unhandled exception halts the entire cron job and rolls back the database transaction, clogging up the rest of the queue. **Solution:** This PR wraps the l10n_pl_edi_get_ksef_bill_vals_from_xml parsing step inside a try/except block within the batch download loop. If a UserError is encountered for a specific invoice, the error is logged as a warning, and the cron proceeds. ### Current behavior before PR: A single malformed XML file causes the cron to fail completely. Valid invoices in the same batch are not created due to the halted queue. ### Desired behavior after PR is merged: The cron successfully processes the batch of downloaded XMLs even if one or more files are invalid. Errors on specific invoices are logged for the user to investigate, while the rest of the valid vendor bills in the batch are succesfully created. opw-6179479 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266180
Code cleanup and technical improvements
This update streamlines how key performance indicators (KPIs) are calculated within Odoo. By using direct SQL queries, KPI computations are now faster and more efficient, reducing the load on the system. This change improves the overall responsiveness of the reporting features.
Original PR description
Refactor KPI providers to compute summaries directly in SQL. This makes KPI computation callable from the /kpi/summary controller, which can call them without loading a registry. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/enterprise#118901 Forward-Port-Of: odoo/enterprise#113422
21 changes
New functionality added to Odoo
This update enables Odoo to comply with new French regulations requiring electronic reporting of B2C and international B2B transactions. It introduces a ‘Flux 10’ system for sending structured data to tax authorities, enhancing data accuracy and security through mandatory 2FA and KYC verification.
Original PR description
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B…
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B and the B2C. This creates two complementary obligations: - **E-invoicing** for domestic B2B transactions, where the invoice itself is exchanged through the PA/Peppol flow. - **E-reporting** for transactions outside that domestic B2B scope, mainly B2C and international B2B, where transaction and payment data must be reported to the tax administration through Flux 10 (period-based). ## Scope Domestic B2B remains handled by the existing e-invoicing flow, because the invoice exchange already carries the required structured information. Flux 10 is introduced for transactions that must be reported separately: - B2C transactions, where there is no buyer-side e-invoice exchange. - International B2B transactions, where the counterparty is outside the French domestic B2B mandate. - Payment reporting when VAT exigibility depends on collection. The reporting is period-based and keeps transaction reports separated from payment reports, because they answer different legal obligations and follow different timelines. ## Corrections and Lifecycle Flux 10 supports both: - **Initial reports**, for the first declaration of a period. - **Rectificative reports**, when already reported data must be corrected or completed. This distinction is needed so corrections remain traceable instead of silently mutating a report that may already have been transmitted. ## Security and Eligibility This PR also enforces stronger safeguards before using PDP/PA services. - **2FA is required** because PDP/PA actions expose regulated fiscal flows and should not be available from a simple password-only login. Email-based 2FA is available as a fallback when users have not configured an authenticator app. - **KYC is introduced** because a company must be identified and validated before Odoo can transmit documents or reports on its behalf through the PDP/PA infrastructure. Together, these changes make the French PDP/PA flow usable not only for invoice exchange, but also for the wider e-reporting obligations required by the French reform. Task-4603708 Forward-Port-Of: odoo/odoo#239576
This update streamlines KPI data retrieval across our servers by using a simplified SQL approach. Instead of loading separate registry data for each database, a new API endpoint accepts credentials and calls KPI providers directly. This significantly speeds up KPI generation and reporting.
Original PR description
In order to improve speed of KPI retrieval on servers hosting many databases, we need to avoid loading a registry for each of them. With this commit, we introduce a route /kpi/summary that accepts a list of credentials in the form of pairs of database name and API key. The API key needs to be local to the database. Modules providing KPIs need to declare a method named `get_kpi_summary` in a file named `models/kpi_provider.py`, and it will return the exact same structure as the previous API `kpi.provider:get_kpi_summary`. The existing ORM-called methods now call the SQL version in order to avoid divergences in the future. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/odoo#267347 Forward-Port-Of: odoo/odoo#258050
Enhancements to existing features
This update ensures that product tags sent to UrbanPiper are dynamically determined based on tax configurations and aggregator needs. Previously, tags were hardcoded, but now the system intelligently selects relevant tags, improving data accuracy and integration with the UrbanPiper platform.
Original PR description
Before this commit: ------------------------------------------ - The UrbanPiper payload used a hardcoded tag when the tax percentage was not 5%. - There was no mechanism to add additional tags based on providers, even though UrbanPiper supports multiple tags. After this commit: ------------------------------------------ - Tags are now dynamically handled using the Tag field in the product. - Users can define tags according to their tax configurations and aggregator requirements. - UrbanPiper only accepts relevant tags (default or provider-specific). task - 5154061 Forward-Port-Of: odoo/enterprise#112550 Forward-Port-Of: odoo/enterprise#96742
This update improves the handling of Philippine taxes within Odoo. Specifically, it reorganizes VAT and reverse charge taxes into groups with positive and negative components, streamlining calculations. It also disables automatic tax closing entries for withholding taxes, ensuring accurate reporting.
Original PR description
Restructure FWVAT DS and FWVAT EM from single percentage taxes into group taxes with two children each: a positive 12% input VAT child and a negative 12% reverse charge child (FWVAT RC). Also, we disable tax closing entry for WHT taxes. task-6146238 Forward-Port-Of: odoo/odoo#266625
Resolved issues and error corrections
This update corrects a bug where newly created product categories didn't automatically use the updated expense accounts set in the company's configuration. The change ensures that all product categories, including new ones, correctly reflect the current default expense and income account settings. This prevents discrepancies in financial reporting and simplifies account management.
Original PR description
**Steps to reproduce:** - Accounting > Configuration > Settings > Default Accounts > Product Accounts - Change the default expense account (and income account) - Create a new product category -…
**Steps to reproduce:** - Accounting > Configuration > Settings > Default Accounts > Product Accounts - Change the default expense account (and income account) - Create a new product category - category still proposed the old accounts Affected versions: from 18.2 till 19.2 **Cause:** `ir.default` for `product.category` (`property_account_expense_categ_id` and `property_account_income_categ_id`) was not updated when `res.company.expense_account_id` / `income_account_id` changed, so new categories kept using stale defaults. and in 19.0 https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L490 and https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L753 calls https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/account/models/company.py#L1136-L1139 However, when stock_account is installed https://github.com/odoo/odoo/blob/894281f2a3e313fc239529572b5cc8c06a3511f7/addons/stock_account/models/res_company.py#L361-L366 this gets called, without calling super, that's why it didn't work although the fix is there, we will need to adapt another fix in 19.0+ **Solution:** Call `_set_category_defaults()` in `res.company.write()` so `ir.default` stays aligned with the company's current product default accounts. opw-6145491 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265052 Forward-Port-Of: odoo/odoo#261594
This update addresses a performance issue in the account module's web interface. By restructuring CSS selectors, the system now loads faster, resulting in a smoother user experience. This change focuses on optimizing how the browser renders account-related pages.
Original PR description
This commit moves the span selector inside one of its parent styling selector block. This avoids the browser to check for any span and look for pseudo-classes :where and :has to compute its style, which caused unexpected slowlness in the webclient. Now, the browser firstly checks for the parent class, and then look for the more complex selectors present below. There are less occurence of the selector inside the component, and it is no longer global. Forward-Port-Of: odoo/odoo#266931
This update resolves an issue where appointment scheduling displayed 'no slots available' for appointments with booking ranges starting in the future. The fix ensures that the calendar accurately reflects available slots, regardless of when the booking period begins, providing a more reliable scheduling experience for users.
Original PR description
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots:…
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots: https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L833 For a punctual appointment whose Allow Bookings range starts in a future month, the first displayed month is start_datetime.month, so the (month, year) tuple doesn't match the month the visitor is looking at. The model fills an empty month and the recovery loop refills the first displayed month (where slots actually live): https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L973-L988 The calendar the visitor just navigated to comes back empty. Compute the navigation base from start_datetime when it lies in the future and keep datetime.now() otherwise. month_id is added on top of that base so it always matches the displayed month index. Introduced by https://github.com/odoo/enterprise/commit/664857dd2c4ae2bc0dde8f44cb94136659ed2fe2 Steps to reproduce: 1. Open the Appointments app 2. Open an appointment type and set Schedule to Weekly and Allow Bookings to On specific dates with a range starting in a future month (for example 1 September to 31 December) 3. Save and click the Preview button in the header 4. Pick a staff member to reach the calendar 5. Click the right arrow to navigate to the next month => the next month shows "Sorry, we have no more slots available for this month" opw-6206293 Forward-Port-Of: odoo/enterprise#117283
This update resolves an issue where resetting payroll work entries (attendance) would unexpectedly delete them. The problem stemmed from a mismatch between the calendar timezone and the employee's timezone when calculating the reset window. The fix ensures work entries are handled correctly regardless of timezone, preventing data loss.
Original PR description
Setup: Set the work entry source to attendance for an employee with active contract and change his timezone so that it differs from the working schedule one. Reset previous/next day delete Work Entry (payroll) - Step to reproduce: after an attendance was created, go to "Work Entries" in payroll, select the previous/next day and hit "Reset Selected Work Entries". The Work Entry will disappear. - Cause: reset window computed with calendar tz and work entry computed with user tz - Solution: localize work entries using calendar or user tz - Test: testing positive ans negative tz in hr_work_entry_attendance (enterprise) Task: 6072325 Forward-Port-Of: odoo/odoo#266537 Forward-Port-Of: odoo/odoo#257309
This update corrects a bug where the 'Reset Selected Work Entries' function in the payroll module was unexpectedly deleting work entries due to timezone discrepancies. The fix adjusts the system's timezone handling to ensure accurate work entry management, preventing data loss and improving payroll processing reliability.
Original PR description
Setup: Set the work entry source to attendance for an employee with active contract and change his timezone so that it differs from the working schedule one. Reset previous/next day delete Work Entry (payroll) - Step to reproduce: after an attendance was created, go to "Work Entries" in payroll, select the previous/next day and hit "Reset Selected Work Entries". The Work Entry will disappear. - Cause: domain to nullify using wrong tz - Solution: adjust domain to use calendar tz - Test: testing positive ans negative tz in hr_work_entry_attendance (enterprise) Task: 6072325 Forward-Port-Of: odoo/enterprise#118441 Forward-Port-Of: odoo/enterprise#114148
This update resolves an issue where Odoo was incorrectly generating CFDI invoices in Mexico, leading to XML rejection by tax authorities. The fix ensures that cash rounding lines, which are not valid CFDI concepts, are excluded, aligning with SAT regulations. This prevents errors and ensures accurate invoice generation.
Original PR description
When using the 'add_invoice_line' cash rounding strategy, Odoo adds a journal line with display_type='rounding'. This line has no product and therefore no ClaveProdServ, causing PAC to reject the XML with error 301. Per SAT regulations, cash rounding is not a valid CFDI concept. The CFDI must report the pre-rounding amounts (e.g. 99.80); the rounding difference (e.g. 0.20) belongs only in the journal entry on the accounting side. opw-6024078 Forward-Port-Of: odoo/enterprise#117400 Forward-Port-Of: odoo/enterprise#112633
This update fixes a problem preventing AI Livechat embedded on other websites from receiving AI responses correctly. The previous setup bypassed security controls, and the response format was incompatible. The fix exposes the necessary endpoint as an HTTP stream and ensures the correct guest token is passed, allowing seamless AI interaction within embedded Livechat.
Original PR description
AI livechat embedded on another origin could not receive AI responses. The response stream is requested with fetch(), so it bypassed the livechat CORS routing that only wraps RPC calls. The matching CORS controller was also exposed as JSON-RPC, which cannot return the streamed HTTP response correctly. Expose the CORS endpoint as an HTTP stream, route the embedded fetch call to it, and pass the livechat guest token explicitly. task-id-6201054 Forward-Port-Of: odoo/enterprise#117535
This update fixes an issue where orders captured in a POS session would incorrectly reappear in a new session after a device was used to close the original. This prevented users from accurately tracking order history and caused confusion about session dates. The change ensures orders are properly recorded in the intended session.
Original PR description
Before this commit, if an order was captured in a session but could not be synced to the server, and the session was closed from another device, the order would be captured in the opening control session that created after the closing. This could lead to confusion for the user as the session opening date would be after the order capture date. opw-6207434 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263776
This update fixes an issue where POS refund orders were incorrectly showing as paid, leading to an underestimation of the outstanding balance on linked sales orders. The change ensures that refund amounts are properly accounted for when calculating the unpaid balance, improving the accuracy of financial reporting. This resolves a previous bug reported as opw-6190337.
Original PR description
POS refund order lines have a positive `price_subtotal_incl` but represent money returned to the customer. `_compute_amount_unpaid` was treating them as paid amounts, causing the unpaid balance on the linked sale order to be understated. opw-6190337 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263241
This update fixes an issue where receipts for orders with many items (over 70) would be cut off mid-print, resulting in incomplete tickets. The fix increases the timeout period for printing, ensuring that all order details are printed correctly, even with extensive product lists. This improves the customer experience and prevents data loss.
Original PR description
**Steps to reproduce:** - Connect an Epson printer - Go to the PoS - Make an order with 50+ products (70 to be safe) - Pay for it and try to print the receipt - It will stop halfway through, and the next ticket will have some leftover lines on top of it **Why the fix:** In d2a4bbc the timeout for the error popup was reduced from 15000 to 3000, and a timeout on the request was also added at 3000. This means that after 3000ms, the printing will stop, even in the middle of printing. Because of this, if the order has too many items, the printing will be forcefully stopped before everything could be printed, and as we stopped it in the middle, some leftover lines can be found on top of the next printed ticket. After this commit, the timeout is set to double the current time, and will be expanded further if we still have some issues. opw-6049062
This update streamlines the calculation of offer fields, resolving performance issues caused by unnecessary dependency chains and redundant computations. Additionally, a fix ensures offer forms display correctly within the payroll workflow, maintaining consistent functionality across versions.
Original PR description
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced…
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced an unnecessary dependency chain: ``` contract_start_date -> employee_version_id -> contract_template_id -> wages and other offer fields ``` As a result, updating `contract_start_date` invalidates and recomputes the whole chain, even when `employee_version_id` does not actually change. In addition, offer fields were coupled in a single compute, causing unrelated fields to be reset to template values when only one field required recomputation. **Fix:** - `contract_template_id` compute now depends on `employee_id` instead of `employee_version_id`, and directly uses the employee's `version_id`, breaking the chain while preserving default behavior. - The offer fields computations were also split to avoid unintended recomputations and field resets. - Simplified `_get_version` by always copying values from the template to the currently active version. --- **Additional fix:** The `is_hr_payroll` context flag is used to distinguish payroll vs recruitment flows when creating an offer with both `employee_id` and `applicant_id` unset. A recent change in [Task #6094737](https://www.odoo.com/odoo/project/1251/tasks/6094737) did not account for this flag, causing both fields to be hidden when opening the form from Payroll (a new feature added in saas-19.3). This is fixed by properly considering `is_hr_payroll`, restoring consistent behavior across all versions. Task: 6158245 Forward-Port-Of: odoo/enterprise#115408
This update resolves an issue where branch users without access to a parent company couldn't create transactions in the parent company's currency journals. The fix ensures accurate currency conversion by temporarily elevating permissions during the transaction process, allowing branch users to manage transactions in parent company accounts.
Original PR description
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps…
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps to Reproduce:** - Make a branch of "My Company (San Francisco)" - Set user "Marc Demo" to only have access to the branch - Add a new bank journal set to "EUR" currency - Switch to Marc Demo - Try to add a transaction in the new bank journal **Root Cause:** When a transaction is created, Odoo determines the amount in company currency by converting it from the foreign currency. The method to convert currency uses "with_company()" to use the company's rates, but the allowed companies of the branch user does not have access to the parent company, causing an access error. **Solution:** Call the currency conversion with sudo() to ensure access to the relevant companies. Ticket [link](https://www.odoo.com/odoo/project.task/6186901) opw-6186901 Forward-Port-Of: odoo/odoo#263968 Forward-Port-Of: odoo/odoo#263425
This update corrects a technical issue in the Peru Accounting Reports module that was causing reports to be rejected by the SUNAT system. Specifically, the report was incorrectly including too much data in field 8 of the DAM document, leading to an error. The fix ensures the report accurately uses the required 3-digit customs dependency code as defined by SUNAT regulations.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
This update improves the stability of the KSeF vendor bill download cron job. Previously, a single error in an XML file would halt the entire process. Now, the system gracefully handles parsing errors, logs them for investigation, and continues processing valid invoices, preventing data loss and queue congestion.
Original PR description
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file…
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file is missing something that is expected, the parser raises a UserError. This unhandled exception halts the entire cron job and rolls back the database transaction, clogging up the rest of the queue. **Solution:** This PR wraps the l10n_pl_edi_get_ksef_bill_vals_from_xml parsing step inside a try/except block within the batch download loop. If a UserError is encountered for a specific invoice, the error is logged as a warning, and the cron proceeds. ### Current behavior before PR: A single malformed XML file causes the cron to fail completely. Valid invoices in the same batch are not created due to the halted queue. ### Desired behavior after PR is merged: The cron successfully processes the batch of downloaded XMLs even if one or more files are invalid. Errors on specific invoices are logged for the user to investigate, while the rest of the valid vendor bills in the batch are succesfully created. opw-6179479 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266180
This update resolves a problem where users couldn't confirm shipments due to incorrect province codes being submitted to the UPS API. The fix ensures that only 5-character province codes are used, aligning with the API's requirements and limitations for supported regions (USA, Canada, and Vietnam).
Original PR description
Issue ----- Users cannot confirm shipments depending on the destination's province. Steps to reproduce ----- - Set up UPS - Create a contact in Philipines - Province: Cebu - Create a delivery - Validate the delivery > Error message Cause ----- Codes can only be 5 characters long, as per the API https://developer.ups.com/tag/Shipping?loc=en_US#operation/Shipment According to the doc, the field is only useful for USA, Canada and Vietnam. ----- Ticket: opw-6149404 Forward-Port-Of: odoo/enterprise#117203
This update fixes an issue where half-day absences were incorrectly rounding up hours, leading to inaccurate payroll calculations for employees using flexible schedules. The change decouples the scheduling logic, allowing for precise splitting of half and full days, ensuring accurate work hour totals and payroll processing. This improves the reliability of the flexible schedule feature.
Original PR description
Steps: - Create half day off for an employee - Create a full day off of the same type - Create a payslip for the employee Issue: - Due to the lack of attendance hours in the flexible schedules, the _get_work_hours_split_half is unable to split half day and full days work entries of the same type. - Half worked days will be rounded up which affects the total number of work days in a month Solution: The approach was to decouple the work_hours_split_half functionality from the attendance hours and rely on the specified hours_per_day instead. This accurately splits half and full days. Task: 6253675
Code cleanup and technical improvements
This update streamlines how key performance indicators (KPIs) are calculated within Odoo. By using direct SQL queries, the system now computes KPI summaries more efficiently, reducing the load on the system. This results in faster reporting and a better user experience.
Original PR description
Refactor KPI providers to compute summaries directly in SQL. This makes KPI computation callable from the /kpi/summary controller, which can call them without loading a registry. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/enterprise#118901 Forward-Port-Of: odoo/enterprise#113422
16 changes
New functionality added to Odoo
This update implements French e-reporting requirements for B2C and international B2B transactions, ensuring compliance with new tax regulations. It introduces a period-based system for reporting transaction data to the French tax authorities, enhancing data accuracy and security through stronger authentication measures.
Original PR description
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B…
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B and the B2C. This creates two complementary obligations: - **E-invoicing** for domestic B2B transactions, where the invoice itself is exchanged through the PA/Peppol flow. - **E-reporting** for transactions outside that domestic B2B scope, mainly B2C and international B2B, where transaction and payment data must be reported to the tax administration through Flux 10 (period-based). ## Scope Domestic B2B remains handled by the existing e-invoicing flow, because the invoice exchange already carries the required structured information. Flux 10 is introduced for transactions that must be reported separately: - B2C transactions, where there is no buyer-side e-invoice exchange. - International B2B transactions, where the counterparty is outside the French domestic B2B mandate. - Payment reporting when VAT exigibility depends on collection. The reporting is period-based and keeps transaction reports separated from payment reports, because they answer different legal obligations and follow different timelines. ## Corrections and Lifecycle Flux 10 supports both: - **Initial reports**, for the first declaration of a period. - **Rectificative reports**, when already reported data must be corrected or completed. This distinction is needed so corrections remain traceable instead of silently mutating a report that may already have been transmitted. ## Security and Eligibility This PR also enforces stronger safeguards before using PDP/PA services. - **2FA is required** because PDP/PA actions expose regulated fiscal flows and should not be available from a simple password-only login. Email-based 2FA is available as a fallback when users have not configured an authenticator app. - **KYC is introduced** because a company must be identified and validated before Odoo can transmit documents or reports on its behalf through the PDP/PA infrastructure. Together, these changes make the French PDP/PA flow usable not only for invoice exchange, but also for the wider e-reporting obligations required by the French reform. Task-4603708 Forward-Port-Of: odoo/odoo#239576
Enhancements to existing features
This update streamlines KPI data retrieval across Odoo servers by using a simplified SQL approach. Previously, each database required a separate registry load, which was slow. Now, KPIs are fetched more efficiently using a new API endpoint and a standardized SQL query, resulting in faster reporting.
Original PR description
In order to improve speed of KPI retrieval on servers hosting many databases, we need to avoid loading a registry for each of them. With this commit, we introduce a route /kpi/summary that accepts a list of credentials in the form of pairs of database name and API key. The API key needs to be local to the database. Modules providing KPIs need to declare a method named `get_kpi_summary` in a file named `models/kpi_provider.py`, and it will return the exact same structure as the previous API `kpi.provider:get_kpi_summary`. The existing ORM-called methods now call the SQL version in order to avoid divergences in the future. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/odoo#258050
This update improves the handling of Philippine taxes within Odoo. Specifically, it reorganizes VAT taxes into groups with input and reverse charge components, and disables automatic tax closing for withholding taxes. These changes ensure accurate tax calculations and compliance with Philippine regulations.
Original PR description
Restructure FWVAT DS and FWVAT EM from single percentage taxes into group taxes with two children each: a positive 12% input VAT child and a negative 12% reverse charge child (FWVAT RC). Also, we disable tax closing entry for WHT taxes. task-6146238 Forward-Port-Of: odoo/odoo#266625
This update ensures that product tags sent to UrbanPiper are dynamically managed based on a product's settings and tax configurations. Previously, tags were hardcoded, but now the system automatically handles relevant tags, improving accuracy and flexibility for integrations with UrbanPiper.
Original PR description
Before this commit: ------------------------------------------ - The UrbanPiper payload used a hardcoded tag when the tax percentage was not 5%. - There was no mechanism to add additional tags based on providers, even though UrbanPiper supports multiple tags. After this commit: ------------------------------------------ - Tags are now dynamically handled using the Tag field in the product. - Users can define tags according to their tax configurations and aggregator requirements. - UrbanPiper only accepts relevant tags (default or provider-specific). task - 5154061 Forward-Port-Of: odoo/enterprise#112550 Forward-Port-Of: odoo/enterprise#96742
Resolved issues and error corrections
This update resolves a performance issue that was causing slow rendering in the Odoo web client. By restructuring CSS selectors, the system now processes styles more efficiently, leading to a faster and smoother user experience. This change focuses on optimizing the visual presentation of the application.
Original PR description
This commit moves the span selector inside one of its parent styling selector block. This avoids the browser to check for any span and look for pseudo-classes :where and :has to compute its style, which caused unexpected slowlness in the webclient. Now, the browser firstly checks for the parent class, and then look for the more complex selectors present below. There are less occurence of the selector inside the component, and it is no longer global. Forward-Port-Of: odoo/odoo#266931
This update resolves an issue where appointment scheduling displayed 'no slots available' for appointments with booking ranges starting in the future. The fix ensures that the calendar correctly reflects all available months, regardless of when the booking range begins, providing a more accurate and user-friendly appointment booking experience.
Original PR description
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots:…
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots: https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L833 For a punctual appointment whose Allow Bookings range starts in a future month, the first displayed month is start_datetime.month, so the (month, year) tuple doesn't match the month the visitor is looking at. The model fills an empty month and the recovery loop refills the first displayed month (where slots actually live): https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L973-L988 The calendar the visitor just navigated to comes back empty. Compute the navigation base from start_datetime when it lies in the future and keep datetime.now() otherwise. month_id is added on top of that base so it always matches the displayed month index. Introduced by https://github.com/odoo/enterprise/commit/664857dd2c4ae2bc0dde8f44cb94136659ed2fe2 Steps to reproduce: 1. Open the Appointments app 2. Open an appointment type and set Schedule to Weekly and Allow Bookings to On specific dates with a range starting in a future month (for example 1 September to 31 December) 3. Save and click the Preview button in the header 4. Pick a staff member to reach the calendar 5. Click the right arrow to navigate to the next month => the next month shows "Sorry, we have no more slots available for this month" opw-6206293 Forward-Port-Of: odoo/enterprise#117283
This update resolves an issue where paying with the 'customer account' payment method on a zero-priced POS order incorrectly created a customer balance due. The fix hides the 'pay_later' payment option in this scenario, aligning with business requirements and preventing incorrect financial reporting. This ensures accurate order settlement.
Original PR description
Step to reproduce: - install "pos_settle_due" - create a pos order, set order price = 0, select a customer - go to payment page, select "customer account" as payment method - here you can set any…
Step to reproduce: - install "pos_settle_due" - create a pos order, set order price = 0, select a customer - go to payment page, select "customer account" as payment method - here you can set any amount to pay, ex 100$ - fulfill the order. Observation: - the order amount is 0, if we pay 100$ using customer account, it is considered as change (which means we returned it to customer) - As per PO, this flow doesn't make sense Issue: - customer has 100$ due for this order, but he won't be able to settle this as fetch order to settle with amount != 0, after commit [1] - [1] https://github.com/odoo/enterprise/commit/12af23d5382e972facfaa999e4c5ab30c97e8d1f https://github.com/odoo/enterprise/blob/951e5f42884c898bc14d9c32ae6a8f08c31ff06d/pos_settle_due/static/src/app/screens/partner_list/partner_line/partner_line.js#L35 Fix: - we hide payment method of type "pay_later" in case of 0 price order opw-6123699 Forward-Port-Of: odoo/enterprise#118296 Forward-Port-Of: odoo/enterprise#116556
This update fixes a bug where POS refund orders were incorrectly showing as paid, leading to an inaccurate calculation of outstanding balances on linked sale orders. The change ensures that refund amounts are properly accounted for when determining the unpaid balance, improving the accuracy of financial reporting. This resolves issue OPW-6190337.
Original PR description
POS refund order lines have a positive `price_subtotal_incl` but represent money returned to the customer. `_compute_amount_unpaid` was treating them as paid amounts, causing the unpaid balance on the linked sale order to be understated. opw-6190337 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263241
This update resolves an issue where the Documents app's PDF preview displayed incorrectly, showing a duplicate iframe. The fix ensures that the preview accurately renders PDF attachments received via email, addressing a problem caused by how the system identifies file types. This improvement ensures consistent and reliable PDF viewing within the Documents application.
Original PR description
**Steps to reproduce:** - Install documents_account - Set up alias to catch incoming mails - Receive a mail with xml attachement which can be previewed as pdf - Go to Documents app - Click on the…
**Steps to reproduce:** - Install documents_account - Set up alias to catch incoming mails - Receive a mail with xml attachement which can be previewed as pdf - Go to Documents app - Click on the document preview - Preview is split in two iframes, both with the same content (pdf) **Issue:** Due to the `isPdf` patch the attachment can match multiple types for the preview (pdf and text) as both getter return `true`. ``` <iframe t-if="state.file.isPdf" ... <iframe t-if="state.file.isText" ... ``` It also seems that xml received by mail are imported as text, which is why the issue doesn't happen when manually uploading the same xml file. **Fix:** Ensure that if the document is matching `isPdf`, it doesn't trigger the second iframe with `isText`. Also it seems fixed in 19.0 as the text iframe is replaced by this xpath: `<xpath expr="//iframe[@t-if='state.file.isText']" position="replace">` which was added for https://github.com/odoo/enterprise/commit/de614ee5e9a087d49939c65c0118ae6164c7b31b related patch: https://github.com/odoo/enterprise/commit/ffcdd2275c8bf564e15151ccbcaf3965ed968450 opw-6018536 Forward-Port-Of: odoo/enterprise#118041 Forward-Port-Of: odoo/enterprise#112041
This update resolves an issue where product variants weren't being created in the Point of Sale (POS) system when a product template used a dynamic attribute with a single value. Previously, this prevented users from adding correctly configured items to their orders, leading to errors. This change ensures that all product variants are created, improving the reliability of the POS system.
Original PR description
When a product template has a dynamic attribute with only one value, `isConfigurable()` returns `false` (correctly suppressing the configurator popup), but `create_product_variant_from_pos` was never called, leaving the order line without a proper variant and causing error when trying to add it to the order. opw-6213957 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264134
This update resolves an issue where branch users without access to a parent company couldn't create transactions in the parent company's currency. The fix ensures accurate currency conversion by temporarily elevating access privileges, allowing branch users to properly handle foreign currency transactions within their respective company journals.
Original PR description
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps…
**Problem:** When a branch user with no access to the parent company tries to create a transaction for a parent company's journal with a foreign currency set, this will raise an access error. **Steps to Reproduce:** - Make a branch of "My Company (San Francisco)" - Set user "Marc Demo" to only have access to the branch - Add a new bank journal set to "EUR" currency - Switch to Marc Demo - Try to add a transaction in the new bank journal **Root Cause:** When a transaction is created, Odoo determines the amount in company currency by converting it from the foreign currency. The method to convert currency uses "with_company()" to use the company's rates, but the allowed companies of the branch user does not have access to the parent company, causing an access error. **Solution:** Call the currency conversion with sudo() to ensure access to the relevant companies. Ticket [link](https://www.odoo.com/odoo/project.task/6186901) opw-6186901 Forward-Port-Of: odoo/odoo#263968 Forward-Port-Of: odoo/odoo#263425
This update corrects an error in the Peru - Accounting Reports module that was causing SUNAT's electronic reporting system (SIRE) to reject DAM (Declaración Aduanera de Mercancías) reports. The fix ensures the correct 3-digit customs dependency code is used in field 8, aligning with SUNAT regulations. This prevents report rejections and ensures accurate data submission.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
Previously, a single error in downloading vendor bills from KSeF via the cron job would halt the entire process. This update fixes this by allowing the cron job to continue processing valid invoices even if some XML files are malformed, logging the errors for investigation. This ensures a more reliable and efficient import of vendor bills.
Original PR description
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file…
### Description of the issue/feature this PR addresses: **Issue:** When downloading vendor bills from KSeF via the cron, the system attempts to parse the XML files sequentially. If a single XML file is missing something that is expected, the parser raises a UserError. This unhandled exception halts the entire cron job and rolls back the database transaction, clogging up the rest of the queue. **Solution:** This PR wraps the l10n_pl_edi_get_ksef_bill_vals_from_xml parsing step inside a try/except block within the batch download loop. If a UserError is encountered for a specific invoice, the error is logged as a warning, and the cron proceeds. ### Current behavior before PR: A single malformed XML file causes the cron to fail completely. Valid invoices in the same batch are not created due to the halted queue. ### Desired behavior after PR is merged: The cron successfully processes the batch of downloaded XMLs even if one or more files are invalid. Errors on specific invoices are logged for the user to investigate, while the rest of the valid vendor bills in the batch are succesfully created. opw-6179479 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266180
This update resolves a problem where users couldn't confirm shipments to certain locations, specifically in the Philippines (Cebu). The issue stemmed from the UPS API requiring province codes to be only 5 characters long, which wasn't being enforced. This fix ensures that only valid, short province codes are used, allowing shipments to be confirmed correctly.
Original PR description
Issue ----- Users cannot confirm shipments depending on the destination's province. Steps to reproduce ----- - Set up UPS - Create a contact in Philipines - Province: Cebu - Create a delivery - Validate the delivery > Error message Cause ----- Codes can only be 5 characters long, as per the API https://developer.ups.com/tag/Shipping?loc=en_US#operation/Shipment According to the doc, the field is only useful for USA, Canada and Vietnam. ----- Ticket: opw-6149404 Forward-Port-Of: odoo/enterprise#117203
This update streamlines the calculation of offer fields, optimizing performance by removing unnecessary dependencies and reducing redundant recomputations. Additionally, a fix ensures offer fields are displayed correctly when creating offers from the payroll module, resolving a previous display issue.
Original PR description
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced…
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced an unnecessary dependency chain: ``` contract_start_date -> employee_version_id -> contract_template_id -> wages and other offer fields ``` As a result, updating `contract_start_date` invalidates and recomputes the whole chain, even when `employee_version_id` does not actually change. In addition, offer fields were coupled in a single compute, causing unrelated fields to be reset to template values when only one field required recomputation. **Fix:** - `contract_template_id` compute now depends on `employee_id` instead of `employee_version_id`, and directly uses the employee's `version_id`, breaking the chain while preserving default behavior. - The offer fields computations were also split to avoid unintended recomputations and field resets. - Simplified `_get_version` by always copying values from the template to the currently active version. --- **Additional fix:** The `is_hr_payroll` context flag is used to distinguish payroll vs recruitment flows when creating an offer with both `employee_id` and `applicant_id` unset. A recent change in [Task #6094737](https://www.odoo.com/odoo/project/1251/tasks/6094737) did not account for this flag, causing both fields to be hidden when opening the form from Payroll (a new feature added in saas-19.3). This is fixed by properly considering `is_hr_payroll`, restoring consistent behavior across all versions. Task: 6158245 Forward-Port-Of: odoo/enterprise#115408
Code cleanup and technical improvements
This update streamlines how key performance indicators (KPIs) are calculated within Odoo. By using SQL directly to generate KPI summaries, the system now responds faster and more efficiently. This change allows the /kpi/summary controller to directly access these calculations, eliminating the need for a separate registry.
Original PR description
Refactor KPI providers to compute summaries directly in SQL. This makes KPI computation callable from the /kpi/summary controller, which can call them without loading a registry. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/enterprise#113422
3 changes
Resolved issues and error corrections
This update resolves a critical issue that caused OOM crashes when generating the Swedish SIE 4 report with large datasets. By optimizing the database query and using efficient data processing techniques, the report now runs significantly faster and uses far less memory, improving overall system performance.
Original PR description
### Description of the issue/feature this PR addresses: Prevent Out of Memory (OOM) crashes and drastically improve execution speed when generating the Swedish SIE4 verification export for massive…
### Description of the issue/feature this PR addresses: Prevent Out of Memory (OOM) crashes and drastically improve execution speed when generating the Swedish SIE4 verification export for massive datasets. ### Current behavior before PR: When exporting a large volume of journal entries (e.g., 190,000+ account moves), the `_export_l10n_se_sie4_verification` method relies on iterating through heavy ORM recordsets and accessing relational child fields (move.line_ids) inside a loop. This triggers a severe N+1 query problem, maxing out server RAM and causing an OOM crash. ### Desired behavior after PR is merged: The method now utilizes a hybrid data extraction approach: - The ORM is used strictly to safely evaluate domains (multi-company rules, dates, states) and fetch a lightweight list of valid move_ids. - A single SQL query with JOIN statements fetches all parent moves, child lines, and account codes in exactly one database query. - itertools.groupby chunks the flat, lightweight dictionary results back into their respective journal entries. The export now handles massive datasets in seconds with minimal memory overhead, while remaining perfectly secure. ### Benchmark: For Memory: | # Input Data | Before PR | After PR | | -------- | -------- | -------- | | ~190,000 moves | MemoryError | 407MB| | ~200,000 moves | 1.8GB | 174.8 MB| For Speed: | # Input Data | Before PR | After PR | | -------- | -------- | -------- | | ~190,000 moves | MemoryError | 5.10s | | ~200,000 moves | 1m29s| 5.3s| ### Reference: opw-6067999 Forward-Port-Of: odoo/enterprise#117577 Forward-Port-Of: odoo/enterprise#113227
This update ensures Odoo automatically syncs product tags with UrbanPiper, resolving an issue where a single, hardcoded tag was used. Now, users can define relevant tags based on their tax settings and UrbanPiper's requirements, leading to more accurate data transmission and improved integration.
Original PR description
Before this commit: ------------------------------------------ - The UrbanPiper payload used a hardcoded tag when the tax percentage was not 5%. - There was no mechanism to add additional tags based on providers, even though UrbanPiper supports multiple tags. After this commit: ------------------------------------------ - Tags are now dynamically handled using the Tag field in the product. - Users can define tags according to their tax configurations and aggregator requirements. - UrbanPiper only accepts relevant tags (default or provider-specific). task - 5154061 Forward-Port-Of: odoo/enterprise#112550 Forward-Port-Of: odoo/enterprise#96742
This update fixes an issue where payments to the Mexican tax authority (CFDI) were being sent multiple times for the same invoice. The fix ensures the 'Update Payments' button only appears after the full invoice payment is reconciled, preventing inaccurate reporting and potential overpayment issues. This improves financial accuracy and compliance.
Original PR description
Issue: Sending payments to SAT before its full amount is reconciled allow sending the same invoice payment several times to CFDI. Steps to reproduce: - In a Mexican company - Create an invoice A of…
Issue: Sending payments to SAT before its full amount is reconciled allow sending the same invoice payment several times to CFDI. Steps to reproduce: - In a Mexican company - Create an invoice A of $40 to Inmobiliaria CVA - Confirm and send to CFDI - Go to bank, create a new Bank transaction of $80 - reconcile with Invoice A - Go to invoice A => click on button "Update payments" (it doesn't appear in previous versions) - Then sheet CFDI and Download There is the first XML sent to CFDI with payment for invoice A - Create an invoice B of $40 to Inmobilira CVA - Confirm and send to CFDI - reconcile the transaction with Invoice B - Go to invoice B - Click on button "Update payments" - Then sheet CFDI and Download There is the second XML sent to CFDI with payment for invoices A and B Invoice A payment was sent twice to CFDI Expected behavior: - The "Update payment" button should appear only once the invoice payment is fully reconciled. Current behavior: - The update payment button appear once the invoice is reconciled with a payment. The method `_l10n_mx_edi_cfdi_invoice_get_payments_diff` is called twice, once to check whether it's needed to display the "Update button" and once when you try to update the payment (called only after clicking on said button). opw-5432421 Forward-Port-Of: odoo/enterprise#108355
7 changes
New functionality added to Odoo
This update enables Odoo to comply with new French tax regulations requiring electronic reporting of business transactions. It introduces a system for sending transaction and payment data to the tax authorities in a structured format, specifically for B2C and international B2B sales, ensuring accurate tax reporting and compliance.
Original PR description
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B…
France’s electronic invoicing reform : The tax administration needs structured fiscal data for the transactions , either via E-invoicing for the nationals B2B or E-reporting for the international B2B and the B2C. This creates two complementary obligations: - **E-invoicing** for domestic B2B transactions, where the invoice itself is exchanged through the PA/Peppol flow. - **E-reporting** for transactions outside that domestic B2B scope, mainly B2C and international B2B, where transaction and payment data must be reported to the tax administration through Flux 10 (period-based). ## Scope Domestic B2B remains handled by the existing e-invoicing flow, because the invoice exchange already carries the required structured information. Flux 10 is introduced for transactions that must be reported separately: - B2C transactions, where there is no buyer-side e-invoice exchange. - International B2B transactions, where the counterparty is outside the French domestic B2B mandate. - Payment reporting when VAT exigibility depends on collection. The reporting is period-based and keeps transaction reports separated from payment reports, because they answer different legal obligations and follow different timelines. ## Corrections and Lifecycle Flux 10 supports both: - **Initial reports**, for the first declaration of a period. - **Rectificative reports**, when already reported data must be corrected or completed. This distinction is needed so corrections remain traceable instead of silently mutating a report that may already have been transmitted. ## Security and Eligibility This PR also enforces stronger safeguards before using PDP/PA services. - **2FA is required** because PDP/PA actions expose regulated fiscal flows and should not be available from a simple password-only login. Email-based 2FA is available as a fallback when users have not configured an authenticator app. - **KYC is introduced** because a company must be identified and validated before Odoo can transmit documents or reports on its behalf through the PDP/PA infrastructure. Together, these changes make the French PDP/PA flow usable not only for invoice exchange, but also for the wider e-reporting obligations required by the French reform. Task-4603708 Forward-Port-Of: odoo/odoo#239576
Resolved issues and error corrections
This update resolves a problem where users authenticating with Polish PESEL certificates were incorrectly rejected by KSeF. The change expands the matching criteria for certificate identifiers, ensuring existing users with standard certificates continue to function correctly. This prevents authentication errors and maintains seamless operation for our Polish customers.
Original PR description
### Description of the issue/feature this PR addresses: **Issue:** A recent update to support `certificateFingerprint` introduced a regression for existing users authenticating with standard…
### Description of the issue/feature this PR addresses: **Issue:** A recent update to support `certificateFingerprint` introduced a regression for existing users authenticating with standard certificates (AKA `certificateSubject`). Because the matching logic strictly checked for the company NIP within the certificate subject, it failed for users using personal PESEL certificates to act on a company's behalf. **Previous PR:** https://github.com/odoo/odoo/pull/264851 **Solution:** Expanded the string-matching heuristic in the XML signer to strip formatting characters from the NIP and explicitly checks for standard Polish qualified certificate prefixes (VATPL and PNOPL) to accurately get the identifier type. ### Current behavior before PR: When a user logs in via a personal PESEL certificate for a company context, the NIP check fails and miscategorizes the payload as a `certificateFingerprint`. KSeF rejects this mismatch, causing a 400 error for previously working setups. ### Desired behavior after PR is merged: The authentication flow distinguishes between `certificateSubject` and `certificateFingerprint` by checking for valid Polish prefixes or exact cleaned NIP matches. Existing customers are restored to working order natively, and new customers using manual fingerprints are still supported without requiring any database or UI changes. opw-6251153 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267060
This update resolves an issue where dropshipping orders incorrectly displayed a negative delivered quantity. The change introduced a new feature for returns, which caused a default setting to add incoming stock moves to the calculation, leading to a -1 quantity. This fix restores the correct delivery quantity by reverting a previous change.
Original PR description
Currently, an error occurs when the user receives a dropship order instead of delivering it directly to the customer. As a result, the sale order shows a negative delivered quantity. ## Steps to…
Currently, an error occurs when the user receives a dropship order instead of delivering it directly to the customer. As a result, the sale order shows a negative delivered quantity. ## Steps to replicate: - Install Sales, Inventory, and Purchase. - Enable Dropshipping from Inventory settings. - Create a test product with the Dropship route enabled and set a vendor for it in the Purchase tab. - Create and confirm a quotation for a customer. - Go to Purchase > `Deliver To:` and set it to `My Company: Receipts.` - Confirm the Purchase Order and validate the receipt. - Go back to the Sale Order. ## Observed Behavior: The delivered quantity is -1, which is incorrect because the customer has not returned any products, nor has the user created a sale order line with a negative quantity (which would indicate a return). ## Root cause: When computing the delivered quantity at [1], the function `_get_outgoing_incoming_moves` [2] is called to retrieve the incoming and outgoing stock moves associated with the sale order lines. Inside this function, moves are filtered and categorized as incoming or outgoing. At [3], the condition is satisfied because the default value of `to_refund` is `True`, so the move is added to `incoming_move_ids`. Later, during the computation at [1], the code iterates through the incoming moves and subtracts their quantities from the delivered quantity. Since the initial delivered quantity is 0, including such a move in `incoming_move_ids` causes the delivered quantity to become -1. <h3> Why did this behavior not occur in lower versions?:</h3> This issue was introduced by [commit], which added the functionality for users to return products that are not listed in the purchase order. As a result, their quantities appear as negative received quantities on the purchase order. Before this change (in saas-18.2), the field `move.to_refund` had a default value of `False`. Because of this, the condition at [3] was not satisfied, and the move was not included in `incoming_move_ids`. Therefore, it was not subtracted when iterating through incoming moves, and the delivered quantity did not become negative. Starting from 18.3, the default value of `to_refund` was changed to `True`. This causes the condition at [3] to be satisfied, the move to be included in `incoming_move_ids`, and its quantity to be subtracted during the computation, resulting in a delivered quantity of -1. [1]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L193-L209 [2]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L316-L353 [3]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L346-L351 ## Solution: We can make the condition stricter by ensuring that only incoming moves that are actual returns are counted as negative in the quantity delivered on a sale order. Specifically, if an incoming move has no corresponding originating return move and the customer has not created a sale order line with a negative quantity (which could also indicate a return), it should not be considered when calculating the delivered quantity. [commit]: https://github.com/odoo/odoo/pull/209110/changes/c1c86182e4b28e929bf56e79f57f33aaa13e67f1 opw-5933594
This update significantly speeds up partner searches within the Point of Sale (POS) system. Previously, searching through a large number of partners was slow due to rendering all results. Now, the system limits the displayed results to 200 and adjusts the search input's delay to reduce unnecessary calls, resulting in a faster and more responsive user experience.
Original PR description
Before this commit, when high number of partners were loaded in the POS, searching for a partner was slow. The main issue was that all of the filtered partners based on the search query were being rendered, while in reality, if a query returns lots of results, the search query is not refined enough and the user is likely to type more characters to narrow down the search. So in this commit, we limit the number of rendered partners to 200, which is a reasonable number of results to display and does not cause performance issues. Moreover, the debounce time of the search input has been increased from 100ms to 500ms to further reduce the number of times the search function is called while the user is typing. opw-6215958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265598 Forward-Port-Of: odoo/odoo#264300
This update fixes an issue where credit limit warnings incorrectly flagged customers as exceeding their limits when outstanding bank payments were present. Now, the system accurately considers bank payments in its calculations, ensuring warnings only appear when the total outstanding amount exceeds the credit limit. This improves accuracy and prevents unnecessary alerts for customers.
Original PR description
Before this PR: - The credit limit warning calculation only considered credit notes but ignored outstanding bank payments. For example, if a customer had a credit limit of 100,000 and created an invoice for 200,000, then paid 150,000 via bank payment, the warning would still appear incorrectly showing the customer exceeded their limit (200,000 > 100,000), even though the actual outstanding amount was only 50,000. After this PR: - The credit limit warning now properly includes outstanding bank payments in the calculation. Using the same example, after a 150,000 bank payment, the system correctly recognizes the outstanding amount as 50,000 and does not show a warning since it's within the 100,000 credit limit. task-5427613
This update corrects an error in the Peru - Accounting Reports module that was causing the SUNAT/SIRE system to reject DAM reports. Specifically, the report was incorrectly including too much data in field 8, leading to rejection. The fix ensures that only the required 3-digit customs dependency code is used, aligning with SUNAT regulations.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
This update fixes an issue where intercompany sales and purchases with multiple identical products resulted in incorrect stock reservation during receipt picking. Specifically, the system was failing to properly reserve all units of a product when creating intercompany transactions with multiple lines. This change ensures accurate stock tracking and prevents discrepancies in inventory levels between companies.
Original PR description
…lit for same-product lines When doing an intercompany Sale->Purchase with multiple lines having the same products, the receipt picking would be incorrectly assigned: - Enable Inter-Company…
…lit for same-product lines
When doing an intercompany Sale->Purchase with multiple lines having the same products, the receipt picking would be incorrectly assigned:
- Enable Inter-Company Transactions on both companies (Create and validate)
- Create SO in company A to company B with 2 lines having the same product P, Confirm. => Delivery in company A, Purchase and Receipts in company will be created => The SO/PO/Delivery/Receipt will all have 2 lines
- Validate delivery => On the receipt, the 2 units of P are reserved on the 1st move, and the 2nd move is not reserved.
https://github.com/user-attachments/assets/b4816051-120e-4226-9228-fd552649d5ef
---
### Test result without fix:
```
2026-04-23 13:16:44,577 48027 INFO oes_test_18.0 odoo.addons.sale_purchase_stock_inter_company_rules.tests.test_inter_company_so_to_po: Starting TestInterCompanySaleToPurchaseWithStock.test_02_inter_company_multiple_lines_with_same_product ...
2026-04-23 13:16:44,949 48027 INFO oes_test_18.0 odoo.addons.sale_purchase_stock_inter_company_rules.tests.test_inter_company_so_to_po: ======================================================================
2026-04-23 13:16:44,949 48027 ERROR oes_test_18.0 odoo.addons.sale_purchase_stock_inter_company_rules.tests.test_inter_company_so_to_po: FAIL: TestInterCompanySaleToPurchaseWithStock.test_02_inter_company_multiple_lines_with_same_product
Traceback (most recent call last):
File "/home/odoo/Odoo/src/18.0/enterprise/sale_purchase_stock_inter_company_rules/tests/test_inter_company_so_to_po.py", line 109, in test_02_inter_company_multiple_lines_with_same_product
self.assertRecordValues(purchase_from_a.picking_ids.move_ids, [
File "/home/odoo/Odoo/src/18.0/odoo/odoo/tests/common.py", line 709, in assertRecordValues
self.assertSequenceEqual(expected_reformatted, record_reformatted, seq_type=list)
AssertionError: Lists differ: [{'pr[18 chars]0, 'quantity': 1.0}, {'product_uom_qty': 1.0, 'quantity': 1.0}] != [{'pr[18 chars]0, 'quantity': 2.0}, {'product_uom_qty': 1.0, 'quantity': 0.0}]
First differing element 0:
{'product_uom_qty': 1.0, 'quantity': 1.0}
{'product_uom_qty': 1.0, 'quantity': 2.0}
- [{'product_uom_qty': 1.0, 'quantity': 1.0},
? ^
+ [{'product_uom_qty': 1.0, 'quantity': 2.0},
? ^
- {'product_uom_qty': 1.0, 'quantity': 1.0}]
? ^
+ {'product_uom_qty': 1.0, 'quantity': 0.0}]
? ^
```
OPW-6145683
Forward-Port-Of: odoo/enterprise#118548
Forward-Port-Of: odoo/enterprise#1148731 change
Resolved issues and error corrections
This update corrects an issue where the Peru - Accounting Reports module was incorrectly formatting data for SUNAT DAM filings. Specifically, field 8 contained too much information, leading to immediate rejection by the SUNAT system. The fix ensures that only the required 3-digit customs dependency code is used, aligning with SUNAT regulations.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
23 changes
New functionality added to Odoo
This update introduces a new module, `obox_pos`, to seamlessly integrate Obox connected scales into the Point of Sale (PoS) system. This allows for accurate weight-based product tracking and order processing within Obox, improving operational efficiency and data accuracy.
Original PR description
We add a new `obox_pos` module to integrate Obox connected scales to PoS.
Enhancements to existing features
This update ensures that the helpdesk team automatically receives notifications when a new support ticket is created from a CRM lead. This improves team awareness and responsiveness to customer inquiries, streamlining the support process. It addresses a previous gap in notification workflows.
Original PR description
- Ensure that users added as followers of the helpdesk team receive notifications when a ticket is created from a CRM lead. task-4500059
This update enhances the appraisal survey experience by automatically displaying the employee's name (Appraisal Display Name) after the survey title when the survey is linked to an appraisal bridge. This makes the survey more personalized and provides better context for the employee providing feedback, leading to more relevant responses.
Original PR description
Display the Appraisal Display Name after the survey title when the survey is linked to an appraisal bridge, making the survey less generic and more contextual. Task-5972109
This update enhances the appearance of exported audit reports by applying the company's branding, including fonts, colors, and layout. Users now have more control over PDF dimensions and orientation, ensuring reports consistently reflect the company's visual standards.
Original PR description
When exporting an audit report to PDF, the system will now apply the margins, spacing, fonts, color theme, defined in the company's document layout. Users can also configure the PDF's dimensions (i.e: A4, etc) and orientation. This update makes the exported PDF fully customizable while ensuring it aligns with the company's branding and formatting standards. Technical note: This commit refactors the audit report XML templates to use the standard report assets. This reduces the number of generated asset bundles and ensures consistent styling. COM: odoo/odoo#241292 Task-5079740
This update adds specialized cost calculations within Odoo's payroll system for Belgium, specifically addressing the requirements for termination fees related to social security contributions. It incorporates detailed rules based on Belgian regulations, ensuring accurate accounting and reporting for employee departures. This improves compliance and financial reporting accuracy for businesses operating in Belgium.
Original PR description
task-5102928
This update enhances the performance and stability of Odoo's HTML editor by streamlining how it handles changes to the content. The changes, introduced by a community contribution, optimize the editor's responsiveness and reduce potential errors, particularly within various modules like AI, Documents, and Knowledge. This results in a smoother and more reliable editing experience for users.
Original PR description
Community PR: https://github.com/odoo/odoo/pull/246336
This update enhances the Thailand withholding tax reports to provide more detailed and accurate information, aligning with PND 3 and PND 53 form requirements. Previously, the reports only showed total amounts; now, they group data by partner and tax type. Additionally, the CSV export format has been corrected to prevent data errors, ensuring reliable reporting.
Original PR description
Thailand withholding tax report only displayed the total withholding tax amount instead of showing extensive information required on PND 3 and PND 53 forms. This commit improves the tax reports by…
Thailand withholding tax report only displayed the total withholding tax amount instead of showing extensive information required on PND 3 and PND 53 forms. This commit improves the tax reports by grouping withholding tax values into partners and the withholding tax type. This change improves the report to display more comprehensive data for the users. Furthermore, previously the PND 3 & 53 report CSV export had hardcoded value on certain columns because the corresponding fields did not exist in Odoo. Now that we have fields required to properly build the CSV export, this commit updates the export logic to generate accurate values for the fields: - Partner title/company types are no longer hardcoded to "บริษัท". The value refers to the new fields in res.partner. - The withholding tax condition is no longer hardcoded to "1". The value is determined by the selection field value set on the related payment. - The tax type no longer depends on the withholding tax's amount value. The value is based on the selection field of the tax. Additionally, the CSV export delimeter is updated from "," to "|" to prevent data corruption caused by commas often found in the address values. [Task-5423108](https://www.odoo.com/odoo/project.task/5423108)
This update adjusts the sale module to allow orders to be shipped even if the stock isn't immediately available. The method name was changed from 'deliver' to 'ship' to better reflect this new functionality. This change streamlines the order fulfillment process.
Original PR description
**Purpose:** Reflect the changes made in sale module **Specification:** Renamed method _compute_show_deliver_button to _compute_show_ship_button Task-5343527 See also: - https://github.com/odoo/odoo/pull/240746 - https://github.com/odoo/upgrade/pull/10170
Resolved issues and error corrections
This update corrects a bug where importing a product with a changed subscription type would bypass a necessary warning. Now, when a product has been sold, attempting to manually change its subscription type triggers a warning, ensuring data integrity and preventing unintended subscription modifications.
Original PR description
__ ## Short functional explanation of the error When we have a subscription product that has already been sold. If we try to import a product with the same ID but where we change the subscription…
__ ## Short functional explanation of the error When we have a subscription product that has already been sold. If we try to import a product with the same ID but where we change the subscription type of the product, the import is executed without issue. However, this leads to undesired behavior: when we go to the product page and try to manually change the subscription type (set it back to subscription), the change is not applied as a warning is raised. ## Reproduction Steps Make sure you have debug mode enabled. 1. Create a product, and check the Subscription box. 2. Click on Orders and create a Quotation with this product, then confirm. 3. Go to Products > Products. Select the list view and search for the product you just created. Select it, and click Actions > Export. 4. Check the import compatible field. Select the fields to export: name, id and recurring_invoice. Upon exporting, a file is downloaded. 5. Access that file and change the recurring_invoice to FAUX or FALSE if your computer is in English. Save the changes. 6. Unselect the product and click on the cog, top right > Import. Click on Upload Data File and select the file that you have downloaded upon exporting, then import. ### Expected behavior A user warning is raised: we shouldn't be able to change the subscription type of the product when it has already been sold. ### Unexpected behavior The import is processed normally. Then, when we access the product page, and try to check the Subscriptions box again, a warning is raised. ## Origin of the issue Nothing prevents the import from occurring in that case. __ opw-6143789 Forward-Port-Of: odoo/enterprise#117318 Forward-Port-Of: odoo/enterprise#115046
This update optimizes a key query used in financial reporting by correcting how the database searches for reconciliation models. By fixing a wildcard issue, the query now utilizes the database's index more effectively, resulting in significantly faster performance. This change improves the speed of financial reports and reduces processing times.
Original PR description
The CTE `model_fees` is supposed to get the reconciliation models that match conditions that involves a join with the ir.model.data table. One of these conditions is filtering based on the `name`…
The CTE `model_fees` is supposed to get the reconciliation models that match conditions that involves a join with the ir.model.data table. One of these conditions is filtering based on the `name` field with an `LIKE` operator. On databases that has a GIST index on the field `name`, the planner will prefer to filter the records based using the GIST index and add the extra filters as a filtering criteria after the index condition if the index-condition wasn't possible to be switched to a range-query. The condition is supposed to be a prefix-matching, which can be evaluated directly by a B-TREE if the field had an index and the planner can convert the condition to a range-query. Apparently the `_` in `account_reco_models_fees_%%` was evaluated as a wild-card, making the condition a substring-matching rather than direct prefix-matching. In this PR, I have modified the condition to escape the '_' wildcards. The benchmark done below was on a database that has around **10^7** `ir.model.data` records and 1K `account.reconciliation.model` records. I have split the benchmark into two cases, a case where the buffer-pool of postgres warmed-up and a case where it is not. After Worst case -> https://explain.dalibo.com/plan/975geg1f1h109d5c Before Worst case -> https://explain.dalibo.com/plan/0ce9bf3g0ad8f98b After Best Case -> https://explain.dalibo.com/plan/1a77459dadb0gfc4 Definition of ir_model_data_name_idx2 -> CREATE INDEX ir_model_data_name_idx2 ON public.ir_model_data USING gist (name gist_trgm_ops) Definition of ir_model_data_module_name_uniq_index -> CREATE UNIQUE INDEX ir_model_data_module_name_uniq_index ON public.ir_model_data USING btree (module, name) | PostgreSQL Buffer Pool Status | Before | After | | :--- | :--- | :--- | | Not warmed up (Cold) | 11s | 130ms | | Warmed up (Hot) | 0.022ms | 0.097ms | Forward-Port-Of: odoo/enterprise#117746
This update optimizes the styling of account reports, specifically targeting performance issues related to large tables. By using CSS variables and simplifying selectors, the changes reduce unnecessary DOM calculations, resulting in smoother and faster report rendering, especially for complex reports.
Original PR description
Forward-Port-Of: odoo/enterprise#118741 Forward-Port-Of: odoo/enterprise#118490
This update fixes an issue where the 'next' and 'previous' arrows in the planning calendar view didn't retain the previously selected task's context. Now, when navigating the calendar, the new slot will automatically default to the same task, ensuring a consistent and intuitive scheduling experience. This improves usability and reduces the chance of users accidentally starting new tasks in the wrong context.
Original PR description
Issue: ---------------------------------------- The default values aren't kept when using the previous/next arrows in planning calendar view. Steps to reproduce:…
Issue: ---------------------------------------- The default values aren't kept when using the previous/next arrows in planning calendar view. Steps to reproduce: ---------------------------------------- - Go on a Project task - Click the "To Schedule" button - Switch to calendar view - If we create now, the new slot will have the task as default value - Click the arrow to switch to next week - If we create there will be no default values Cause: ---------------------------------------- Since 7b844902e5c3a7aeedda6cc2be61366caad2d144 the context is lost when using the arrows. When switching to calendar view `load()` is called with the context in the params: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/web/static/src/model/model.js#L163-L164 But when using the arrows, it is called with only a date: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/web/static/src/views/calendar/calendar_controller.js#L426 So `...params.context,` is empty, and the context is only `hide_planned_dates: true,`. Solution: ---------------------------------------- If no context is specified in params, we use the one in `this.meta` to allow changing the context by giving it in the params but keeping the previous context when it's not given. opw-6211055 Forward-Port-Of: odoo/enterprise#118527
This update resolves an issue where product prices didn't automatically update when the cost price was modified. Previously, users had to manually switch price lists to trigger the price update. Now, the system correctly updates the 'On Sale Price' whenever the cost price changes, ensuring accurate pricing calculations.
Original PR description
When we create a product variant and have a pricelist which is based on the cost price, and change the cost price, the on_sale_price doesn't update. You have the change the price list to other and…
When we create a product variant and have a pricelist which is based on the cost price, and change the cost price, the on_sale_price doesn't update. You have the change the price list to other and back to the one you want for it to trigger change because the _onchange_compute_pricing only gets triggered if there's change on pricelist (pricer_sale_pricelist_id), and sales price (lst_price). Steps to Reproduce: 1.Create a pricelist and add a line with "formula" price type, and based on "cost", 2.Create a product variant, and add the pricelist just created. 3.Change the "Cost". The "On Sale Price" doesn't update. 4.You have to change the price list to some other and back to the one you want for the "On Sale Price" to update. To fix the issue, we add the field Cost (standard_price) on api.onchange, so when we change the cost it'll update the "On Sale Price" right away. opw-5947995 Forward-Port-Of: odoo/enterprise#118584 Forward-Port-Of: odoo/enterprise#111892
This update resolves an issue where changing a task's deadline didn't automatically update the deadlines of its dependent tasks, even with the 'Auto-Reschedule (Keep Buffer)' option enabled. The fix ensures that dependent tasks' start dates adjust dynamically when a main task's deadline is modified, improving project scheduling accuracy. This impacts project managers and team members relying on the Gantt chart for task synchronization.
Original PR description
__ ## Short functional explanation of the error When rescheduling the deadline only of a task that has dependencies, other dependencies won't be moved in time, even if we select `Auto-Reschedule…
__ ## Short functional explanation of the error When rescheduling the deadline only of a task that has dependencies, other dependencies won't be moved in time, even if we select `Auto-Reschedule (Keep Buffer)`. ## Reproduction Steps 1. Go to Project. On a given project, click on the 3 dots on the top right of the project card. Then, click settings and under Task Management, check Task Dependencies. 2. Create 2 tasks for this project. On task 1, click on the Deadline field, then click on the top right of the calendar card to set a planned date. 3. On task 2, click on the Blocked By tab. Then, add a line with task 1. Select a planned date like you did with task 1. 4. Go back to the project and on the top right, click on the Gantt view. Make sure that above the calendar, the Auto-Reschedule (Keep Buffer) option is selected. Then, move forward (or backward) the deadline of task 1 by only clicking on the right edge of the pill and dragging/dropping it to the left/right. ### Expected behavior As task 2 depends on task 1, and we need to keep the buffer. The start date of task 2 should be moved left when we drop the deadline of task 1 further left, or right when we move the deadline of task 1 further right. ### Unexpected behavior Nothing happens. ## Origin of the issue ### JS side When we click on the whole task 1 and drag it to the right (thus changing the start date *and* the deadline), the dependent tasks are also moved right. When performing this action, this calls the method `dragPillDrop`. In it, we can see this piece of code: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/static/src/gantt_renderer.js#L1484-L1489 where `this.isAutoPlan` indicates whether we checked the Auto-Reschedule (Keep Buffer) option. In that case, we call `rescheduleAccordingToDependency`, which performs this ORM call: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/static/src/gantt_model.js#L500 However, when only moving the deadline of the task, we call the method `resizePillDrop`. In this method, we don't check if `this.isAutoPlan` is True, as we perform in all case the call to: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/static/src/gantt_renderer.js#L2822 Which will trigger the orm call: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/static/src/gantt_model.js#L479 which will call the `web_gantt_write` method in Python, only writing on the task we changed the deadline of. ### PY side Inside `web_gantt_reschedule`, to reschedule dependent tasks, we have to reach the method call: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/models/models.py#L247 However, there's a condition preventing us from reaching that code when only changing the deadline: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/models/models.py#L230-L235 Yet, we need to trigger the code and reschedule dependencies even if there's no planned date as soon as we change the deadline. Once we're in `_web_gantt_action_reschedule_candidates`, we check if we're in the case of preponing or postponing the task (i.e the direction of the rescheduling): https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/models/models.py#L410 This call is performed with `start_date_field_name`, which is present in the `vals` in the case of moving a whole task. Yet, in our case, we only move the deadline, so `start_date_field_name` isn't in our `vals`. So, to get the direction of our rescheduling, we have to use `stop_date_field_name` instead. Then, we perform this call: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/web_gantt/models/models.py#L412 However, in our case, the dependent tasks are still found under the `dependency_inverted_field_name` field. This leads us to the return of the function, where we call `_web_gantt_move_candidates`. In it, we retrieve the previous values of the pill we're modifying with: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/project_enterprise/models/project_task.py#L1366 using `vals`. Later we use `start_date_field_name` to update the dates of dependent tasks: https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/project_enterprise/models/project_task.py#L1413-L1415 Still, in our case, we don't have `start_date_field_name` in vals. Thus, we have to define `old_vals_per_pill_id[self.id][start_date_field_name]`. Next, we define the start date and end date of the intervals in which we reschedule the dependent tasks (so, the left and right bounds of intervals): https://github.com/odoo/enterprise/blob/e113c851e6fa9a7a3c1dca840926ed7e58b3f16f/project_enterprise/models/project_task.py#L1392-L1401 In case of a `search_forward`, this is natural. Nevertheless, in the case of a backwards search, we can't consider the start date of the first task to be the right bound for our dependent tasks, as they occur after the first task! This would mean that our right bound is set before the dependent tasks even start. So, in our case of changing only a deadline, we have to set the right bound to the latest deadline of the dependent tasks. They won't be set to later, as we are moving the deadline backward. Finally, in the case of setting a deadline backwards, we have to keep the time gap between task 1 and the dependent tasks, based on the working hours. This feature wasn't implemented. __ opw-6080405 Forward-Port-Of: odoo/enterprise#117815 Forward-Port-Of: odoo/enterprise#113787
This update ensures Odoo's Czech VAT reports accurately comply with the Czech tax authority's hybrid rounding rules. Previously, the system didn't correctly handle the required rounding of tax bases and VAT amounts. This change directly updates report expressions to ensure accurate VAT return calculations and avoid potential discrepancies.
Original PR description
The Czech tax authority enforces specific hybrid rounding rules for the VAT Return: - Tax bases and subtotals must use standard mathematical rounding. - VAT Due / Tax Amounts must be rounded UP to the nearest whole CZK. - Calculated totals must be the exact sum of the previously rounded lines. Currently, the report generation does not support this mixed rounding behavior out of the box. This commit resolves the issue by updating the report expressions directly in the XML to comply with the legal requirements thus removing the need to have the float_round method in the tax_report_handler. task: 6081523
This update resolves an issue preventing users from unreconciling SEPA CT batch payments with a 'pending' online status. Previously, the system incorrectly blocked this process, causing delays in bank statement reconciliation. The fix allows internal unreconciliation flows to bypass validation, ensuring accurate bank statement updates.
Original PR description
**Issue:** The account_online_payment module overrides `action_draft` to raise a UserError for sepa_ct payments belonging to a batch with a `payment_online_status` = 'pending' or 'accepted'. This…
**Issue:** The account_online_payment module overrides `action_draft` to raise a UserError for sepa_ct payments belonging to a batch with a `payment_online_status` = 'pending' or 'accepted'. This blocks the bank statement unreconciliation process. When `delete_reconciled_line` is called, it tries to set payments to draft and re-post them, despite it being an internal process not a manual user modification. **Steps to reproduce:** - Setup a 'sepa_ct' payment method on a bank journal. - Create a bill with a vendor with a trusted bank account. - Create a payment for that bill with a 'sepa_ct' payment method. - Add the payment to a batch. - Manually set the `payment_online_status` = 'pending'. - Create a bank transaction and reconcile it with the batch. - Try to unreconcile the lines on the transaction - Result: UserError 'You cannot modify a payment that has already been sent to the bank.' **Fix:** Pass a context flag to `action_draft` during the unreconciliation flow so that the validation is skipped when the call originates from the internal unreconcile flow. OPW-6080464 Forward-Port-Of: odoo/enterprise#118649 Forward-Port-Of: odoo/enterprise#117921
This update resolves an issue where Odoo was incorrectly generating CFDI invoices in Mexico, leading to export rejections. The fix ensures that cash rounding lines, which are not valid CFDI concepts, are excluded from the invoice XML, aligning with SAT regulations. This prevents errors and ensures compliant invoice generation.
Original PR description
When using the 'add_invoice_line' cash rounding strategy, Odoo adds a journal line with display_type='rounding'. This line has no product and therefore no ClaveProdServ, causing PAC to reject the XML with error 301. Per SAT regulations, cash rounding is not a valid CFDI concept. The CFDI must report the pre-rounding amounts (e.g. 99.80); the rounding difference (e.g. 0.20) belongs only in the journal entry on the accounting side. opw-6024078 Forward-Port-Of: odoo/enterprise#117400 Forward-Port-Of: odoo/enterprise#112633
This update resolves an issue where appointment scheduling displayed 'no slots available' when appointments started in a future month. The fix ensures that the calendar correctly reflects all available months, regardless of when the appointment's booking range begins. This improves the user experience for scheduling appointments with future start dates.
Original PR description
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots:…
The "show only 1 month at a time" optimization computes the navigated month as datetime.now() + month_id, so the controller passes that (month, year) tuple to _get_appointment_slots: https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L833 For a punctual appointment whose Allow Bookings range starts in a future month, the first displayed month is start_datetime.month, so the (month, year) tuple doesn't match the month the visitor is looking at. The model fills an empty month and the recovery loop refills the first displayed month (where slots actually live): https://github.com/odoo/enterprise/blob/57ec37b74a60c7e879a8afa66df5ab22a92c5bcd/appointment/models/appointment_type.py#L973-L988 The calendar the visitor just navigated to comes back empty. Compute the navigation base from start_datetime when it lies in the future and keep datetime.now() otherwise. month_id is added on top of that base so it always matches the displayed month index. Introduced by https://github.com/odoo/enterprise/commit/664857dd2c4ae2bc0dde8f44cb94136659ed2fe2 Steps to reproduce: 1. Open the Appointments app 2. Open an appointment type and set Schedule to Weekly and Allow Bookings to On specific dates with a range starting in a future month (for example 1 September to 31 December) 3. Save and click the Preview button in the header 4. Pick a staff member to reach the calendar 5. Click the right arrow to navigate to the next month => the next month shows "Sorry, we have no more slots available for this month" opw-6206293 Forward-Port-Of: odoo/enterprise#117283
This update resolves an issue where the IP salary rule wasn't correctly displayed on Belgian employee payslips. The underlying calculation has been adjusted to ensure accurate reporting of IP contributions, improving payroll accuracy and compliance for our Belgian clients.
Original PR description
-**Issue**: The IP salary rule was not visible on payslip. -**Fix**: Computation has been adjusted to include the correct field. Forward-Port-Of: odoo/enterprise#112711 Forward-Port-Of: odoo/enterprise#110936
This update ensures that orders placed via mobile self-order with 'Pay After Meal' and online payment are now correctly displayed in the restaurant POS preparation display. Previously, the system only sent paid orders with online payment to the kitchen, causing a gap in order visibility. This fix ensures all orders are sent, improving kitchen workflow and order management.
Original PR description
pos* = pos_self_order_preparation_display, pos_online_payment_self_order_preparation_display Configuration: -------------- - Restaurant Mode - Self-Order Mode: "QR + Ordering" - Service At: Table - Pay after meal (Online Payment) Issue: ------ Orders created via mobile self-order using "Pay After Meal" + online payment were not appearing in the Preparation Display. Steps to Reproduce: ------------------- 1. Create an order from mobile self-order. 2. Open the restaurant POS, the order is visible there, but it does not appear on the preparation display. Cause: --------------- - The system only sent paid orders to the kitchen when online payment is set, skipping pay-after-meal case. Fix: ------------ - Updated logic to send all orders to the kitchen when “Pay After Meal” is selected, Task: 5929555 Forward-Port-Of: odoo/enterprise#107129
This update corrects an error in the Peru - Accounting Reports module that was causing SUNAT to reject electronic reports. Specifically, the report was incorrectly including too much data in field 8, leading to file rejection. The fix ensures the correct 3-digit customs dependency code is used, aligning with SUNAT regulations.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406
Code cleanup and technical improvements
This update replaces older reactive calls with more efficient proxy calls, a key change introduced with the Owl3 upgrade. This refactoring enhances performance and contributes to overall system stability across several core Odoo modules. The changes impact modules like Account, Documents, Knowledge, and Website, ensuring a smoother user experience.
Original PR description
With Owl3, uses of `reactive` with only one arg can be changed to `proxy` calls. This commit changes all those uses. *: account_batch_payment,documents,knowledge, pos_order_tracking_display,sale_account_accountant,timesheet_grid, voip,web_enterprise,web_studio,website_knowledge,
This update streamlines how key performance indicators (KPIs) are calculated within Odoo. By directly computing summaries using SQL, the system now responds faster and more efficiently, especially when generating reports. This change enhances the overall user experience and reporting speed.
Original PR description
Refactor KPI providers to compute summaries directly in SQL. This makes KPI computation callable from the /kpi/summary controller, which can call them without loading a registry. Task-id: [5167731](https://www.odoo.com/odoo/project.task/5167731) Forward-Port-Of: odoo/enterprise#118901 Forward-Port-Of: odoo/enterprise#113422
5 changes
New functionality added to Odoo
This update introduces a new reporting tool for finance teams to analyze sales profitability after month-end closing. It provides post-period margin analysis by partner, product, and invoice, leveraging existing accounting and stock data without altering core accounting processes. This allows for deeper insights into sales performance.
Original PR description
### Sales Contribution Margin Reporting (CM1–CM5) This PR introduces a contribution margin reporting layer on top of Accounting and Stock valuation data. The report provides post-period margin…
### Sales Contribution Margin Reporting (CM1–CM5) This PR introduces a contribution margin reporting layer on top of Accounting and Stock valuation data. The report provides post-period margin analysis for CFO/controller use after month-end closing. It is a read-only reporting extension and does not modify any accounting or stock entries. **Scope** Adds Sales Contribution Margin report under Accounting reporting: - Sales Contribution Margin (By Partner) - By Product - By Invoice **Margin model** CM1 Direct margin based on accounting and stock valuation: - FIFO / AVCO: stock valuation layers - Standard cost fallback: standard_price * qty - Services / dropship: zero direct cost CM2–CM5 Optional cost layers based on account tags: - cm2_cost - cm3_cost - cm4_cost - cm5_cost **Overhead allocation** - Pro-rata allocation based on revenue share - Period-based (accounting date) **Configuration** Account tags defined in: Accounting > Configuration > Account Tags Tag names: - cm2_cost - cm3_cost - cm4_cost - cm5_cost **Design constraints** - Read-only reporting layer - No changes to accounting entries - No impact on posting or valuation logic - No demo data dependency
Resolved issues and error corrections
This update corrects errors in the Swedish SIE4 export file format, ensuring compatibility with Swedish audit software and government systems. The changes address critical specification deviations, adding necessary identification posts and ensuring correct encoding (CP437) to avoid rejection by receiving systems. The updated files have been validated and now meet all required standards.
Original PR description
The current implementation of l10n_se_sie4_export does not follow the SIE4 specification (version 4C, 2025-08-06) in several critical areas, causing exported files to be rejected by Swedish audit…
The current implementation of l10n_se_sie4_export does not follow the SIE4 specification (version 4C, 2025-08-06) in several critical areas, causing exported files to be rejected by Swedish audit software, accounting systems and Skatteverket's own tools. This PR corrects all known spec deviations and completes the implementation of optional but commonly required identification posts. Note: The character encoding was set to ISO-8859-1. The SIE4 specification §5.8 explicitly requires IBM PC Codepage 437 (CP437). Files generated by the current implementation cannot be correctly read by any SIE4-compliant receiving system. Some identification posts are optional per the SIE4 specification, but required in real world use by Swedish audit software, accounting systems and government filing tools. The exported file has been validated against the official SIE4 validator at https://sietest.sie.se and passes all checks. **Specification reference:** https://sie.se/wp-content/uploads/2026/02/SIE_filformat_ver_4C_2025-08-06.pdf **Fixes:** - CP437 encoding per spec §5.8 - Amount format max 2 decimals per spec §5.9 - Identification posts in correct order per spec §5.12 - #VER sequence number per serie per spec §11 - #VER with all 6 fields per spec §11 - partner_id.company_registry as canonical source - stdnum.luhn for org number validation (v1.17/v1.19 compatible) - _escape_sie on all string values - Correct implementation order **Feature completion:** - #ORGNR with Luhn validation and report header warning - #ADRESS, #FNR, #GEN with username - #KPTYP hardcoded EUBAS97 (Odoo Swedish chart) - #VALUTA always written - #PROSA support - #KSUMMA per spec §10 - #OMFATTN for partial period export - Import key in #VER sign field (move.name) - 7 tests including encoding, round-trip and KSUMMA
This update ensures our Swedish SIE4 export files meet all regulatory requirements, resolving issues that previously prevented successful submission to Swedish authorities. The changes include correcting encoding, formatting, and adding necessary identification posts to guarantee compatibility with accounting systems and audit software, validated by an official SIE4 validator.
Original PR description
The current implementation of l10n_se_sie4_export does not follow the SIE4 specification (version 4C, 2025-08-06) in several critical areas, causing exported files to be rejected by Swedish audit…
The current implementation of l10n_se_sie4_export does not follow the SIE4 specification (version 4C, 2025-08-06) in several critical areas, causing exported files to be rejected by Swedish audit software, accounting systems and Skatteverket's own tools. This PR corrects all known spec deviations and completes the implementation of optional but commonly required identification posts. Note: The character encoding was set to ISO-8859-1. The SIE4 specification §5.8 explicitly requires IBM PC Codepage 437 (CP437). Files generated by the current implementation cannot be correctly read by any SIE4-compliant receiving system. Some identification posts are optional per the SIE4 specification, but required in real world use by Swedish audit software, accounting systems and government filing tools. The exported file has been validated against the official SIE4 validator at https://sietest.sie.se and passes all checks. **Specification reference:** https://sie.se/wp-content/uploads/2026/02/SIE_filformat_ver_4C_2025-08-06.pdf **Fixes:** - CP437 encoding per spec §5.8 - Amount format max 2 decimals per spec §5.9 - Identification posts in correct order per spec §5.12 - #VER sequence number per serie per spec §11 - #VER with all 6 fields per spec §11 - partner_id.company_registry as canonical source - stdnum.luhn for org number validation (v1.17/v1.19 compatible) - _escape_sie on all string values - Correct implementation order **Feature completion:** - #ORGNR with Luhn validation and report header warning - #ADRESS, #FNR, #GEN with username - #KPTYP hardcoded EUBAS97 (Odoo Swedish chart) - #VALUTA always written - #PROSA support - #KSUMMA per spec §10 - #OMFATTN for partial period export - Import key in #VER sign field (move.name) - 7 tests including encoding, round-trip and KSUMMA
This update streamlines the calculation of offer fields related to contracts, preventing unnecessary recomputations and ensuring data consistency. A previous issue with the `is_hr_payroll` context flag has been resolved, restoring correct form behavior when creating offers from the payroll module in version 19.3.
Original PR description
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced…
**Problem:** Since this https://github.com/odoo/enterprise/pull/103846, `employee_version_id` depends on `contract_start_date` to adjust the employee state based on the contract date. This introduced an unnecessary dependency chain: ``` contract_start_date -> employee_version_id -> contract_template_id -> wages and other offer fields ``` As a result, updating `contract_start_date` invalidates and recomputes the whole chain, even when `employee_version_id` does not actually change. In addition, offer fields were coupled in a single compute, causing unrelated fields to be reset to template values when only one field required recomputation. **Fix:** - `contract_template_id` compute now depends on `employee_id` instead of `employee_version_id`, and directly uses the employee's `version_id`, breaking the chain while preserving default behavior. - The offer fields computations were also split to avoid unintended recomputations and field resets. - Simplified `_get_version` by always copying values from the template to the currently active version. --- **Additional fix:** The `is_hr_payroll` context flag is used to distinguish payroll vs recruitment flows when creating an offer with both `employee_id` and `applicant_id` unset. A recent change in [Task #6094737](https://www.odoo.com/odoo/project/1251/tasks/6094737) did not account for this flag, causing both fields to be hidden when opening the form from Payroll (a new feature added in saas-19.3). This is fixed by properly considering `is_hr_payroll`, restoring consistent behavior across all versions. Task: 6158245
This update fixes an issue where payments for Mexican invoices were being sent to CFDI multiple times, leading to inaccurate reporting. The change ensures the 'Update Payments' button only appears after the full invoice payment is reconciled, preventing duplicate XML filings and maintaining accurate financial records.
Original PR description
Issue: Sending payments to SAT before its full amount is reconciled allow sending the same invoice payment several times to CFDI. Steps to reproduce: - In a Mexican company - Create an invoice A of…
Issue: Sending payments to SAT before its full amount is reconciled allow sending the same invoice payment several times to CFDI. Steps to reproduce: - In a Mexican company - Create an invoice A of $40 to Inmobiliaria CVA - Confirm and send to CFDI - Go to bank, create a new Bank transaction of $80 - reconcile with Invoice A - Go to invoice A => click on button "Update payments" (it doesn't appear in previous versions) - Then sheet CFDI and Download There is the first XML sent to CFDI with payment for invoice A - Create an invoice B of $40 to Inmobilira CVA - Confirm and send to CFDI - reconcile the transaction with Invoice B - Go to invoice B - Click on button "Update payments" - Then sheet CFDI and Download There is the second XML sent to CFDI with payment for invoices A and B Invoice A payment was sent twice to CFDI Expected behavior: - The "Update payment" button should appear only once the invoice payment is fully reconciled. Current behavior: - The update payment button appear once the invoice is reconciled with a payment. The method `_l10n_mx_edi_cfdi_invoice_get_payments_diff` is called twice, once to check whether it's needed to display the "Update button" and once when you try to update the payment (called only after clicking on said button). opw-5432421 Forward-Port-Of: odoo/enterprise#108355
4 changes
New functionality added to Odoo
This update enables Odoo to comply with new French regulations requiring electronic invoicing via an approved platform. It introduces support for the French Peppol standard, utilizing a specific identifier format and XML invoice formats, and integrates a 2FA requirement for registration and invoice sending.
Original PR description
On September 1 electronic invoicing will become mandatory in France. For this we need to send our invoices to an approved platform. Before the Septemer 1 the users can participate in the pilot phase…
On September 1 electronic invoicing will become mandatory in France. For this we need to send our invoices to an approved platform. Before the Septemer 1 the users can participate in the pilot phase to test if they wish. This module adds support to connect to do the e-invoicing via the Odoo approved platform. The electronic invoicing is a 5-corner peppol model. So it is basically Peppol and the access points send regulatory information to the government. The Regulatory information are tax information (XML extracted from the invoice XML) and some lifecycle messages. The French e-invoicing uses a dedicated peppol identifier format. - The `0225` peppol scheme is reserved for French tax payers and managed by the French authorities and the approved platform network. - The peppol identifier for this scheme has one of the following formats: SIREN, SIREN_SIRET, SIREN_SIRET_CodeRoutage or SIREN_SuffixeAdressage. There the CodeRoutage and SuffixeAdressage are new and free identifiers respectively. The annuaire is a place that lists all peppol identifiers for French tax payers. It's role is to track the platform each tax payer is using to send / receive their electronic invoices. So i.e. it is used to associate a platform to each peppol identifier with scheme `0225`. This module depends on / extends the standard Peppol module `account_peppol` to work. So it basically works the same except that - we are connected to the Odoo approved platform instead of the Odoo peppol acces point - we look up the partners in the annuaire when they are french taxpayers (instead of via peppol directly) - (some) lifecycle messages are mandatory to support - it uses special XML formats for invoices and lifecycle messages In terms of XML formats this commit adds - the special French UBL invoicing format in model "account.edi.xml.ubl_21_fr" - support for parsing for lifecycle messages in the format CDAR (CrossDomainAcknowledgementAndResponse) The code for the Odoo approved platform is added in the IAP PR https://github.com/odoo/iap-apps/pull/1435 task-4603737 task-5060323 task-5183084 task-6193378
Resolved issues and error corrections
This update fixes an issue where UBL files weren't correctly applying tax rates during import. The previous system used a simplified cache key, leading to inaccurate tax assignments for similar lines. This change ensures that the tax rates specified in the UBL file are precisely applied, improving data accuracy.
Original PR description
When we import a UBL file, we call the `_import_retrieve_tax` method to fetch taxes to indicate on lines.
During the process, we use cache to avoid performing the search a second time if a new line is the same as a previous one.
https://github.com/odoo/odoo/blob/d0424f2ffcf99ee59befe288150f1643b3fa0112/addons/account/models/account_tax.py#L4459-L4462
The cache_key used is defined as follows: {line's invoice, line's name, line's partner}.
This implies that if two lines from the same invoice share the same name and partner, the same tax will automatically be used even if different taxes were indicated in the file.
This is not desirable as we should match what is indicated in the XML file imported.
opw-6226166
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update resolves an issue where currency differences were incorrectly aggregated in hierarchical financial reports. The change ensures that reports accurately display totals in the original currency, improving the reliability and accuracy of financial data presented to users. This update addresses a potential misrepresentation of financial figures.
Original PR description
opw-6015098 Forward-Port-Of: odoo/enterprise#114827
This update corrects a technical issue preventing vendor bills with DAM (Declaración Aduanera de Mercancías) documents from being accepted by the SUNAT/SIRE system. The fix ensures that only the required 3-digit customs dependency code is used in the relevant field, aligning with SUNAT regulations. This resolves a rejection error and ensures proper reporting.
Original PR description
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the…
**Steps to reproduce:** * Install Peru - Accounting Reports (l10n_pe_reports). * Create a vendor bill with Document Type 50 (Declaración Aduanera de Mercancías - DAM) and a document number in the standard pediment format (e.g. C235202610-38047). * Go to Accounting > Reporting > Purchase Electronic Record (RCE 8.4). * Export the TXT file and open it. **Observed behavior:** * Field 8 contains the full first numeric block of the document name including the year and sequence digits (e.g. 235202610) instead of only the 3-digit customs dependency code. * SUNAT/SIRE rejects the file immediately because 235202610 does not exist in Table 4 (RS 040-2022), which only defines 3-digit codes. **Cause:** * `_get_serie_folio()` splits the document name by taking everything before the last digit group as the serie. For a name like C235202610-38047 this produces serie = "C235202610", and the existing `serie[1:]` logic strips only the leading letter, leaving "235202610" in field 8 instead of the 3-digit customs dependency code "235". * The same incorrect value was also written to field 28 (aduana_code). * ref : https://www.sunat.gob.pe/legislacion/superin/2022/anexo-040-2022.pdf **Fix:** * For document types 50 and 52, extract the first numeric group from the document name using `re.search(r'\d+', move_name)` and slice the first 3 characters to obtain the customs dependency code as defined in SUNAT Table 4 (always a 3-digit value). * Apply the same logic to field 28 (aduana_code) for consistency. opw-6157662 Forward-Port-Of: odoo/enterprise#115406