Wednesday, July 2, 2025
15 changes · 18.0
Enhancements to existing features
Uruguayan electronic invoices now send a valid item name consistently and place longer product details in the description field. This prevents duplicated product names on generated PDF reports and better matches DGI field limits.
Original PR description
This PR aims to improve the way we create NomItem and DscItem lines on the XML files we send to DGI in order to generate the PDF report. We have two fields to inform to DGI in an electronic invoice,…
This PR aims to improve the way we create NomItem and DscItem lines on the XML files we send to DGI in order to generate the PDF report. We have two fields to inform to DGI in an electronic invoice, NomItem which is mandatory an has a maximum of 80 characters to send, and DscItem that is optional an has a limit of 1000 chars. So we ensure NomItem is always sent, and the description will be filled like this: First, if the product name is longer than 80 chars, DscItem field will contain the characters that didn't fit in the NomItem field (characters from the 80th) Then it will contain the description of the product and the addenda content if it exists. Plus, I refactor the method _l10n_uy_edi_cfe_D_global_discount so it is also aligned with what I mentioned before. Another reason for this improvement is that, as the description of a product contains the product name at the beginning, we faced some issues when a user added a description on the fly in the line of the product, and then confirmed and printed the report. In this case, the name of the product was duplicated in the report. With this change, the description will only contain the the part of the product name that exceeds the 80th character. Example: 
Payroll calculations now include additional state-specific employer rates for Alabama, Colorado, and Washington. This helps ensure US payroll results better reflect current state obligations and reduces the need for manual payroll adjustments.
Original PR description
Added salary rules for state: - US: Alabama ESA rate - US: Colorado Support Surcharge rate - US: Colorado Solvency Surcharge rate - US: Washington EAF Rate task-4814709
Resolved issues and error corrections
This fixes an issue where manually adjusted extra hours on an employee attendance could be reset when another attendance was created. The system now avoids recalculating automatically approved extra hours when they appear to have been manually changed, helping payroll and attendance records better reflect user edits.
Original PR description
**Steps to reproduce** - Set "Extra Hours Validation" to "Automatically approved" - Create an attendance for an employee - Change the "Extra Hours" to a different value - Create another attendance…
**Steps to reproduce** - Set "Extra Hours Validation" to "Automatically approved" - Create an attendance for an employee - Change the "Extra Hours" to a different value - Create another attendance for this employee (not necessarily on the same day) - See that the "Extra hours" of the previous attendance has been recomputed, resetting the value entered by the user. **Cause** When creating an attendance for an employee, we recompute the `validated_overtime_hours` for the other attendances of this employee https://github.com/odoo/odoo/blob/cac96f5d3c391ea0d52da2e3433e7eabe07e8fb0/addons/hr_attendance/models/hr_attendance.py#L426 In case of attendances with no validation, this field is synced with the `overtime_hours` https://github.com/odoo/odoo/blob/cac96f5d3c391ea0d52da2e3433e7eabe07e8fb0/addons/hr_attendance/models/hr_attendance.py#L156 **Solution** We may still want to recompute the `validated_overtime_hours` of automatically approved attendances, since it is their default state, unlike manually approved attendances. If the `validated_overtime_hours` field is different from `overtime_hours`, it means it has been modified. In that case, we avoid recomputing it. This doesn't guarantee a manually set value will never be overriden by a change in its dependencies, but it reduces the likelihood. opw-4639230
Restaurant point-of-sale preparation printers now print cancelled kitchen order tickets when items are reduced or removed while other items are added. This helps kitchen staff see both new orders and cancellations, reducing missed changes and service errors.
Original PR description
Steps to reproduce: -------------------------- - Install POS restaurant & configure a preparation printer. - Open a session, order item A with some quantity from table X. - Again open table X & remove some qty of item A and add some qty of item B. - Order the changes. - On the preparation printer the cancelled KOT for item A won't appear. Issue: -------- - No receipt printed for the items which are cancelled. Cause: --------- - We have conditioned the printing in a way that if we found something new or if mode is updated rest prints won't be printed. Fix: ----- - Now we will have 2 receipts one for the new ordered items and the another with cancelled items. Task: 4805293
Credit notes created from vendor bills now carry negative landed cost amounts, so inventory value is reduced instead of increased. This prevents refunds from accidentally applying landed costs a second time and overstating stock value.
Original PR description
Before this PR, creating a landed cost in the following scenario incorrectly increased the stock valuation instead of reducing it: - Create a Purchase Order with a valuated product and a landed cost…
Before this PR, creating a landed cost in the following scenario incorrectly increased the stock valuation instead of reducing it: - Create a Purchase Order with a valuated product and a landed cost product in the order lines. - Validate the receipt of the PO. - Create the vendor bill from the PO and confirm it. - Create a landed cost from the vendor bill by clicking "CREATE LANDED COSTS" and selecting the receipt in the landed cost. - Validate the landed cost. - Create a credit note from the vendor bill. - Create a landed cost from the credit note by clicking "CREATE LANDED COSTS" and selecting the same receipt. - Validate the landed cost. In this scenario, the refund amount is treated as a positive landed cost, causing the stock valuation to increase again. This can lead to the landed cost being applied twice by mistake, overstating inventory value. After this PR, the landed cost line amounts for credit notes are correctly set as negative, which reduces the stock valuation instead of increasing it. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr OPW #4844792 @qrtl QT5401 Forward-Port-Of: odoo/odoo#216378 Forward-Port-Of: odoo/odoo#212669
Checkout now filters available delivery methods by the appropriate company, preventing errors when some delivery methods belong to another company and others are shared or linked to the website company. This helps customers complete orders reliably in multi-company website setups.
Original PR description
Description of the issue/feature this PR addresses: Error during checkout when using delivery methods with mixed company assignments. Current behavior before PR: If you create a delivery method assigned to company X, and then create another without a company (i.e., assigned to the website company or left empty), the checkout process fails when trying to select a delivery method. Steps to reproduce: 1. Create a delivery method and assign it to company X. 2. Create another delivery method with no company or assign it to the website's company. 3. Go to the website and try to place an order. 4. The checkout will fail when selecting the delivery method. Desired behavior after PR is merged: Checkout handles delivery methods consistently, even when companies are mixed or missing. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#216662 Forward-Port-Of: odoo/odoo#216515
The Time Off Balance report no longer applies a default period filter that could hide valid remaining days or hours. This prevents misleading balances when employees have allocations spanning different years, giving managers and HR teams a clearer view of available time off.
Original PR description
**Issue** In the "Balance" report, the number of days/hours left is incorrect when a period filter is applied. **Cause** The report groups all allocations for a certain time off type and returns a…
**Issue** In the "Balance" report, the number of days/hours left is incorrect when a period filter is applied. **Cause** The report groups all allocations for a certain time off type and returns a single `hr.leave.employee.type.report` which uses the start date of the record with the lowest id. The "Period" filter, using the start date of the records, will therefore not make sense. **Change** Remove the default period filter as trying to display a balance by period introduces too many complications. **Steps to reproduce** - Have an employee with 0 allocations. - Create an allocationfor this employee with a start and end date in the previous year for a certain time off type. - Create another allocation for this employee with a start and end date in the current year for the same time off type. - Time Off > Reporting > Balance - Bug: with the default filter (Period: current year), the "Number of days" and "Number of hours" left for that time off type shows nothing. However, when applying a filter for the previous year, both allocations are counted. opw-4715547
This fixes an issue in Point of Sale where using quick-add amounts followed by another digit could leave the payment amount unchanged or turn it into an incorrect decimal value. Cashiers can now enter payment amounts more reliably, reducing checkout mistakes and manual corrections.
Original PR description
Steps to reproduce: =================== - Add a product to the orderline from the product screen - Click payment - Select any payment method - Enter the amount manually - Press `+20`, then press `2`, OR press `+20`, then press `6` Issue: ====== - In the case of `+20` and `2`, the expected result is `202`, but we get `20` - In the case of `+20` and `6`, the expected result is `206`, but we get `20.01` Cause: ====== - `formatCurrency` is used for the buffer, but the buffer should not depend on the currency Fix: ==== - Remove the usage of `formatCurrency` and treat the buffer as a string Task: 4850543 Forward-Port-Of: odoo/odoo#213294
Invoices linked to Saudi down payments now show a clear validation message if the down payment has not first been submitted to ZATCA. This prevents crashes during invoice posting and helps businesses follow Saudi e-invoicing compliance steps correctly.
Original PR description
Description of the issue/feature this PR addresses: This PR fixes a crash that occurs when posting an invoice linked to a down payment that has not yet been submitted to ZATCA. The issue is caused by a missing l10n_sa_confirmation_datetime on the referenced prepayment move. Current behavior before PR: When the prepayment invoice is not ZATCA-posted, its l10n_sa_confirmation_datetime is False, causing a crash during UBL generation for the final invoice. No clear error is shown to the user. Desired behavior after PR is merged: The system will raise a clear ValidationError, notifying the user that the related prepayment must be successfully submitted to ZATCA before continuing. This prevents silent failures and ensures proper compliance. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Customer statement emails now use the sender and reply-to addresses configured on the email template. This ensures businesses can control which address customers see and reply to, instead of unintentionally using the current user's email address.
Original PR description
Steps to reproduce:
Go to Settings> Email templates
Open the template Customer statements
Change the value in email from or reply to
Go to Accounting > Customers > Customers
Open a customer
Send a customer statement
Issue:
The address in use is not the same as we specified in the customer template
Cause:
if no email_from is provided, we will use the current partner's use's email address https://github.com/odoo/odoo/blob/cc0aaff5f93d5332c60d5bd8097173326a0a12b3/addons/mail/models/mail_thread.py#L2863-L2864
We don't check if the template has any email_from address defined
Note:
As from this fix, if no address is defined, by default it will be the `{{ object._get_followup_responsible().email_formatted }}`
opw-4864155The UAE payroll rules now match the government end-of-service calculator by applying the full 30-day compensation only after an employee completes the sixth year of service. This helps ensure final settlement amounts are calculated correctly and consistently with official guidance.
Original PR description
- to algin with UAE goverment eos calculator, salary rule is update to concider full 30 compensation after completing the 6th year not the 5th. Task: 4756963
Fixes an issue where adding a second rental product could shift the selected rental end date for customers in UTC+ time zones. This keeps the customer's chosen rental period consistent in the website cart, reducing booking mistakes and checkout confusion.
Original PR description
## Version
18.0
saas-18.1
Fixed from saas-18.2 thanks to commit 951433846e18e77a3d468af1f005b5c8e224ef89
## Issue
If user's timezone is in UTC+X, rental period changes after adding 2nd rental product to cart.
## Steps to reproduce
- Go to Rental App:
- Via `Products` create 2 rental products (`Product A` and `Product B`):
- Under the `Rental prices` tab, add a new pricing with a `Daily` period;
- Publish the products.
- Go to website's shop:
- Look for `Product A`:
- Select a one-day period (same date for start and end dates);
- Add the item to cart.
- Look for `Product B`:
- Click `Add to cart` button and see the end date change for the next day.
opw-4744250EasyPost shipping labels now include the related Odoo delivery reference, making it easier to match physical shipments and carrier dashboard entries with the correct Odoo delivery. This reduces manual lookup work and helps users track shipments more reliably.
Original PR description
Issue ----- When using the Easypost delivery service, we don't pass the move reference to the carrier. This makes it hard for the user to match the deliveries found on the carrier dashboard with the…
Issue ----- When using the Easypost delivery service, we don't pass the move reference to the carrier. This makes it hard for the user to match the deliveries found on the carrier dashboard with the corresponding Odoo move. Steps to reproduce ----- - Set an Easypost delivery method up - Create a sale - Add delivery product & get a rate - Confirm the sale - Go to the linked delivery & confirm it --> The printed label has no reference field Discussion ----- As per EasyPost: > The reference field within the shipment body is used for transmissions of electronic data between the shipper and EasyPost, and typically does not get expressed anywhere on the physical label. To get data to the label, you need to leverage the "print_custom" fields outlined in the options section of the shipment. See also https://docs.easypost.com/docs/shipments/options Visual comparison ----- DPD UK labels, before and after the change:  USPS labels, before and after the change:  ----- Ticket: opw-4681615
Repeat website appointment bookings made with the same email and phone now reuse the existing visitor contact instead of creating duplicates. This keeps customer records cleaner while ensuring contacts created by internal users are not changed by website visitors.
Original PR description
**Steps to reproduce:** 1. Install appointment and website 2. Book two appointments on the website without logging in, using the same email and phone number **Issue:** - Two separate contacts are…
**Steps to reproduce:** 1. Install appointment and website 2. Book two appointments on the website without logging in, using the same email and phone number **Issue:** - Two separate contacts are created each having one appointment, instead of a single contact with two appointments. **Cause:** https://github.com/odoo/enterprise/blob/c27021bb5bf5994c3e9500d91c6977ee7b795150/appointment/controllers/appointment.py#L683 - The appointment booking logic does not check for existing customers Based on the email and phone from website visitors. **Solution:** - Search for an existing contact created by the visitor before creating a new one. **Behaviour before this commit:** - If a visitor create multiple appointments with same crediantials (email, phone) then multiple contacts are being created - Converted public user from internal user will always create new contact. **Behaviour after this commit:** - If a visitor create multiple appointments with same crediantials (email, phone) then only one contact will be created. - Contact created by internal users will not be modified by a visitor - Converted public user from internal user will always create newa contact. opw-4884363
This fix prevents an error when older online banking records do not yet have a provider type set. It helps migrations complete successfully and keeps payment link status checks from failing on missing provider information.
Original PR description
The issue occurs because the value of the provider_type field is null. As a result, when the system attempts to compute the value of the account_online_linked Boolean field — which depends on both…
The issue occurs because the value of the provider_type field is null. As a result, when the system attempts to compute
the value of the account_online_linked Boolean field — which depends on both provider_type and account_online_link.
The error occurred due to a null `provider_type`.
157, in _compute_account_online_linked
batch.account_online_linked = account_online_link
and 'payment' in account_online_link.provider_type
TypeError: argument of type 'bool' is not iterable
An error occurred during migration.
The issue originates [here](https://github.com/odoo/enterprise/commit/eb78dd3b9a3d78bb6aa4ffcf35cee82c8e78224c) due to a `null` value in the `provider_type` field.
actually the field [provider_type](https://github.com/odoo/enterprise/pull/44357/files) is introduce in the version 17.0 this is because to improves the online synchronization process by ensuring that the third-party provider (TPP) involved in each sync is now stored and displayed.
- The provider is now automatically recorded during each synchronization.
- It is shown in both the form view and the tree view for better visibility.
- Previously, this information was not displayed, making it difficult to trace which provider handled the sync.
This change enhances transparency, traceability, and helps in debugging or support scenarios.
The issue arises because the value of the provider_type field is not set manually by the customer, as the field is marked [readonly](https://github.com/odoo/enterprise/blob/e4f0d273780274202cd0fd653c6a74320530842b/account_online_synchronization/views/account_online_sync_views.xml#L28) in the view.
This means users cannot edit or input a value for provider_type through the UI.
Instead, the value of the provider_type field is automatically computed when a third-party payment gateway (such as SaltEdge, Plaid, etc.) is connected to the system.
This setup process establishes a link (account_online_link) between the Odoo bank account and the external provider, and during that process,
the provider_type is set based on the provider's metadata.
If the connection is not properly established, the provider_type field may remain unset (None).
so if the value of provider_type is null and the when we going to computed the value of boolean field i.e account_online_linked which depends on the provider_type field and record in account_online_link see [here](https://github.com/odoo/enterprise/blob/e4f0d273780274202cd0fd653c6a74320530842b/account_online_payment/models/account_batch_payment.py#L156)
then issue is occur so to handle this issue safely, I have added a condition: if the value of provider_type is null, the account_online_linked field will be set to False.
```sql
=> select id,provider_type from account_online_link;
id | provider_type
----+---------------
6 |
12 |
13 |
(3 rows)
=>
```
```sql
('account_batch_payment.menu_batch_payment_purchases', 332, 'Accounting > Vendors > Batch Payments', 474):
Traceback (most recent call last):
File "/tmp/tmp2ec381z7/migrations/base/tests/test_mock_crawl.py", line 271, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmp2ec381z7/migrations/base/tests/test_mock_crawl.py", line 284, in mock_action
return self.mock_act_window(action)
File "/tmp/tmp2ec381z7/migrations/base/tests/test_mock_crawl.py", line 444, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmp2ec381z7/migrations/base/tests/test_mock_crawl.py", line 475, in mock_view_form
[data] = record.read(fields_list)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 3843, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 4074, in _read_format
vals[name] = convert(record[name], record, use_display_name)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 7061, in __getitem__
return self._fields[key].__get__(self)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 1303, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 1485, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/18.0/addons/mail/models/mail_thread.py", line 427, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5280, in _compute_field_value
fields.determine(field.compute, self)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 110, in determine
return needle(*args)
File "/home/odoo/src/enterprise/18.0/account_online_payment/models/account_batch_payment.py", line 156, in _compute_account_online_linked
batch.account_online_linked = account_online_link and 'payment' in account_online_link.provider_type
TypeError: argument of type 'bool' is not iterable
```
OPW-4910519
UPG-2999613
TBG-2091