Tuesday, March 24, 2026
29 changes · saas-19.2
Enhancements to existing features
This update adjusts the tax settings for Thailand (l10n_th) to align with recent regulatory changes. Specifically, new tax withholding accounts have been created and existing account codes have been updated to ensure accurate tax calculations and reporting. This change impacts financial reporting within the Odoo system for Thai businesses.
Original PR description
Description of the issue/feature this PR addresses: Changed the configurations of the tax 3% WH I COMM and 3% WH I ROY A new account Tax Withheld - PND 2 (213301) is created: - The code of the existing tax withheld accounts are shifted by 1 (e.g., 213301 -> 213302) - The XML ID and the reference to the shifted accounts are also updated 6043714 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update fixes a discrepancy in test data related to tax reporting for foreign customers in Ecuador. The system now correctly identifies company partners ('02' tipoCliente) based on a new internal field, ensuring accurate tax calculations and compliance with Ecuadorian regulations. This change improves the reliability of reports generated for international sales.
Original PR description
Since `tipoCliente` is now determined using the computed `is_company` field, the test data must reflect this logic. `partner_ext` represents a foreign partner and is considered a company, therefore its `tipoCliente` should be set to '02'. See: https://github.com/odoo/enterprise/commit/a779badac35cf4a8f483f490e8ae29eb6bf3d2c5 `l10n_ar_edi`: For foreign partners, AFIP requires the CUIT pais based on the partner’s country and document type, not on partner.is_company. In multi-localization databases, is_company may be influenced by local heuristics and lead to picking the wrong foreign tax identifier. Use the identification type instead: VAT documents map to the legal-entity CUIT pais, while non-VAT documents map to the natural-person one. See: https://github.com/odoo/enterprise/pull/86089#discussion_r2128977870 runbot-241126 Forward-Port-Of: odoo/enterprise#110055
This update fixes a critical issue where signature deadlines weren't updating correctly, leading to outdated task reminders. It also ensures that 'Signature Request' activities are automatically removed when a request is canceled, preventing clutter and improving the user experience. The change includes a safeguard to prevent errors when canceling directly from the activity widget.
Original PR description
1. **Date Sync: mail.activity & sign.request** **Before Fix:** When the validity_date on a sign.request was updated, the linked mail.activity (the "Please Sign" task) did not update its deadline.…
1. **Date Sync: mail.activity & sign.request**
**Before Fix:** When the validity_date on a sign.request was updated, the linked mail.activity (the "Please Sign" task) did not update its deadline. This led to a discrepancy where a document might expire in 2 days, but the user's to-do list still showed a deadline from a week ago.
**Expected Behavior:** The activity deadline should always reflect the current validity of the document to ensure signers are aware of the actual remaining time.
**Fix:** Overrode the write method on sign.request. When the validity_date is modified, the system now automatically updates the date_deadline of all associated records in sign_activity_ids.
2. **Activity Cleanup on Cancel**
**Before Fix:** Canceling a sign.request changed the document state but left "Signature Request" activities sitting in users' to-do lists. This resulted in "orphan" activities that pointed to canceled documents, cluttering the chatter and the activity bin.
**Expected Behavior:** Canceling a request should globally clean up any pending tasks related to that specific request.
**Fix:** Updated the cancel method to unlink associated activities.
**Note on Conflict Prevention:** To avoid a UserError/MissingRecord when canceling directly from the activity widget (where the interface attempts to delete the activity immediately after calling the cancel method), a context flag skip_sign_activity_unlink was introduced. This ensures that if the activity is already handling its own deletion, the backend doesn't "double-delete" it.
Task: 5989542This update corrects a technical issue impacting UK customer top-ups. The system previously relied on outdated data location information, causing processing errors. This change ensures accurate top-up payments for UK accounts by aligning with the current payment structure.
Original PR description
Fix the UK top-up logic as UK accounts payload structure shifts from the EU where the country data is located in the EU payload it could be found under bank_transfer[financial_adresses][0][iban][country] and bank_transfer[country] but in the uk payload it can only be found in the second As we used the first one, we are now switching it to the second as it's the only common ground Forward-Port-Of: odoo/enterprise#111588
This update fixes an issue where linked records were lost when importing spreadsheets from CSV or XLSX files. The change ensures that newly created spreadsheet documents maintain the original linked record, improving data consistency and simplifying workflows. This resolves a bug impacting how spreadsheets are created and linked to other Odoo records.
Original PR description
When importing an XLSX or CSV document into a spreadsheet, the linked record is lost on the newly created spreadsheet document. This happens because the conversion creates a new document through `copy()`, while `res_model` and `res_id` are computed fields and are not copied by default. This commit explicitly forwards the linked record values during the conversion so the created spreadsheet keeps the same linked record as the source document. Task: [6008920](https://www.odoo.com/odoo/project/2328/tasks/6008920) Forward-Port-Of: odoo/enterprise#111532 Forward-Port-Of: odoo/enterprise#110047
This update fixes an issue where salary deductions weren't being accurately calculated for certain types of salaries (like 'ATTACH_SALARY') in the Kenyan payroll system. The changes ensure that these deductions are now correctly applied, leading to more precise net pay calculations for employees. This resolves a previous error impacting payroll accuracy.
Original PR description
**Behavior before this commit** Some salary rules (e.g. `ATTACH_SALARY`) were ignored in the NET calculation. **Behavior after this commit** - Four rules are now added to the "Total deductions" line: their sequence and category has been changed. - The sign of these lines has also been switched: an attachment of salary of a positive amount should be added to the amount of total deductions, which is then deducted from the net.  opw-5894647 Forward-Port-Of: odoo/enterprise#110579 Forward-Port-Of: odoo/enterprise#107033
A recent change has resolved an error that occurred when updating payroll data in the Saudi Arabian company setup. This fix prevents a data mismatch issue that arose when users deleted salary rule categories, ensuring the 'Payroll: Update Data' process runs smoothly. This improves the reliability of payroll processing for Saudi Arabian companies.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is executed. **Steps to Reproduce:** - Install `l10n_sa_hr_payroll` with demo data. - Switch to `Saudi Arabian` company. -…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is executed. **Steps to Reproduce:** - Install `l10n_sa_hr_payroll` with demo data. - Switch to `Saudi Arabian` company. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the Saudi Arabian company. - Go to `Scheduled Actions` and run `"Payroll: Update Data"`. `ValueError: External ID not found in the system: l10n_sa_hr_payroll.l10n_sa_category_provision` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], this causes an error due to the missing rule category [2]. This commit ensures that, when updating the salary rule data, the rule category data is updated beforehand, as shown here [3]. [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1]- https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_sa_hr_payroll/models/hr_payslip.py#L157-L165 [2]: https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_sa_hr_payroll/data/hr_salary_rule_saudi_data.xml#L249 [3]: https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_ke_hr_payroll/models/hr_payslip.py#L9-L18 sentry-7349905716 Forward-Port-Of: odoo/enterprise#111438
This update fixes an issue where DATEV reports generated from Odoo were sometimes inaccurate due to incorrect account assignments. Now, when a move line's account is changed, the DATEV export automatically updates to reflect the new account, preventing duplicate lines in the export. This ensures accurate financial reporting to DATEV.
Original PR description
Description of the issue this commit addresses: When the account of a move line is updated (e.g. replacing the suspense account with the actual one), l10n_de_datev_main_account_id was not recomputed which leads to an incorrect DATEV export with duplicate lines. Desired behavior after this commit is merged: Changing the account_id of a move line recomputes l10n_de_datev_main_account_id so that the exported DATEV data reflects the current accounts of the move. Forward-Port-Of: odoo/enterprise#111493
This update fixes an issue where payroll moves with analytic distribution rules weren't properly anonymized, potentially exposing employee data. The change ensures that payroll moves are correctly aggregated and anonymized, maintaining privacy and compliance. A new test has been added to verify the fix.
Original PR description
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to…
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to enforce privacy and avoid having lines for each employee in the payrun. If salary rules with analytic distributions are involved, though, the lines are not merged and we lose the anonimity.
This happens because in the _get_existing_lines funciton, that should return the lines to be merged with the input line (line), the condition for the rules that have an analytic distribution is wrong.
In particular, the condition is wrong because the
distribution_analytic_account_ids field is a recordset of the accounts, while line_id['analytic_distribution'] is a dictionary with keys that are comma separated strings of the ids of the accounts, with values reflecting the percentage.
For example, if a rule has one analytic distribution for 40% and involving accounts 13,7 and 12 + another analytic distribution for 60% involving accounts 3 and 5, line_id['analytic_distribution'] will be {'13,7,12': 40.0, '3,5': 60.0} while distribution_analytic_etc will be a recordset containing (13,7,12,3,5). To fix the problem and keep everything inline, we extract the logic to a new function, where we first unravel the ids from the keys of the dictionary and only then try to match them to the values in the recordset.
Task: 6043957
Forward-Port-Of: odoo/enterprise#111140This update resolves an issue with the format of Client IDs used in the payroll module, specifically addressing a change in how the 'chaman' expeditor number is represented. This ensures consistent data handling and avoids potential errors during payroll processing. The fix improves the reliability of the system for Belgian payroll calculations.
Original PR description
Forward-Port-Of: odoo/enterprise#111531 Forward-Port-Of: odoo/enterprise#111276
This update resolves issues related to incorrect overtime calculations when employees work across different time zones. Specifically, it ensures that overtime intervals are accurately determined based on the employee's local time, preventing crashes and ensuring correct overtime tracking. This improves the reliability of our HR attendance system.
Original PR description
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a…
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a period, then create two consecutive midnight-to-midnight attendances in the employee's local timezone. Creating the second attendance crashes with: "ValueError: Expected singleton: hr.attendance.overtime.line(...)". Steps to reproduce (stale overtime lines): With the same setup, delete the attendance after it generated overtime lines. The overtime lines remain in the database instead of being removed. The singleton crash occurred because `end_of_day` in `_get_overtime_intervals` was computed as a naive datetime, implicitly treated as UTC. For UTC+ timezones, the actual local end of day is earlier than UTC midnight. As a result, overtime intervals were computed with a stop time extending past the real local midnight into UTC time. When consecutive attendances were processed together, these extended intervals overlapped. The `Intervals` class (`keep_distinct=True`) merges overlapping intervals into a single entry with a multi-record recordset as payload. The subsequent `overtime.rule_ids.work_entry_type_id` and `overtime.status` calls expected a singleton but received a multi-record set, causing the crash. The same multi-record issue also affected the iteration in `_set_real_overtime_intervals` and the overtime work entry loop in `_get_attendance_intervals`. The stale overtime lines issue occurred because `_get_overtimes_to_update_domain` (hr_attendance) built its search date range from raw UTC `.date()` values instead of the employee's local timezone. For UTC+ employees whose attendance spans local midnight, the overtime line is dated in the next local calendar day. Since the domain was derived from UTC dates, that next local day fell outside the search range, so the overtime line was never found and deleted when the attendance was removed. Solution: - In `_get_overtime_intervals`, localize `end_of_day` to the employee's timezone before converting to UTC, so overtime intervals are correctly bounded by the local end of day. - In `_set_real_overtime_intervals` and the overtime loop in `_get_attendance_intervals`, iterate over individual records from potentially multi-record `Intervals` payloads to avoid singleton errors. - In `_get_overtimes_to_update_domain` (hr_attendance), localize check_in/check_out to the employee's timezone before computing the date range so overtime lines for dates that only exist in local time are correctly included in the delete-and-recreate cycle. opw-5931665 Forward-Port-Of: odoo/enterprise#111075 Forward-Port-Of: odoo/enterprise#109419
This update fixes an issue where multi-select rectangles on scaled PDF signature pages were inaccurately drawn, leading to selection problems. Additionally, the update resolves a potential error when dropping elements and ensures helper lines align correctly during dragging, improving the overall signature experience. This enhances the reliability and usability of our digital signature process.
Original PR description
When drawing the multi-select rectangle on scaled PDF pages, the rectangle corner was not properly synchronized with the mouse pointer, leading to inaccurate selection. Additional fixes: - An uncaught error could be triggered when dropping elements on the page. - Helper lines during dragging were not accurately aligned around sign items. task-6049004 Forward-Port-Of: odoo/enterprise#111156
This update fixes an issue where repositioning a signature within the PDF viewer caused erratic resizing behavior. The change ensures only one resize listener is attached per signature, resulting in a more reliable and predictable resizing experience for users. This improves the overall quality and usability of the signature functionality.
Original PR description
Previously, repositioning a sign item inside the PDF iframe would attach multiple resize event listeners. This led to inconsistent and unintuitive resizing behavior. This commit ensures that only a single resize listener is registered per item, avoiding duplicated handlers and restoring stable interaction. task-6048759 Forward-Port-Of: odoo/enterprise#111520 Forward-Port-Of: odoo/enterprise#111146
This update fixes an issue where users weren't receiving email notifications for signature requests, even when they preferred to receive notifications in the Odoo inbox. Now, all signature requests will trigger email notifications, ensuring signers are promptly informed. This change maintains in-app visibility for users who rely on the Odoo interface.
Original PR description
When a user's notification preference is set to "inbox", no email is sent, which may prevent signers from being notified of signature requests. This commit enforces sending email notifications for signature requests regardless of user notification settings. Notifications are still created in Odoo, preserving in-app visibility for users who rely on it. task-6041834 Forward-Port-Of: odoo/enterprise#111094
This update ensures the sale dashboard accurately displays orders fulfilled through the POS system. Previously, orders in 'done' status weren't showing up, but this fix now correctly integrates POS order status updates into the dashboard view, providing a more complete picture of sales activity.
Original PR description
Step to reproduce: - install spreadsheet_dashboard_sale and pos_sale - create a order in pos , invoice it too - open sale dashboard Observation: - the order fulfilled in pos, does not reflect in…
Step to reproduce: - install spreadsheet_dashboard_sale and pos_sale - create a order in pos , invoice it too - open sale dashboard Observation: - the order fulfilled in pos, does not reflect in dashboard Cause: - sale has 4 status i.e ["draft", "sent", "sale", "cancel"] - when pos_sale is installed, new status oders are added i.e ['paid', 'invoiced', 'done'] - sale dashboard pivot relies on sale defined status only, which so not consider orders that have status in ['paid', 'invoiced', 'done'] Fix: - fix the domain of pivots such that, it will now accept other orders too **Before:** <img width="1058" height="277" alt="image" src="https://github.com/user-attachments/assets/e58c88fa-5ad3-4194-9f9c-ddf41f2f73de" /> <img width="1116" height="190" alt="image" src="https://github.com/user-attachments/assets/259e0347-5d5b-4d5c-9aeb-74102aa4becd" /> <br/> **After** <br/> <img width="1137" height="232" alt="image" src="https://github.com/user-attachments/assets/406b71a5-1dd8-4164-9d4e-4f0bca34c9e8" /> <img width="1125" height="235" alt="image" src="https://github.com/user-attachments/assets/fded3203-7d72-45ea-b5aa-142ebcd52136" /> opw-5487654 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248142
This update ensures that timesheet entries are correctly removed when a time off request is deleted or cancelled, preventing data inconsistencies. Previously, timesheets lingered even after time off was removed, leading to inaccurate tracking. This fix addresses a bug related to how the system handles time off cancellations and ensures accurate timesheet reporting.
Original PR description
BUG 1: ----------- **Steps to reproduce:** 1. Install Time Off and Timesheets with demo data. 2. Create a time off for an employee and approve it. 3. Check the related timesheet entry for that…
BUG 1: ----------- **Steps to reproduce:** 1. Install Time Off and Timesheets with demo data. 2. Create a time off for an employee and approve it. 3. Check the related timesheet entry for that employee. 4. Delete the approved time off. 5. Check the timesheet entries again. **Issue:** The timesheet entry remains even after the related time off record is deleted. **Cause:** Following commit 944c11e, admins can delete [approved time off ](https://github.com/odoo/odoo/blob/f6cf0d067e5f30e2b22ea513071cd7c5e3d9f44c/addons/hr_holidays/models/hr_leave.py#L956-L959)records. The relationship between the leave and the analytic line (timesheet) did not have a deletion policy defined. When the leave was [unlinked](https://github.com/odoo/odoo/blob/f6cf0d067e5f30e2b22ea513071cd7c5e3d9f44c/addons/hr_holidays/models/hr_leave.py#L961-L964), the analytic line remained without its parent reference. **Solution:** Explicitly remove related timesheet entries before deleting the leave record. BUG 2: ----------- Currently, refusing/cancelling a time off record can lead to orphan timesheets/duplicated hours (16h instead of 8h) if a public holiday exists on the same day. **Root cause:** The issue comes from this write method: https://github.com/odoo/odoo/blob/79ff1d63caed2c1058aa338947b9af90ebb6cd20/addons/project_timesheet_holidays/models/hr_leave.py#L128-L130 The method first unlinks the holiday_id from the timesheets and then attempts to delete them. However, once the holiday_id is set to False, the timesheets are no longer linked to the leave. As a result, leave.timesheet_ids becomes empty, and nothing is deleted. This leads to orphan timesheet records. When the leave is later refused or cancelled, a new public holiday timesheet entry is generated (if applicable), resulting in duplicated timesheet entries for the same day. **Steps to reproduce:** 1. Create a time off for one day and validate it (8h timesheet generated). 2. Create a public holiday for the same day. 3. Observe that leave duration becomes 0, but the timesheet remains. 4. Refuse or cancel the time off. 5. Observe two timesheet entries for the same day (16h total). opw-5384428 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247155
This update resolves a validation error that occurred when creating invoices from POS orders using non-cash payment methods. Previously, enabling cash rounding triggered an error due to a mismatch in how rounding logic was applied. Now, the system correctly avoids rounding when a non-cash payment is used, ensuring invoices are created without errors.
Original PR description
## Issue before this commit: Creating an invoice from a POS order with **Cash Rounding enabled only for cash payment methods** raised an unexpected validation error: > *"The operation cannot be…
## Issue before this commit: Creating an invoice from a POS order with **Cash Rounding enabled only for cash payment methods** raised an unexpected validation error: > *"The operation cannot be completed: Missing required account on accountable line."* This happened when the order was paid using a **non-cash payment method**, but rounding logic was still applied. ## Steps to Reproduce: 1. Install the `point_of_sale` module. 2. Go to POS Configuration → Settings: * Enable **Cash Rounding** * Set a **Rounding Method** * Enable **Only on cash methods** 3. Create a product: * Sale Price: 260 * Tax: 6% 4. Open a POS session. 5. Add the product to an order. 6. Apply a discount (e.g., 1.123). 7. Pay using a **non-cash payment method** (journal not marked as cash). 8. Enable **Invoice** and validate the order *(or create the invoice later from the Orders menu)* ## Cause of the Issue: While `_prepare_invoice_vals` correctly avoids setting `invoice_cash_rounding_id` for non-cash payments, `_create_invoice` still executes rounding logic whenever cash rounding is enabled on the POS configuration. This leads to a mismatch where: * No rounding configuration is set on the invoice * Rounding logic still attempts to create/update rounding lines * Required accounts (profit/loss) cannot be determined * A validation error is raised due to missing account on the generated line ## With This Commit: The rounding logic in `_create_invoice` is now guarded by checking the presence of `invoice_cash_rounding_id`. This ensures rounding is only applied when properly configured and avoids unexpected validation errors for non-cash payment invoices. Steps To Reporduce: [Video Link](https://drive.google.com/file/d/10ticlUW5i5pbu_oDDPqR-jg0hVcNWf3Z/view?usp=sharing) opw-6005320 opw-5951991 opw-6036870 Forward-Port-Of: odoo/odoo#254844
This update optimizes how Odoo handles large sale orders, significantly speeding up the rendering process. Previously, calculating parent sections was slow, leading to UI delays. Now, the system pre-computes these relationships, resulting in a much smoother and faster experience when working with complex orders.
Original PR description
This commit resolves a performance bottleneck that occurred when handling very large sale orders (e.g., ~200 order lines). Previously, the util function `getParentSectionRecord` determined the parent…
This commit resolves a performance bottleneck that occurred when handling very large sale orders (e.g., ~200 order lines). Previously, the util function `getParentSectionRecord` determined the parent (sub)section of an order line by iterating over all preceding order lines. Since this logic was executed for each order line, the overall complexity became O(n²). Moreover, this function was invoked inside the `shouldCollapse` method, which is used in multiple UI flows during rendering. As a result, large sale orders could cause noticeable UI slowdowns and block the main JavaScript thread. To address this, we now build a parent–child section mapping once per render in O(n) time. Subsequent lookups simply read from this mapping instead of recomputing the parent by scanning previous lines. This significantly reduces the computational cost and prevents UI blocking when working with large orders, leading to a much smoother rendering experience. opw-5865167 Benchmark: | No. records | Before | After | |----------------|---------------|--------------| | 150 | 1300ms | ~850ms | | Before | After | |---------------|--------------| | <img width="287" height="284" alt="image" src="https://github.com/user-attachments/assets/dd73ab18-3c53-4958-99b7-083dd5cd9e64" /> | <img width="311" height="277" alt="image" src="https://github.com/user-attachments/assets/b6e90fa3-85eb-4d72-b616-28aff9a938e8" />| --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255180 Forward-Port-Of: odoo/odoo#252991
This update resolves an issue preventing invoices sent to partners in Åland Island (AX) from being properly transmitted via Peppol. Previously, invoices were generated and attached but didn't appear in the system chatter. Now, invoices will be sent via Peppol, ensuring seamless integration and enabling companies in Åland Island to utilize Peppol.
Original PR description
Before this commit, invoice to a partner in Åland Island can't be sent via Peppol. XML and PDF are generated, linked to the account.move, but are not sent and don't appear in the chatter. Steps to reproduce: - Create a partner in Åland Island - Create an invoice - Send to Peppol Current behavior: - Invoice is not sent, appear in the attachment, but doesn't appear in the chatter. Expected behavior: - invoice is sent and attachments are in the chatter This also allow activating Peppol for companies in Åland Island. Ticket [link](https://www.odoo.com/odoo/project.task/5949439) opw-5949439 Forward-Port-Of: odoo/odoo#251943
This update ensures that DDT (Documento di Trasporto per il Dazio Dogale) information is displayed correctly for dropship orders in Italy. Previously, this information was missing, creating a discrepancy in reporting. The fix addresses a technical issue related to how the system identifies dropship operations, now ensuring accurate visibility of key shipping documents.
Original PR description
Steps to reproduce the bug: - Create a company with country = Italy and select it - Install the module “l10n_it_stock_ddt” - Activate “Dropshipping” in the inventory settings - Create a delivery → the group "DDT Information" is visible - Create a dropship → the group "DDT Information" is not visible Problem: The DDT information should also be visible for dropship operations. The compute used for “l10n_it_show_print_ddt_button” correctly takes dropship operations into account, but it cannot be reused to control the visibility of the DDT Information group because this compute is True only when the picking state is done and locked: https://github.com/odoo/odoo/blob/e6d4ab62e950c8b88ac54fecbf2682cba846c7c3/addons/l10n_it_stock_ddt/models/stock_picking.py#L34-L35 opw-5190251 Forward-Port-Of: odoo/odoo#254986
This update resolves a bug where invoice cancellations triggered by TicketBAI would block Odoo, leading to data inconsistencies. The fix checks for a security hash before sending invoices to TicketBAI, preventing Odoo from attempting to reset protected invoices. This ensures invoices can be correctly processed and avoids database blocks.
Original PR description
Before this commit, if the user configured the sales journal to be locked by a hash, then a cancellation in ticketbai would 1/ send the cancel request to ticketBAI. This would be processed…
Before this commit, if the user configured the sales journal to be locked by a hash, then a cancellation in ticketbai would 1/ send the cancel request to ticketBAI. This would be processed successfully 2/ try to reset the invoice to draft inside of Odoo, then cancel it. This would fail with an error since account moves protected by a hash cannot be reset to draft. The result is a blocked database where the invoice cannot be altered in Odoo while its status doesn't match the status in ticketBAI. In this commit, we propose to check for the secure hash before sending the invoice over to ticketBAI. The invoice is not altered yet at that stage to account for potential ticketBAI errors in the normal flow. While this option is not great from a usability perspective (preventing secure hashes with ticketBAI is probably best), we believe the current solution offers the best compromise in the context of a bugfix. The issue does not seem to be reproducible outside of production as the core of the problem is a mismatch in state between ticketBAIand Odoo. opw-5912848 Forward-Port-Of: odoo/odoo#250886
This update corrects a bug where invoices were displaying the delivery date one day in the past. The fix addresses a timezone mismatch during invoice creation, ensuring the correct delivery date is reflected based on the system's time. This improves data accuracy for sales reporting and customer invoicing.
Original PR description
Currently when the user creates an invoice the delivery date is set incorrectly. <h2>Steps to produce:</h2> * Set system timezone to Asia/Kolkata and time to 5:00 * Install Sales, Inventory * Create…
Currently when the user creates an invoice the delivery date is set incorrectly. <h2>Steps to produce:</h2> * Set system timezone to Asia/Kolkata and time to 5:00 * Install Sales, Inventory * Create and confirm a sale order * Go to Delivery and Validate the delivery * Go back to the Sale order and create an invoice. <h2>Observed Behavior:</h2> The delivery date on the customer invoice is set to one day before the current date, even though the effective date for the delivery correctly reflects the system date and time. <h2>Root cause:</h2> This issue occurs because, when a delivery is validated, the `date_done` field is set using the current time in UTC at [1], because odoo operates in UTC by default. This value is then used to compute the effective date on the sales order at [2], which in turn is used to determine the delivery date on the invoice at [3] and [4]. Users see the effective date on the delivery in their own timezone because `Datetime` fields are converted from UTC to the user’s timezone on the client side as stated in [5]. However problem arises from a type mismatch. The delivery date field is of type `Date`, while the effective date is a `Datetime`. As a result, when the value is assigned at [3] or at [4], only the date portion is passed. Because a Date field does not carry any timezone information, no timezone conversion occurs, leading to the observed discrepancy. [1]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/stock/models/stock_picking.py#L1274 [2]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/sale_order.py#L87-L88 [3]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/account_move.py#L122 [4]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/sale_order.py#L301 [5]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/odoo/orm/fields_temporal.py#L214-L217 ## **Solution:** Using the `context_timestamp` function makes it possible to work with the `Datetime` in the client’s timezone, which can then be used to correctly assign the delivery date on the invoice. opw-5391189 Forward-Port-Of: odoo/odoo#255404 Forward-Port-Of: odoo/odoo#247122
This update allows users to reverse previously scrapped stock moves, expanding flexibility in inventory management. Previously, this functionality was limited, impacting the ability to correct errors or adjust quantities accurately. This change improves inventory accuracy and streamlines operational workflows.
Original PR description
This commit enables reverting a scrapped move. Previously, it was only possible to revert inventory adjustment moves and commit https://github.com/odoo/odoo/commit/1c7d80a10b5d7db1c4163166bf52b3f3c77044ba was supposed to add the ability in. Task: 6001058
This update resolves issues with how overtime calculations handle different time zones, specifically preventing crashes and ensuring overtime lines are correctly deleted. The fix ensures accurate overtime intervals are generated and processed, regardless of the employee's location.
Original PR description
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a…
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a period, then create two consecutive midnight-to-midnight attendances in the employee's local timezone. Creating the second attendance crashes with: "ValueError: Expected singleton: hr.attendance.overtime.line(...)". Steps to reproduce (stale overtime lines): With the same setup, delete the attendance after it generated overtime lines. The overtime lines remain in the database instead of being removed. The singleton crash occurred because `end_of_day` in `_get_overtime_intervals` was computed as a naive datetime, implicitly treated as UTC. For UTC+ timezones, the actual local end of day is earlier than UTC midnight. As a result, overtime intervals were computed with a stop time extending past the real local midnight into UTC time. When consecutive attendances were processed together, these extended intervals overlapped. The `Intervals` class (`keep_distinct=True`) merges overlapping intervals into a single entry with a multi-record recordset as payload. The subsequent `overtime.rule_ids.work_entry_type_id` and `overtime.status` calls expected a singleton but received a multi-record set, causing the crash. The same multi-record issue also affected the iteration in `_set_real_overtime_intervals` and the overtime work entry loop in `_get_attendance_intervals`. The stale overtime lines issue occurred because `_get_overtimes_to_update_domain` built its search date range from raw UTC `.date()` values instead of the employee's local timezone. For UTC+ employees whose attendance spans local midnight, the overtime line is dated in the next local calendar day. Since the domain was derived from UTC dates, that next local day fell outside the search range, so the overtime line was never found and deleted when the attendance was removed. Additionally, `_get_localized_times` called `.astimezone()` on naive UTC datetimes without first localizing them, producing incorrect local times for the same reason. Solution: - In `_get_overtimes_to_update_domain`, localize check_in/check_out to the employee's timezone before computing the overtime search date range (with a ±1 day buffer) so overtime lines for dates that only exist in local time are correctly included in the delete-and-recreate cycle. - Fix `_get_localized_times` to call `utc.localize()` on naive UTC datetimes before converting to the employee's timezone. opw-5931665 Forward-Port-Of: odoo/odoo#254543 Forward-Port-Of: odoo/odoo#251812
This update fixes a validation issue related to Saudi Arabia's ZATCA tax reporting. Previously, the system didn't include invoice cash rounding amounts in the payable calculation, leading to validation errors. This change ensures accurate VAT calculations and prevents invoice validation failures.
Original PR description
Currently the generated ZATCA XML is not accounting for invoice cash rounding, leading to an invoice validation issue due to a mismatch in the calculation of PayableAmount. Steps to reproduce: - Have a SA Company setup - Create a [cash rounding] with strategy 'Add invoice line' and rounding 1.00 (UP) - Create an invoice for 99.55 + 15% Tax - Set Cash Rounding Method to [cash rounding] - Confirm and send xml for validation Issue: Validation will issue the following warning `[202] BR-CO-16 : Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Pre-Paid amount (BT-113) + Rounding amount (BT-114).` Analysis: The ZATCA implementation was calculating the payable amount strictly as (TaxInclusiveAmount - PrepaidAmount). This change ensures the rounding amount is fetched and added to the total payable calculation opw-5939550 Forward-Port-Of: odoo/odoo#255178 Forward-Port-Of: odoo/odoo#253555
This update ensures that analytic lines created from services and materials within sales orders automatically use the 'Project' plan instead of the standard 'Sales Orders' plan. A new setting allows users to customize this behavior if needed, providing greater flexibility in tracking costs. This change improves reporting accuracy for project-based sales.
Original PR description
This change ensures that analytic lines generated from Services and Materials create analytic accounts per Sale Order under the **Project** plan by default, instead of using the dedicated **Sales Orders** plan. A new system parameter `sale.analytic_plan_sale_orders` has been introduced to allow users to override this behavior and define a custom analytic plan for upsell lines when needed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where component consumption wasn't accurately tracked in the manufacturing process. Specifically, a technical glitch was resetting the consumed quantity, leading to incorrect inventory levels. This fix ensures components are properly used during production runs.
Original PR description
# Product Configuration *Manufactured Product* - Storable - Tracked by Quantity - Manufacture Route - Has a BOM with atleast 1 component *Component Product* - Storable - Tracked By Lot # How to…
# Product Configuration
*Manufactured Product*
- Storable
- Tracked by Quantity
- Manufacture Route
- Has a BOM with atleast 1 component
*Component Product*
- Storable
- Tracked By Lot
# How to reproduce
- Ensure there is available stock for the component product in a lot
- Create a MO for the Manufatured Product
- Confirm the MO
- Click "Details" on the component product
- Remove the reserved quant and add a new one
- Increase the quantity of this new quant to more than "To Consume"
- Save
- Observe that "Consumed" = The quantity you just set on the quant
- Click on "Produce All"
# The issue
- The Consumed quantity is reset to the "To Consume" quantity.
- Furthermore, a warning popup should be displayed when clicking on "Produce All" but there is none.
- Finally, depending on the version you may get this error message : "You need to supply Lot/Serial Number for products and 'consume' them: - Component Product" even though a lot is already assigned
# Why
All these issues stem from the fact that move_raw_ids.picked from mrp.production is set to False instead of True.
This issue was introduced by this commit (https://github.com/odoo/odoo/commit/ef592464983d66ac76bc71a9886462f1f47dc28d) that changed the way the picked value is set.
In write(self, vals) de stock_move, we have :
```py
if self.env.context.get('force_manual_consumption') and 'quantity' in vals:
moves_to_update = self.filtered(lambda move: move.product_uom_qty != vals['quantity'])
if moves_to_update:
moves_to_update.write({'manual_consumption': True, 'picked': True})
```
Followed a bit later by :
```py
res = super().write(vals)
```
This usually works fine except when vals contains edition commands for move_line_ids. Then, the first write will correclty set picked to True, but then picked will be reevaluted after the second write with :
```py
@api.depends('move_line_ids.picked', 'state')
def _compute_picked(self):
for move in self:
if move.state == 'done' or any(ml.picked for ml in move.move_line_ids):
move.picked = True
else:
move.picked = False
```
If all the resulting move_line_ids from the commands edition have picked set to False, then move.picked will also be set to False.
opw-5937171
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#253607This update resolves an issue where notification reminders failed when attendees had access to companies not visible to the event organizer. The fix ensures that attendee company access is properly checked, preventing access errors and guaranteeing reminders function as expected for all users, regardless of their company affiliations.
Original PR description
[FIX] calendar: use sudo for attendee company access in notifications Invitations with notification reminders fail if the attendee has access to companies hidden from the organizer. ### Reproduction Steps 1. User A (Company 1) invites User B (Company 1 & 2). 2. Add a "Notification" reminder. 3. Saving the event raises an AccessError on res.company. ### Cause When preparing notifications, the attendee's company list is fetched while still in the organizer's environment. The `res.company` record rule restricts visible companies to the organizer's own, so the attendee's extra companies are blocked. Since 9a21edd99e7f, `Many2many.read()` uses `_search()` without `bypass_access`, which explicitly checks read access and raises `AccessError` instead of silently filtering at the SQL level. opw-5916536 Forward-Port-Of: odoo/odoo#253679
This update corrects an issue where embedded attachments within SDI invoices were overwriting the main XML file, causing import failures. The fix involves storing attachments separately, ensuring data integrity and proper invoice processing. Additionally, the naming convention for attachments has been improved.
Original PR description
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR…
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR also stores attachments embedded in the `<Allegati>` element of the XML in this same field. This results in three issues when importing invoices from the SDI: 1. The first embedded attachment will overwrite the XML file's contents, corrupting it. 2. Subsequent embedded attachments will continue to overwrite the previous attachment. 3. All embedded attachments are linked to the `account.move` record by the Many2one field `attachment_ids`, which is contrary to the stated goal of PR #212726. These behaviors cannot be replicated in a runbot environment, as there is no way to test the SDI import process in runbot at the time of writing. Localhost environments can replicate this issue by receiving an XML from the test l10n_it API server, or by passing similarly encrypted data to the method `_l10n_it_edi_process_downloads()`. See the method `test_decrypt_invoice_from_IAP()` from PR #250439 for an example of the encryption process. **Solution**: Do not overwrite the field `l10n_it_edi_attachment_file`. Add stored field(s) to master for attachment(s) within an XML's `<<Allegati>` element. This PR also improves how Allegati attachments are named, as my previous PR #246220 could result in files with two extensions (e.g. "filename.txt.TXT"). Ticket [link](https://www.odoo.com/odoo/project.task/5800658) opw-5800658 Forward-Port-Of: odoo/odoo#252806