Monday, August 31, 2026
23 changes · 19.0
Resolved issues and error corrections
This update fixes several user-facing issues, including unreliable timers, broken IoT device pagination, document creation crashes, payroll leave calculations, and display problems in HR and communication tools. It also improves timesheet suggestions and restores a progress bar in manufacturing planning, helping users track work more accurately and avoid confusing interface behavior.
Italian electronic credit notes now list only the specific down payment invoice they reverse, instead of including unrelated past down payment documents or the credit note itself. This prevents inaccurate FatturaPA XML references and reduces the risk of confusion or compliance issues in Italian invoicing workflows.
Original PR description
Steps to reproduce: - Create a sale order with a down payment term. - Invoice the down payment (down payment invoice A). - Credit that down payment invoice directly (credit note A), without…
Steps to reproduce: - Create a sale order with a down payment term. - Invoice the down payment (down payment invoice A). - Credit that down payment invoice directly (credit note A), without reconciling it with anything else. - Generate the FatturaPA XML for credit note A. - Observe that DatiFattureCollegate lists both down payment invoice A and credit note A itself, instead of only down payment invoice A. On an order with several down payment invoices/credit notes over time, every one of them is listed instead of just the document the current credit note actually reverses. Cause of the issue: _l10n_it_edi_export_data built downpayment_moves from self.invoice_line_ids._get_downpayment_lines().move_id with no filtering. _get_downpayment_lines() (sale override) returns every invoice line ever created against the same down payment sale order line, across the whole life of the order, not just the invoice the current document actually relates to. The template renders DatiFattureCollegate for every one of those moves unconditionally, on top of the already-correct reversed_entry_id/reconciled_moves fallback, including the current document itself. Solution: Restrict downpayment_moves to lines with a negative price_subtotal, mirroring the existing down payment deduction-line detection a few lines above, and explicitly exclude the current document. This limits DatiFattureCollegate's down payment entries to the case they are meant for: a final invoice actually deducting a previously invoiced down payment. opw-6429716 Forward-Port-Of: odoo/odoo#281355 Forward-Port-Of: odoo/odoo#279938
Clearing an internal note on a restaurant point-of-sale order line now updates the existing preparation display item instead of cancelling it and creating a new one. This prevents kitchen staff from seeing the same quantity as a fresh order and accidentally preparing it twice.
Original PR description
Steps to reproduce ------------------ 1. Open a restaurant PoS with a preparation display. 2. Add a product, put the internal note "A" on the line, press Send. 3. Change the note from "A" to "B", then open the note again and click "discard", that will clear it. 4. Press Send. -> The line is fully cancelled on the preparation display and the same quantity is sent again as a new order. Expected Behavour ----------------- The existing line should be updated in-place instead of cancelling and re-creating a new one. Why it's happening ------------------ In `_process_preparation_changes` we calculate a key for every line and the `note` is inside this key. For the order lines we take `line.note or "[]"`, but for the note history we take `note['new'] or ''`, in that case, the keys don't match, so we cancel the current one and create a new line!! The fix ------- We use `"[]"` now, in many places (for completness), a follow up of 484ef2e8b2b. opw-6467346
Opening a page from the Website Pages list now keeps users on their current Odoo host when the page belongs to the default website. This prevents unexpected redirects to a configured real domain, avoiding login interruptions and preserving the user's context.
Original PR description
Steps to reproduce: =================== 1. Go to Website > Pages 2. Set a real domain on the default website 3. Open any page linked to that website => User is redirected to the real domain When clicking on a page linked to the default website from the Website > Pages list, if that website had a real domain configured, the action was redirecting the user to that domain instead of staying on the current host (e.g. <db>.odoo.com). since it's a different domain the user would then end up in the login page and lose the context of the page they wanted to open. Solution: ========= Now we change the behavior as requested by PO. On <domain>.odoo.com, in the Pages list view, if the page is linked to the default website, keep <domain>.odoo.com and don't redirect to the real domain => User should stay on the current host opw-6141457 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an accounting display issue where a reconciled bank transaction could hide the related vendor bill reference when exchange rate differences were involved. This helps users correctly identify matched bills during bank reconciliation, especially for foreign-currency payments.
Original PR description
In the bank reconciliation widget, a reconciled transaction matched with a bill and a loss exchange entry no longer displays the bill reference next to the reconciled line. Steps to reproduce: - Have…
In the bank reconciliation widget, a reconciled transaction matched with a bill and a loss exchange entry no longer displays the bill reference next to the reconciled line. Steps to reproduce: - Have company currency USD and foreign currency EUR - Create a vendor bill in foreign currency (100 EUR, rate 1 USD = 1 EUR) - Create a bank transaction in the foreign currency for less than the bill total, at a rate making the amount higher in company currency (90 EUR, 108 USD at 1 EUR = 1.2 USD) - Open the bank reconciliation widget, reconcile transaction and bill - Unfold the reconciled transaction Issue: A bill reference is missing Analysis: The exchange difference line is reconciled with the transaction line. Being reconciled with two lines (bill and exch), the widget relies on `*_reconciled_lines_excluding_exchange_diff` to show the fields. However, `count_reconciled_lines_excluding_exchange_diff` has been defined as boolean instead of int, faulting the comparison. opw-6479015
Argentinian electronic invoices can now be printed when an export customer uses a generic identification type without an ARCA code. This prevents printing failures for affected foreign customer invoices and adds coverage to avoid the issue returning.
Original PR description
## Description Printing any posted electronic invoice whose commercial partner has an identification type **without** ARCA code (typically the generic `VAT` type from `l10n_latam_base`, common on…
## Description
Printing any posted electronic invoice whose commercial partner has an identification type **without** ARCA code (typically the generic `VAT` type from `l10n_latam_base`, common on foreign partners of export invoices) crashes:
```
File ".../l10n_ar_edi/models/account_move.py", line 161, in _compute_l10n_ar_afip_qr_code
data.update({'tipoDocRec': int(rec._get_partner_code_id(commercial_partner_id))})
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
```
## Steps to reproduce
1. Install `l10n_ar_edi`.
2. Create a customer: Country **Spain**, Identification Type **VAT** (no ARCA code), Identification Number `ESA12345674`, ARCA Responsibility Type **Cliente / Proveedor del Exterior**.
3. Create and validate an invoice for this customer on an export electronic journal (document type 19).
4. Print the invoice → traceback above.
## Root cause
Since bb8e6fda72ae6364cf7806acb400b071f4108fc9 ([FIX] l10n_ar_edi: return the correct ARCA code when final consumer, odoo/enterprise#106881), `_get_partner_code_id()` lost its final `return partner_id_code` fallback: when the identification type has no ARCA code and the partner is not a Final Consumer, the method now returns an implicit `None`. The QR code compute casts the result with `int()`, which accepted the previous falsy return (`int(False) == 0`, rendering `tipoDocRec: 0` as in 17.0/18.0) but raises on `None` — making every such posted invoice impossible to print.
## Fix
Restore the fallback return so the method always returns the identification type code (possibly falsy) instead of an implicit `None`. The intent of bb8e6fda72ae is preserved: a Final Consumer with an identification number still gets its real code, and the other callers already handle falsy values (`partner_id_code or 0`).Nilvera refund documents for Turkish e-invoicing are now recognized as refunds even when they are sent with positive amounts. When possible, the imported refund is also connected to the original invoice, improving accounting accuracy and traceability.
Original PR description
# Description of the issue/feature this PR addresses: Nilvera can send refund documents as Invoice with refund-specific InvoiceTypeCode values. # Current behavior before PR: The default UBL import logic only treats an Invoice as a refund when its amount is negative. As a result, Nilvera refund documents sent as Invoice with positive amounts are imported as invoices. Also, imported refunds are not linked to their original invoice. # Desired behavior after PR is merged: Nilvera refund documents using refund-specific InvoiceTypeCode values are imported as refunds. When a unique match is found, the imported refund is linked to its original invoice through reversed_entry_id. task-id-5948275 I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Belgian payroll now avoids incorrectly paying a public holiday when it falls at the start of a renewed sickness certificate after the guaranteed salary period has ended. This helps ensure employees on long-term sick leave are paid according to the correct legal payroll rules and prevents overpayments.
Original PR description
Steps to reproduce: - Employee sick long-term, medical certificate renewed month by month. - Guaranteed salary period (30 days) already over. - Compute payroll for a month whose public holiday falls on day 1 of a new certificate. - That holiday is paid. Every other day that month is correctly unpaid. Cause: the 30-day lookback in _get_leave_work_entry_type_dates compared exact datetimes, not dates. A certificate starting the same day as the holiday, just later in the clock, got excluded from the lookback. The holiday then fell back to its default paid type. Fix: compare by calendar date instead, in both the lookback query and its day-coverage loop. Added a regression test for the split-certificate case. Task 6512860
This fixes week calculations so a Monday week start is correctly respected even when the user's locale normally starts weeks on another day. It prevents weekly work hours from being split across the wrong weeks, helping scheduling limits apply to the correct days.
Original PR description
**Description of the issue/feature this PR addresses:** `weeknumber` takes a `first_week_day` override, documented as `(0 = Monday, ..., 6 = Sunday). If None, derived from the locale.`, but tests it…
**Description of the issue/feature this PR addresses:** `weeknumber` takes a `first_week_day` override, documented as `(0 = Monday, ..., 6 = Sunday). If None, derived from the locale.`, but tests it with `if not first_week_day`, so Monday (`0`) is discarded and the locale's own day is used. `resource` passes `int(get_lang(self.env).week_start) - 1`, which is exactly `0` for Monday, at three call sites. #259600 added the parameter for the opposite case, a Monday locale with a Sunday-start user, and that direction works; this one never has. **Current behavior before PR:** With `en_US` (first day Sunday) and week start set to Monday, `resource_resource.py:299` builds `week_start_date` from Monday while `:303` buckets by Sunday. Monday 2026-08-24 to Sunday 2026-08-30 comes back as W35 for six days and W36 for the Sunday, so one week's hours are split across two buckets and the `hours_per_week` cap lands on the wrong days. **Desired behavior after PR is merged:** The override is honoured and those seven days are all W35. I checked this with a partition property: every day of a `first_week_day`-aligned week must share one `(year, week)`. Over 9 locales x 7 values of `first_week_day` x 12 years, 275940 combinations, 5 locales failed and every failure was in the `first_week_day=0` bucket. After the change there are none. I also diffed every output before and after, 315360 combinations of locale, `first_week_day` and date: 4460 rows change, all of them `first_week_day=0` on a non-Monday locale. `None` and values 1 to 6 are byte identical, so the change is contained to the broken case. Targeting 19.0 because that is the oldest branch carrying the parameter; 17.0 and 18.0 do not have it. AI-assisted: I used Claude to sweep the parameter space and write the tests.
The property editor now stays available even when a saved relationship filter cannot be checked by the server. Users can still open, correct, or delete the affected property instead of being blocked by an error.
Original PR description
When a relational property has a domain the server cannot evaluate, opening its definition editor crashes. The editor calls search_count on that domain to show how many records match, both when it…
When a relational property has a domain the server cannot evaluate, opening its definition editor crashes. The editor calls search_count on that domain to show how many records match, both when it opens and on every later render. The server raises a ValueError and the call has no error handling, so the whole editor goes down. The bad domain stays saved on the property, so reopening the editor fails the same way and the property can no longer be edited or deleted. Wrap the search_count call in _updateMatchingRecordsCount (property_definition.js) in a try/catch and show no count when it fails. This is the only place the editor counts matching records, so guarding it here handles a bad domain from any source, the field selector or the code editor. The field selector still shows its warning on the invalid path, so the user can fix or delete the property. Steps to reproduce: 1. On a model that has a Properties field, add a Many2one property and set its Model to a model that itself has a Properties field. 2. Open the property Domain and click New Rule. 3. In the field selector pick the Properties entry, then close the selector. => An error dialog appears and the property can no longer be edited or deleted. Ticket [link](https://www.odoo.com/odoo/project.task/6101311) opw-6101311 Forward-Port-Of: odoo/odoo#281221 Forward-Port-Of: odoo/odoo#259886
Credit card and cash journals configured for file imports now show the Import File button on the Accounting dashboard. This removes confusion for users and makes file-based statement imports accessible wherever the journal type supports them.
Original PR description
The "Import File" button on the dashboard card only shows up for bank journals. Credit card journals are treated the same way as bank journals pretty much everywhere else: the dashboard card itself,…
The "Import File" button on the dashboard card only shows up for bank journals. Credit card journals are treated the same way as bank journals pretty much everywhere else: the dashboard card itself, the statements list, the "Transaction Feeds" setting on the journal form (where you can pick the file import option), and even `create_document_from_attachment` in this module, which already accepts them. So you end up with a credit card journal set to import files but nothing on its card to actually do it, and people assume the feature is simply not there. Show the button on credit card journals too. Steps to reproduce: - Install account_bank_statement_import_csv (or any other import format) - Create a "Credit Card" journal and set its Transaction Feeds to the file import option - Go to the Accounting dashboard - The bank journal card has an "Import File" button, the credit card one doesn't --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#129546
Point of Sale invoice settlements are no longer treated as new invoices when they only settle existing amounts due. This prevents validation failures and avoids creating unnecessary zero-value electronic invoice numbers in Argentina, while keeping normal sales invoicing unchanged.
Original PR description
Steps to reproduce: - Argentinean company, Responsable Inscripto (l10n_ar_pos installed) - A posted customer invoice with VAT, partially paid - In the PoS, pick the customer, "Settle invoices",…
Steps to reproduce: - Argentinean company, Responsable Inscripto (l10n_ar_pos installed) - A posted customer invoice with VAT, partially paid - In the PoS, pick the customer, "Settle invoices", select that invoice, pay the balance by bank transfer and validate Issue: Validation fails with "There should be a single tax from the "VAT" tax group per line, but this is not the case for line ..." and the settlement cannot be recorded at all. The invoice being settled is correct; the rejected line belongs to a second invoice the PoS creates for the settlement itself. Cause: `setToInvoice` already refuses to invoice a settlement, but its condition, `is_settling_account and no line`, only describes a deposit: the deposit line is added at validation. When settling a due or an invoice, `is_settling_account` stays false and the order does carry lines - the settle lines - so the guard never fires. l10n_ar_pos then sets `to_invoice` on mount, as a sale must generate an electronic document in AR, and the settle line, untaxed on purpose since it pays an existing document rather than selling anything, reaches `_check_argentinean_invoice_taxes`. Fix: Refuse the flag as well when every line is a settle line. Such an order generates an empty document - all its lines, the receivable one included, have a zero balance - so it records nothing and only consumes a document number, which in AR means an AFIP number for a zero-amount invoice. An order that also sells something keeps its invoice, since the sale still has to be reported. Reconciliation is unaffected: it happens in `_reconcile_account_move_lines` at session close, and is already covered for both invoiced and non-invoiced settlement orders. opw-6464675
Project updates now show the same accurate profitability amounts as the project dashboard, including the correct net amount still to invoice. This prevents overstated expected revenue when vendor bills or invoicing adjustments affect a project's profitability.
Original PR description
Steps to reproduce: ------------------- 1. Install sale_project and accounting. 2. Create a service product with: - Invoicing Policy: Prepaid/Fixed Price - Create on Order: Project & Task - Cost:…
Steps to reproduce: ------------------- 1. Install sale_project and accounting. 2. Create a service product with: - Invoicing Policy: Prepaid/Fixed Price - Create on Order: Project & Task - Cost: $50, Sales Price: $100 3. Create a sales order with this product, quantity = 1, and confirm it. 4. Create a vendor bill for this product with a line price of $50 (linked via analytic distribution to the project's analytic account) 5. Open the generated project's dashboard and verify that "To Invoice" shows $50 (to_bill -50 + to_invoice 100). 6. Create a project update and observe. Issue: ------ The project update total displays $100 under "To Invoice" instead of $50. Cause: ------ The project update template displays the aggregated profitability totals (`profitability['total']['revenues']` and `profitability['total']['costs']`) instead of the dedicated `to_bill_to_invoice` and `billed_invoiced` values, causing stale "to invoice" amounts to persist after invoicing. Solution: --------- Use the `to_bill_to_invoice` and `billed_invoiced` values when rendering the project update profitability report. opw-6323869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278334 Forward-Port-Of: odoo/odoo#273605
Romanian SAF-T (D406) exports now use the required file version value of 2.0 instead of 2.4.8. This helps ensure generated declarations match the expected Romanian reporting format and reduces compliance submission issues.
Original PR description
**Steps to reproduce:** - Install the `l10n_ro_saft` module and switch to the RO Company. - Navigate to Accounting > Reporting > General Ledger. - Click the gear icon > SAF-T (D406 Declaration). - Open the generated XML file and check the `AuditFileVersion` node. **Observation:** The `AuditFileVersion` node is set to `2.4.8`. **Expected behavior:** The `AuditFileVersion` node should be set to `2.0` (confirmed with the PO [1]) **Root Cause:** At [2], the `file_version` value is incorrectly set to `2.4.8` instead of `2.0`. [1]: https://www.odoo.com/mail/message/1144385840 [2]: https://github.com/odoo/enterprise/blob/ce2ad80c91aea27b143a80018aa73ed10d16cdbe/l10n_ro_saft/models/account_general_ledger.py#L179-L183 opw-6452918 Forward-Port-Of: odoo/enterprise#127935
Closing a Point of Sale session could fail when orders included both a tracked product and a kit containing that same product. The fix correctly totals quantities across matching order lines, preventing the error and allowing sessions to close normally.
Original PR description
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The…
**Step to reproduce :** 1. Create Product A and enable lot tracking for it. 2. Create a Kit product and add Product A as one of its components. 3. Go to PoS and create orders using: - Product A - The Kit product - A combination of Product A and the Kit product 4. Create three different orders with these combinations. 5. Try to close the PoS session. **Issue :** An error occurs when attempting to close the PoS session. The issue is in the pos_mrp module, specifically in the _get_lot_line_qty method. When accessing the following line: `lines_data[move.bom_line_id.bom_id.product_tmpl_id.product_variant_id.id]['order_lines'].qty` we expect order_lines to contain a single record. However, in this scenario, multiple order lines can be returned for the same product. As a result, accessing .qty directly on order_lines raises a singleton error. **Solution :** With this fix, we first retrieve the quantity from each order line and thensum the quantities together. This ensures that multiple matching order lines are handled correctly and prevents the singleton error when closing the PoS session. opw-6442765 Forward-Port-Of: odoo/odoo#284526 Forward-Port-Of: odoo/odoo#281622
Tax return workflows now only move to a paid status when that status is valid for the selected process. This prevents an error when users reply to messages on certain corporate tax return records, keeping collaboration and tax return handling uninterrupted.
Original PR description
**Steps to reproduce:** - Log in as the `Mitchell Admin` and install the `accountant` module. - Open Accounting and click `Set Period` under `Tax Returns`. - Set the `Opening Date` and apply the…
**Steps to reproduce:** - Log in as the `Mitchell Admin` and install the `accountant` module. - Open Accounting and click `Set Period` under `Tax Returns`. - Set the `Opening Date` and apply the accounting periods. - Log in as another user (e.g., Mark Demo). - Open the Accounting app and click `Tax Returns`. - In the kanban view, remove the search filter and open `Annual Closing: Corporate Tax 2026`. - From the chatter, send a message. - Log in again as the Mitchell Admin user. - Open `Annual Closing: Corporate Tax 2026`. - Click the `Reply All` icon on the message sent by the other user and click `Send`. **Error:** `ValueError: Wrong value for account.return.generic_state_review_submit: 'paid'` **Root Cause:** At [1] and [2], only the `generic_state_only_pay` and `generic_state_tax_report` workflows define `paid` as a valid state. The `generic_state_review_submit` and `generic_state_review` workflows do not include this state. When replying to a message, [3] calls the `action_send_mail` method, which eventually calls `_action_finalize_payment` at [4]. This method unconditionally sets the tax return `state` to `paid`, even for the `generic_state_review_submit` and `generic_state_review` workflows, causing an error in the `_inverse_state` method. **Fix:** This commit prevents the error by ensuring that the state is changed to `paid` only when the configured workflow supports the `paid` state. [1]: https://github.com/odoo/enterprise/blob/b89614661682ecbd131d940539aac8afdd9d7289/account_reports/models/account_return.py#L83-L95 [2]: https://github.com/odoo/enterprise/blob/b89614661682ecbd131d940539aac8afdd9d7289/account_reports/models/account_return.py#L724-L768 [3]: https://github.com/odoo/enterprise/blob/b89614661682ecbd131d940539aac8afdd9d7289/account_reports/wizard/mail_compose_message.py#L46 [4]: https://github.com/odoo/enterprise/blob/b89614661682ecbd131d940539aac8afdd9d7289/account_reports/models/account_return.py#L1461-L1465 opw-6404112
Maintenance requests now create follow-up activity deadlines based on the user's local timezone instead of UTC. This prevents scheduled work from appearing due a day early for users in timezones far ahead of UTC, improving planning accuracy.
Original PR description
Steps to reproduce: =============== - Install `maintenance` module - Set your user's timezone to Pacific/Auckland (UTC+12/+13). - Go to Maintenance > Maintenance Requests > New. - Set the Scheduled…
Steps to reproduce:
===============
- Install `maintenance` module
- Set your user's timezone to Pacific/Auckland (UTC+12/+13).
- Go to Maintenance > Maintenance Requests > New.
- Set the Scheduled Date to tomorrow morning (e.g. 8:00 am).
- Save and check the auto-generated activity in the chatter.
Issue:
====
The activity generated for the maintenance request's Scheduled Date is
created with a deadline of Today instead of Tomorrow, even though the
Scheduled Date was explicitly set to Tomorrow.
Cause:
=====
`schedule_date` is a `Datetime` field, always stored in UTC. In
`MaintenanceRequest.activity_update()`, the deadline for the activity
(a `Date` field) was computed with:
```py
fields.Datetime.from_string(request.schedule_date).date()
```
`from_string()` only parses the stored value; it does not convert it
to any timezone. Calling `.date()` on it therefore truncates the raw
UTC datetime directly, ignoring the timezone of the user who picked
the date.
For a user ahead of UTC by a large enough offset (e.g. Pacific/Auckland,
UTC+12/+13), picking "Tomorrow 8:00 am" in their local timezone can
resolve to a UTC instant that still falls on Today's date (Tomorrow
8:00 local minus 13 hours lands at 19:00 UTC on Today). Truncating
that UTC value straight to a date silently shifts the deadline back
by one full day versus what the user selected.
Fix:
===
The deadline is now computed from the schedule date after converting
it to the record's (user's) timezone, using
`fields.Datetime.context_timestamp()`, instead of truncating the raw
UTC value. This fixes the reported issue for any user whose timezone
offset makes the truncation land on the wrong side of midnight UTC.
---
Note - automatic activity creation is remove from this [commit](https://github.com/odoo/odoo/commit/ab63e9709d8ea790a8a72a0a86b8bccc478c02d5) in saas-19.2
---
opw-6363868
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275330This fixes an issue that prevented non-admin users from sending Vietnam electronic invoices through SInvoice after migrating from version 18. The change restores the expected invoicing workflow while keeping sensitive company credentials restricted from normal user access.
Original PR description
### Steps to Reproduce: 1). Install l10n_vn_edi_viettel ('Vietnam E-Invoicing') module in v18. 2). Migrate the database in any version above v18. 3). AccessError will appear while generating ('Send…
### Steps to Reproduce:
1). Install l10n_vn_edi_viettel ('Vietnam E-Invoicing') module in v18.
2). Migrate the database in any version above v18.
3). AccessError will appear while generating ('Send to SInvoice') on invoice for non-admin users.
### Issue:
- In v18, users were able to send and generate documents via (Send to SInvoice). Since v18.1 onwards, field access [check] is enforced during this flow, and since `l10n_vn_edi_username` is restricted to admin users only [here], non-admin users hit an AccessError as soon as
`_l10n_vn_edi_get_credentials_company` reads this field on`res.company`.
```py
You do not have enough rights to access the field "l10n_vn_edi_username" on Companies (res.company). Please contact your system administrator.
Operation: read
User: 12
Groups: allowed for groups 'Role / Administrator'
```
### Solution:
- This commit fixes the issue by adding a `sudo()` call on the company inside [_l10n_vn_edi_get_credentials_company] itself, so that non-admin users can successfully send and generate documents like in the previous version, without any hassle.
[check]: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/odoo/orm/models.py#L3384
[here]: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/l10n_vn_edi_viettel/models/res_company.py#L9
[_l10n_vn_edi_get_credentials_company]: https://github.com/odoo/odoo/blob/ecc267a231958c2dd99a7287c6bd1adbdbd22965/addons/l10n_vn_edi_viettel/models/account_move.py#L885
Ticket [link](https://www.odoo.com/odoo/project.task/6434854)
opw-6434854
Forward-Port-Of: odoo/odoo#281396The Planning auto-plan action now works when open shifts include different roles. This prevents an error that blocked scheduling for employees assigned to multiple planning roles, making workforce planning more reliable.
Original PR description
Currently, using the 'Auto Plan' feature on several open shifts that have different roles raises an error. ### Steps to reproduce: - Install Project Planning (`project_forecast`) with demo data. -…
Currently, using the 'Auto Plan' feature on several open shifts that have different roles raises an error. ### Steps to reproduce: - Install Project Planning (`project_forecast`) with demo data. - Create an employee and in the settings tab under planning section assign multiple roles to that employee. - Navigate to Planning app, remove all filter and search for this employee. - Click on Actions>Auto Plan ### Error: ``` ValueError: Expected singleton: planning.role(2, 4, 3, 6, 1) ``` ### Root Cause: Since [commit](https://github.com/odoo/enterprise/pull/122035/changes/cccee5bc7da8195fa65dad0dbf65709c929c3fdf), `_get_open_shifts_resources` builds one domain for the whole batch of open shifts being planned. `self.role_id` is a mapped field over that whole recordset, so when the shifts span more than one role it returns several planning.role records. Accessing `.id` on that multi-record recordset raises "Expected singleton" instead of the intended list of role ids. ### ref: https://github.com/odoo/enterprise/blob/cebef1c1e364ec2dea0de3a4fd72a32c65116620/project_forecast/models/planning_slot.py#L109 ### Fix Use `self.role_id.ids` so the domain works with any number of distinct roles among the open shifts, matching how `project_id` is already handled in the same domain. **opw-6484707**
The Uzbek balance sheet now includes current year profit or loss in the equity section. This keeps the report balanced and accurate before and after year-end closing, supporting more reliable statutory financial reporting.
Original PR description
The Uzbek balance sheet was unbalanced because the current year's profit/loss was not included in the Equity section, even though it is part of the official report structure. This commit adds a dedicated 'Current Year Earnings' report line, computed from the current fiscal year's income, expense and equity_unaffected accounts. This ensures the balance sheet correctly reflects the current year's result both before and after the year-end closing process. The new line is also included in the Total Equity computation, and the displayed formula in the report label is updated accordingly. see https://github.com/odoo/odoo/pull/280594 task-6361059
The Uzbekistan accounting setup now classifies current-year and period profit accounts correctly so they are counted only once in the balance sheet. This prevents overstating the Equity section and improves the accuracy of local financial reports.
Original PR description
Accounts 8710 (Current Year Profit/Loss) and 9910 (Net Profit for the Period) were equity_unaffected, causing their balances to be picked up both by the retained earnings tag-based formula and by the current-year-earnings domain formula in l10n_uz_reports, double- counting them in the balance sheet's Equity section. This commit changes both accounts' type to Equity and adds the BS Line 0540 tag to 9910 (8710 already carried it), so their balances are captured through the tag alone. see https://github.com/odoo/enterprise/pull/123845 task-6361059
Confirmed sales order reports will no longer show optional products that the customer did not choose after a migration to Odoo 19. This keeps printed sales documents accurate by showing only selected optional items with a quantity above zero.
Original PR description
Steps to Reproduce: 1. Create a sale order in v18. 2. Add optional products to the quotation. 3. Keep the sale order in Quotation state. 4. Migrate the database from v18 to v19. 5. Open the migrated…
Steps to Reproduce: 1. Create a sale order in v18. 2. Add optional products to the quotation. 3. Keep the sale order in Quotation state. 4. Migrate the database from v18 to v19. 5. Open the migrated sale order in v19. 6. Confirm the sale order. 7. Print the sale order report. Current Result: All optional products, including the products that were not selected by the customer, are displayed in the confirmed sale order report. Expected Result: Only the products selected by the customer should be displayed in the confirmed sale order report. https://github.com/user-attachments/assets/e91479c1-0313-4d43-9f38-184ecc67d437 Unselected optional products should be hidden. Cause: In v18, optional products were stored in the `sale.order.option` model. During the migration to v19, the `sale.order.option` model is [removed](https://github.com/odoo/upgrade/blob/7318af8e1754efddbadfa30cd7a33b66668cb8dd/migrations/sale_management/saas~18.5.1.0/post-migrate.py#L175) and its records are migrated to `sale.order.line`. As a result, regular sale order lines and optional products are now stored in the same `sale.order.line` model with is_optinal = True. The report was not handling these migrated optional product lines correctly, so unselected optional products were also included in the confirmed sale order report. Fix: Hide optional products with zero quantity from confirmed sale order reports. Selected optional products with a quantity greater than zero are still displayed. upg - 4610921 opw - 6481753 [here]: https://github.com/odoo/upgrade/commit/ef8a887780a007b3fb890803e6e3938a7915a50b [here]: https://github.com/odoo/enterprise/commit/d6231bacb840b85c8ab8d22e00e8f5be7e5c0941 [here]: https://github.com/odoo/odoo/commit/5f4db1d08a9aec7bd4f2a168e279bf5b719592a3 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
This fixes a Microsoft Calendar sync issue where updating one moved occurrence in Outlook could incorrectly recreate the whole recurring series in Odoo. Individual changes such as adding an attendee now stay limited to the intended event, while real recurrence pattern changes still update the series.
Original PR description
The stored rrule of a recurrence embeds a DTSTART line based on the recurrence dtstart (the smallest start among its events). When the first occurrence is moved in Outlook, the Odoo dtstart no longer…
The stored rrule of a recurrence embeds a DTSTART line based on the recurrence dtstart (the smallest start among its events). When the first occurrence is moved in Outlook, the Odoo dtstart no longer matches that DTSTART, but the stored rrule is not recomputed at that point (it only depends on the pattern fields). On a later sync touching the seriesMaster (e.g. after adding an attendee to the moved occurrence), the recurrence values are written again and the rrule is reserialized with a DTSTART based on the moved occurrence. _write_from_microsoft() took this new rrule string as a pattern change and reapplied the recurrence: all occurrences were deleted and recreated as copies of the moved one, spreading its specific data (e.g. the newly added attendee) to the whole series. Ignore the DTSTART line when comparing the rrule before and after the write: a DTSTART-only difference does not reflect any pattern change in Outlook. An actual pattern change (FREQ, UNTIL, INTERVAL, ...) still reapplies the recurrence as before. Steps to reproduce: 1. In Outlook, create a recurring event 2. In Odoo, run the calendar sync 3. In Outlook, move the first occurrence of the recurrence (shift its start and stop time by 30 minutes) 4. In Odoo, run the sync 5. In Outlook, add an attendee to that same first occurrence 6. In Odoo, run the sync All the occurrences are deleted and recreated as copies of the first one, and the attendee ends up on every occurrence instead of one. opw-5129848 Forward-Port-Of: odoo/odoo#284747 Forward-Port-Of: odoo/odoo#269549