Daily updates from Odoo
Monday, July 28, 2025
21 changes · 18.0
Enhancements to existing features
Point of Sale payments in Argentina, Peru, and Uruguay now request an invoice by default. This supports local requirements that sales generate an electronic document, reducing the risk of missed invoicing during checkout.
Original PR description
[IMP] l10n_*: set default invoice true in pos modules: l10n_pe_pos, l10n_ar_pos, l10n_uy_pos In the POS, in the payment screen, the button to request an invoice is set to true by default. This is done because a sale in these countries must generate an electronic document. task-4612192
Indian companies will now keep HSN codes on point-of-sale accounting entries even when POS orders are reversed after session closure. This helps maintain accurate HSN-wise tax reporting for GSTR filings and reduces manual correction work.
Original PR description
This commit ensures that the `l10n_in_hsn_code` is also included in the accounting move lines are generated for reversal entries of POS orders when the The company’s fiscal country is India. Key changes: * Introduced the method `_prepare_product_aml_dict` in `point_of_sale` to centralize journal line creation logic. * Overridden the method in `l10n_in_pos` to append the `l10n_in_hsn_code` from the base values for Indian companies. * Ensured this applies consistently for both regular and reversal entries. This enhancement is essential for maintaining accurate HSN-wise reporting in GSTR filings, even when entries are reversed after session closure. OPW: 4931360
The French tax report now shows a warning when key declared tax amounts do not balance against related totals. This helps users spot possible reporting errors before submitting or reviewing the report.
Original PR description
This commit will add a warning banner when the sum of field 08+09+9B+10+11+T1->T7 is not equal to sum of field A1+A2+A3+B2+B3+B4 Task-4933787
The database expiration message now reflects the updated payment grace period, where expiration is set 15 days after the next invoice date. This helps customers understand the real deadline earlier and encourages timely payment before access is affected.
Original PR description
Previously, the database expiration date was set to the same date as the expiration field, which is now defined as 15 days after the next invoice date. Issue: Users tend to wait until the last minute to pay. This improvement aims to better handle expiration timing and encourage timely payments. TaskID: 4384877 Forward-Port-Of: odoo/enterprise#90810 Forward-Port-Of: odoo/enterprise#90664
Resolved issues and error corrections
Point of Sale now correctly accepts multiple existing serial numbers for the same product when creating new serial numbers is disabled. This prevents valid sales from being blocked during checkout and helps staff process tracked inventory reliably.
Original PR description
**Steps to reproduce:** - Install `point_of_sale`. - Go to POS -> configuration -> settings - Search 'Operation type' -> open picking type -> Disable `Create new` - Create a storable product 'test'…
**Steps to reproduce:** - Install `point_of_sale`. - Go to POS -> configuration -> settings - Search 'Operation type' -> open picking type -> Disable `Create new` - Create a storable product 'test' with serial tracking. - Add on-hand quantity with serial numbers. - In POS, select the product and choose one SN, - Select it again and choose another SN. **Observation:** - The order line should have 2 quantities with a list of Serial numbers chosen by the user. For one quantity, it's working fine, but for multiple quantities, an issue occurs. **Issue:** - While confirming edit serial numbers popup for multiple quantities, it checks whether each selected SN is valid or not. - The condition is that the entered SN is in the existing available SNs option. But the already chosen SN is not in the existing SN option, - Also, creating a new SN is disabled, so it's considered an invalid input. https://github.com/odoo/odoo/blob/876b7337eb689e0682ab48e9e833f9f0dc6bb8d2/addons/point_of_sale/static/src/app/store/select_lot_popup/select_lot_popup.js#L190-L193 **Solution:** - Added a condition to allow SNs that are already selected (matched by name and ID) to be considered valid inputs. opw-4865902 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now better recognizes older Microsoft Word, Excel, and PowerPoint files, and avoids renaming newer Excel files as ZIP files when their type is detected too generically. This prevents portal uploads in Documents from receiving incorrect file extensions and reduces confusing warnings for users.
Original PR description
## [FIX] core: python3-magic vs .doc/.xls/.ppt [python3-magic](https://packages.ubuntu.com/noble/python3-magic)/[python-magic](pypi.org/project/python-magic) (apt/pip) is a frontend for…
## [FIX] core: python3-magic vs .doc/.xls/.ppt [python3-magic](https://packages.ubuntu.com/noble/python3-magic)/[python-magic](pypi.org/project/python-magic) (apt/pip) is a frontend for [libmagic](https://manned.org/man/ubuntu-noble/magic) the library that can introspect files to determine their types. The Documents app makes heavy usage of our mimetypes utilities to scan and fix the extensions of files uploaded by portal users. Everytime a portal user uploads a `.doc`/`.xls`/`.ppt` file, python3-magic is gonna guess the mimetypes `application/x-ole-storage` or `application/CDFV2` which are the mimetypes of the generic file format that Microsoft Office was using until 2006. The problem is that there is no specific extension for those two mimetypes as Microsoft was using the same file format for many of its office applications. In this work we enrich python3-magic's detection with our own, which is able to tell different `application/x-ole-storage` and `application/CDFV2` files apart. **Please note**: Excel files are detected only when the entire file is present. Excel files uploaded via the Documents app are not detected because Documents only `guess_mimetype` on the first 1kiB of the document. We also added a condition to keep the .doc/.xls/.ppt extension in case the generic `application/x-ole-storage` or `application/CDFV2` mimetype is guessed. Before it was emitting a warning due to the unknown extension. ## [FIX] core: python3-magic vs new (2025) .xlsx files [python3-magic](https://packages.ubuntu.com/noble/python3-magic)/[python-magic](pypi.org/project/python-magic) (apt/pip) is a frontend for [libmagic](https://manned.org/man/ubuntu-noble/magic) the library that can introspect files to determine their types. The Documents app makes heavy usage of our mimetypes utilities to scan and fix the extensions of files uploaded by portal users. Sometypes when portal user uploads a `.xlsx` file, python3-magic fails to detect the Microsoft Excel 2007+ (OOXML) mimetype and instead guesses a generic `application/zip`. Technically this is not wrong, OOXML files (like Java JAR and Python Weels) are using the zip format. This is quite strange because python3-magic is able to work with `.xlsx` files. I'm guessing that Microsoft deployed a new version of Excel and that magic doesn't correctly guess the new (2025) `.xlsx` files. Using a hex editor, the old (from our unittests) and new (from a 2025 support ticket) seem similar: OOXML files, deflate compression, same files present. They are a bit different, in the old the `[Content_Types.xml]` file comes last, in the new it comes first. The zip headers are different too, the old uses zip Data Descriptors, the new doesn't. The problem is that the Documents app uses the guessed mimetype to "fix" the extension of the uploaded file. So the portal-user's `file.xlsx` gets wrongly rewritten to `file.zip`. We first used an approach similar to the previous commit[^1], to use our own detection of OOXML files. It works great in base where we run the detection on whole files. However it doesn't work for the Documents app because it attempts to guess the mimetype only reading the first 1kiB of the uploaded file. A first PR odoo#213647 suggested to change Documents to load the whole file first, and then run `guess_mimetype`, but was rejected. In this work, we made so we don't fix the extension of zip-like files should the guessed mimetype be application/zip. [^1]: [FIX] core: python3-magic vs .doc/.xls/.ppt opw-4607156 opw-4753670
This fixes an issue where saving a website page with an embedded signing/payment component could create a duplicate, non-working signature box. The component is now protected from direct website editor changes, helping keep quotation signing pages reliable for customers.
Original PR description
Problem: Making `owl-component` editable causes issues. Upon saving, its content gets duplicated because the saved DOM includes both the rendered and injected content. Solution: Mark `owl-component` as non-editable to prevent modification and avoid content duplication. Steps to reproduce: 1. Navigate to Sales → Open a quotation that requires signature 2. Go to Website preview 3. Click "Sign & Pay" 4. Open Web Editor 5. Save. → A duplicate, non-functional signature box appears opw-4749129 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#217651
Combo products in Point of Sale now count as a single item for loyalty program rules instead of counting each included option separately. This prevents customers from receiving extra unintended discounts or points when buying combos, improving accuracy in promotions.
Original PR description
Combo lines where counted as products in the loyalty program rules, but they are part of only one product, the combo product. So when you add a combo product to the cart, it should count as one product no matter how many items are in the combo. Steps to reproduce: ------------------- * Create a combo product with 3 products options in it * Create a loyalty program that give 1 point with a minimum quantity of 2. And 100% discount on the cheapest product in exchange of 1 point * Open PoS session * Add the combo product to the cart > Observation: You get 2 discount of 100%. Why the fix: ------------ We ignore combo lines in the loyalty program rules. This way, no matter how many products are in the combo, it will only count as one product for the loyalty program rules. opw-4783013 Forward-Port-Of: odoo/odoo#213002
Users can now attach receipts to submitted expense reports without encountering an error screen. The fix improves reliability for expense submissions by checking access and attachment details before saving receipts.
Original PR description
<b>Version:</b> - 18.0 <b>Steps to Reproduce:</b> 1. Log in as Admin. 2. Install the Expenses module. 4. Go to Users > Select or Create an internal user: - Create an Employee for the user (if not…
<b>Version:</b> - 18.0 <b>Steps to Reproduce:</b> 1. Log in as Admin. 2. Install the Expenses module. 4. Go to Users > Select or Create an internal user: - Create an Employee for the user (if not already done). - Ensure Expenses is set blank. 5. Log in with this user. 6. Go to Expenses > Create a new expense. 7. Add a name and total, click "Create Report", then "Submit to Manager". 8. Go back to the expense and attempt to attach a receipt. <b>Issue:</b> - A traceback is raised when trying to attach receipt after submitting the report. **Cause:** - When setting the main attachment, the method _message_set_main_attachment_id tries to filter on mimetype assuming it's always a string. If the attachment has False value for mimetype, this leads to AttributeError: 'bool' object has no attribute 'endswith'. **Solution:** - Safely check whether the attachment exists before calling _message_set_main_attachment_id. This avoids passing an empty recordset and prevents triggering the downstream error. <b>opw-4760255</b>
This fix ensures tips added after payment in Restaurant Point of Sale are recorded as part of the customer's payment instead of appearing as change or an accounting difference. It helps sessions close cleanly and keeps receipts and journal entries accurate.
Original PR description
Steps to reproduce: ------------------- 1. Enable tipping after payment 2. Make an order, pay it with customer account, then tip an amount X 3. On the receipt, that amount X is shown as 'change'!! 4.…
Steps to reproduce: ------------------- 1. Enable tipping after payment 2. Make an order, pay it with customer account, then tip an amount X 3. On the receipt, that amount X is shown as 'change'!! 4. Close the PoS session 5. On backend, go to Sessions, and choose the session you just closed 6. It won't be closed, as there are still a diff of X amount, so click 'Close Session & Post Entries' (the purple button), and confirm the prompt about posting the diff X into the receivable PoS account 7. Go to journal items (the magical button), and observe that the tip amount X is on a different move line labeled 'Difference at closing PoS session', and is not even in the name of the customer Why the problem: ---------------- Before 17.4, we had a function `set_tip` on the backend that updated the payment line to add the tip amount whenever we tip after [1]. However, after commit 2a5f1ab, the logic of `set_tip` was moved to the frontend [2], or most of it, as it seems that we missed moving the logic that updates the payment line. The fix: -------- We now restore the method `set_tip` that was before 2a5f1abf2e98ee09fa7a912b87d71879b5ff260b, which will update the payment line and the order. [1]: https://github.com/odoo-dev/odoo/blob/636606d12cec79a0196ed0f9b7bb71a78d4fe65a/addons/pos_restaurant/models/pos_order.py#L206 [2]: https://github.com/odoo/odoo/blob/d5baeec9b60bdf3a5ab9d1243f46e957c0489877/addons/pos_restaurant/static/src/app/tip_screen/tip_screen.js#L90-L96 opw-4736154
Invoices sent to a billing contact now use the parent company's invoice sending method when that contact is managed under the company. This prevents invoices from being sent manually or through the wrong channel because of an older setting on the individual contact.
Original PR description
Problem: When an individual has an invoice sending method set before being assigned to a company parent contact, the account move sending wizard will not send the invoice based on the parent…
Problem: When an individual has an invoice sending method set before being assigned to a company parent contact, the account move sending wizard will not send the invoice based on the parent contact's sending method. The user expects the invoice to be sent based on the parent contact's invoice sending method when the individual's accounting setting is managed by the company. Steps to Reproduce on Runbot: 1. Install sale, subscription, accounting. 2. Enable Customer addresses in Accounting > Settings 3. Create a company contact > set the "Invoice sending=By email" 4- Create a child billing contact > unlink it from the company > set the "Invoice sending=Manual" > link it back to the company. At this point, the billing contact should follow the parent company settings 5. Create a subscription > set the company as the customer. Note: deactivate the "Online payment" and set the "Start date" in the past, so you can generate the invoice with the cron "Sale Subscription: generate recurring invoices and payments". 6 Generate the invoice. opw-4812984 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix improves Nilvera Turkish e-invoice XML so invoices include required exchange-rate notes for foreign currencies and document-level discount totals. It also adjusts the invoice amount layout to comply with Nilvera requirements, reducing the risk of rejected or incorrect e-invoices.
Original PR description
This commit does following fixes for e-invoice XML generated for Nilvera. - adds currency exchange rate as note in XML if invoice currency is other than TRY. - adds total discount amount at the Invoice document level. - creates a new XML template for TR e-invoice inherited from the UBL Invoice Template. - removes the `<cac:PrepaidAmount>` node as it is not a valid node in Nilvera and adds the node value to `<cac:PayableAmount>` so that actual invoice amount is preserved while sending e-invoice. TaskID:4815875 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#216594
This update fixes several issues in the website editor, especially around image resizing, rotation, and transformation controls. It also improves editing reliability for button text and corrects Turkish e-invoice XML formatting to meet required standards.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Invoices and sales orders for foreign customers without a state now correctly use the overseas place-of-supply setting instead of the company’s Indian state. This prevents overseas transactions from being treated as domestic Indian sales, improving GST accuracy and compliance.
Original PR description
Before this PR: When creating invoices/orders for foreign customers that don't have states defined in their country, both **account.move** and **sale.order** models would incorrectly assign the company's Indian state as the place of supply. This happened because the fallback logic would always use **move.company_id.state_id** without checking if the partner was actually Indian. As a result, foreign customers would be treated as Indian customers in GST calculations, leading to incorrect tax treatment and compliance issues. After this PR: Both models now correctly identify foreign customers by checking the partner's country first, before falling back to state-based logic. Foreign customers without states are now properly assigned the foreign state reference (**l10n_in.state_in_oc**) instead of the Indian company's state. This ensures accurate GST treatment where foreign customers are correctly identified as overseas transactions. Task-4900697 Forward-Port-Of: odoo/odoo#216220
Fixed an issue where scheduled reminder emails for signature requests could crash if the request had no “Valid Until” date. This keeps reminder automation running reliably for documents that are intentionally left without an expiry date.
Original PR description
When a `sign.request` record has `validity` as `False`, attempting to send a reminder via the `_cron_reminder` method leads to a crash. **Steps to Reproduce:-** 1. Install the `Sign` module. 2.…
When a `sign.request` record has `validity` as `False`, attempting to send a reminder via the `_cron_reminder` method leads to a crash.
**Steps to Reproduce:-**
1. Install the `Sign` module.
2. Navigate to the Sign section and click on `Upload PDF & Sign`
3. Upload any PDF document and add your signature, then click `Send`
4. In the new wizard, remove the value for `Valid Until` and enable the `reminder` option. Set the reminder to `every 1 day.`
5. When our scheduled action named `Sign: Send Mail Reminder` executes the following day, it will throw an error.
**Error:-**
`TypeError(''<' not supported between instances of 'bool' and 'datetime.date'') while evaluating 'model._cron_reminder()''`
**Root Cause:-**
The SQL query within the `_cron_reminder()` method retrieves all records where:
- The request is `active` and in the `sent` state.
- Either:
- `validity < today` or
- A reminder is due based on `last_reminder + reminder`.
The fetched records are then iterated through at [1].
[1]
https://github.com/odoo/enterprise/blob/ac4aeeea98dcf2fc7f06e6a3fabc55e256330e2c/sign/models/sign_request.py#L454
If `validity` is `False`, this comparison raises a `TypeError` because it is invalid to compare a `boolean` with `datetime.date`.
**Solution:-**
- A safety check was added before the comparison between `request.validity` and today's date, ensuring that `request.validity` exists.
Sentry-6727599497Reversed point-of-sale orders are now included when preparing India GSTR-1 HSN summaries. This prevents missing product and tax details for reversals processed after session closure, improving report accuracy for compliance.
Original PR description
Before this change, HSN summary generation skipped POS reversal journal entries, which could lead to missing product and tax data for reversed orders made After the session closure. This commit improves the `_get_gstr1_hsn_json` method by: * Including reversed POS orders (`reversed_pos_order_id`) in the POS order list. * Ensuring their corresponding order lines are considered during HSN data aggregation. This ensures accurate HSN reporting even for POS reversals processed as standalone entries. OPW: 4931360
This fixes an issue where asset depreciation entries could become unbalanced when depreciation values were recalculated using a different expense account. It helps prevent accounting errors, especially in migrated databases or cases where asset expense accounts changed after entries were locked.
Original PR description
…ciation value The computation of account.move.depreciation_value is using the sum of account move lines whose account is either the expense account of the asset or an account of type expense. However, the inverse function defined on depreciation value was not considering the possibility that the move lines are using an account of type expense instead of the expense account of the asset, what ended up triggering an error in case the depreciation value had to be recomputed, because it would set the move as unbalanced.
Rental orders with multiple planned service lines now avoid assigning the same resource to overlapping shifts. If no suitable resource is available, the system creates an open shift instead, helping planners prevent scheduling conflicts.
Original PR description
Steps to Reproduce: ---------------------- - Install the sale_renting_planning module. - Create a rental service product with `Plan Services` enabled. - Create a rental order with multiple lines for the same product. - Confirm the rental order Issue: --------------------------- - You'll see that some generated shifts are assigned to same resource causing conflict. Cause: --------------------------- - Shifts are being generated at the same time for all the SOL which cause them to be assigned to the same resource and make conflict. Fix: ----------------------------- - In this commit when the shift values are generated we will check if the resources are available or not. If no resource is available then it will create open shift for that SOL. task-4829807
Loan calculations now handle unusually large borrowed amounts without showing an error traceback. This prevents disruption for accounting users who enter high-value loans and helps keep the loan setup process reliable.
Original PR description
When user tries to compute a loan for very large amount, A traceback will appear. Steps to reproduce the error: - Install ``Accounting`` module - Go to Accounting > Accounting > Loans > Create a new…
When user tries to compute a loan for very large amount,
A traceback will appear.
Steps to reproduce the error:
- Install ``Accounting`` module
- Go to Accounting > Accounting > Loans > Create a new >
Amount Borrowed: Add large number (ex. 100307634624635503132686083.9)
- Compute
Traceback:
```
File "home/odoo/src/enterprise/18.0/account_loans/wizard/account_loan_compute_wizard.py", line 115, in _compute_preview
schedule = self._get_loan_payment_schedule()
File "home/odoo/src/enterprise/18.0/account_loans/wizard/account_loan_compute_wizard.py", line 99, in _get_loan_payment_schedule
if schedule := loan.get_payment_schedule():
File "home/odoo/src/enterprise/18.0/account_loans/lib/pyloan.py", line 511, in get_payment_schedule
balance_bop = self._quantize(payment_schedule[(i + m) - 1].loan_balance_amount)
File "home/odoo/src/enterprise/18.0/account_loans/lib/pyloan.py", line 295, in _quantize
return Decimal(str(amount)).quantize(Decimal(str(0.01)))
InvalidOperation: [<class 'decimal.InvalidOperation'>]
```
https://github.com/odoo/enterprise/blob/c9701dcd384f3b4b1446dd61d73353455c2a83a8/account_loans/lib/pyloan.py#L295 Here, ``quantize`` does not support such a larger number.
So, it will lead to the above traceback.
sentry-6110624097This fix ensures Studio exports keep important customization fields that were previously excluded by default. It helps prevent incomplete exports for views, approvals, automations, attachments, and field selections, reducing the risk of missing configuration when moving Studio changes between databases.
Original PR description
If you create a **StudioExportModel** with a model that we always export (for studio customizations, i.e. ir.ui.view) then the excluded_fields field gets computed. Before this commit, the _compute_excluded_fields method of the StudioExportModel model could have excluded some fields we would like to export. This commit fixes that. **List of fields we should export but by default were excluded:** - "base.automation": "action_server_ids" - "ir.model.fields": "selection" - "studio.approval.rule": ["approver_ids", "can_validate"] - "ir.ui.view": "arch" - "ir.attachment": "datas" task-4866474
The disallowed expenses reports now assign unique identifiers to lines with no rate or a 0% rate. This prevents report failures caused by duplicate entries, helping users reliably generate these accounting reports.
Original PR description
Before this **PR**: When only the account_disallowed_expenses module was installed, the report failed with a duplicate key error if a line had a 0 rate or no rate at all. This was because such child lines were assigned the same line_id as their parent. After this **PR**: Lines with a 0 or no rate have the parent account appended to their line_id to ensure uniqueness and avoid key collisions. Forward-Port-Of: odoo/enterprise#90236