Monday, September 7, 2026
72 changes · master
New functionality added to Odoo
Companies using Turkish Nilvera e-invoicing can now define multiple invoice series on a single journal and apply them based on customer, invoice scenario, invoice type, exports, or credit notes. This reduces unnecessary journal setup while keeping invoice numbering aligned with different business processes.
Original PR description
In Türkiye, companies commonly use a different invoice series for each business process: invoice type, branch, or customer. A journal carries a single sequence, so getting a second series means creating a second journal purely to renumber, which inflates the configuration for no accounting reason. This commit adds an "e-Document Sequences" list on the journal. Each line pairs a series code with the invoice characteristics it applies to: customer, GİB scenario, GİB invoice type, product export invoice and credit note. When an invoice matches every condition of a line, the series code is used instead of the journal's code. task-6316156 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
Enhancements to existing features
Employees and payroll users now see a warning on time off records that points them to the payslip needing correction. This helps payroll teams resolve time off adjustments more directly, while removing an unnecessary payslip status field from the time off view.
Original PR description
-Warning has been introduced on the timeoff form view, to redirect to the payslip to be corrected. -"payslip_state" has been removed from the timeoff view.
Resolved issues and error corrections
The website shop header now uses the already saved cart quantity when available instead of reloading the full cart each time. This avoids unintended cart resets or recovery actions while customers are browsing or completing payment, improving checkout reliability.
Original PR description
`header_cart_link` computed the badge quantity with `request.session.get('website_sale_cart_quantity', request.cart.cart_quantity)`. Python evaluates the default argument unconditionally, so every render resolved `request.cart` even when the quantity was already cached in the session. Resolving the cart runs `_get_and_cache_current_cart`, which can mutate the session (cart reset, abandoned-cart recovery) as a side effect of merely rendering the header.
Read the cached quantity directly when the session key is present, falling back to `request.cart` only when it is absent.
This is needed for https://github.com/odoo/odoo/pull/268897 to prevent the cart from being reset while waiting for the user to do the payment.Payroll users now see a clearer warning on time off records when a related payslip needs correction, with a direct path to the payslip to update. The payroll dashboard and correction process have also been streamlined so teams can resolve time off and payslip issues more easily.
Original PR description
-Warning has been introduced on the timeoff form view, to redirect to the payslip to be corrected. -"payslip_state" has been removed from the timeoff view. -UX changes in the payroll dashboard.
Manufacturing orders are now easier to use because the Unbuild action has been moved away from the main buttons, reducing confusion with resetting an order to draft. Stock transfers are also easier to find because the quick search now includes vendor names.
Original PR description
This improvement enhances the manufacturing and stock user experience by: - Moving the Unbuild button to the cog menu of the MO form view to avoid confusion with the Reset to Draft action. - Updating the Transfer quick search filter in stock.picking to also consider the vendor name, making it easier to find transfers related to a specific vendor. Task iD- 6460372 Enterprise PR: https://github.com/odoo/enterprise/pull/128087
Manufacturing users get a clearer experience in ECO approvals, planning schedules, and work order lists. The approvals section now has more room, planning opens with fewer visual distractions, and work order action buttons are sized more consistently.
Original PR description
*: quality_mrp_workorder This improvement enhances the UX by: - Extending the Approvals view in ECO stages to full width for better form visibility. - Setting Show Dependencies to false by default in the Planning Gantt view for a cleaner and less cluttered view. - Fixing the Finish button size in the work order list view to ensure consistent sizing across the list view. Task Id - 6460372 Community PR: https://github.com/odoo/odoo/pull/282715
Manufacturing order overviews now include a To Replenish toggle that shows only components still needing to be ordered. This helps users quickly focus on missing supplies by hiding unrelated operations, byproducts, and already-covered components while the filter is active.
Original PR description
Users could not quickly identify components that still needed to be ordered because the MO overview displayed them alongside all other components. Add a To Replenish toggle to the top-right control panel so users can limit the overview to components whose status is To Order. This commit's changes: - Add the To Replenish toggle to ongoing manufacturing orders - Show only components whose status is To Order when enabled - Hide operations and byproducts while the filter is enabled task-5946139 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
Belgian payroll wording has been standardized so salary classifications are now consistently called salary scales across employee records, salary offers, reports, warnings, and demo data. This reduces confusion for HR users and makes payroll configuration easier to understand.
Original PR description
Harmonize the terminology used for Belgian salary scale classifications across
UI labels, views, models, salary offers, reports, data records, and test suites.
Previously, different terms ("Job Categories", "Professional Categories", and
"Category") were used inconsistently throughout the payroll configuration,
contract options, and employee views.
- Rename model `l10n_be.job.category` to `l10n_be.salary.scale`
- Rename relational field to `l10n_be_salary_scale_id` across employees, versions, and contract offers
- Rename record names in CSV data (e.g., "Category A" -> "Salary Scale A")
- Update payroll warnings, PDF reports (individual account, social balance), JS patches, and salary configurator
- Rename data, view, model, and test files to match the new nomenclature
- Update demo data and tests in dependent module `test_l10n_be_hr_payroll_account`
Task: 6475636Odoo Discuss can now use a custom call client bundle for testing alternative video call infrastructure or server updates. If no custom bundle is active, the standard built-in client continues to be used, reducing disruption while making experimentation easier.
Original PR description
Testing alternative SFU implementations (or updating the SFU with a breaking client-server API change) currently requires replacing the bundled client in the source tree. Add a config setting to provide a custom SFU JS client bundle. The bundle is stored as an attachment and replaces the default client through an `ir.asset`. When deactivated or empty, it is the built-in static bundle that is used.
The messaging menu can now combine filters from multiple features, so users see more accurate and relevant conversations without pagination issues. It also supports context-specific tabs that stay out of the global menu and counters while still loading and counting their own content correctly.
Original PR description
See individual commits for rationale. enterprise: https://github.com/odoo/enterprise/pull/130289
Project users can now open a Time by Stage report to see how long tasks spend in each stage. This helps teams spot workflow bottlenecks and better understand where project work is slowing down.
Original PR description
- added `Time by Stage` option to open the report page - create `project.task.stage.report` for the stage time calculation --- task-5139455
Serial numbers now show their delivery date in stock and field service planning screens, making it easier for teams to see when equipment was delivered. When all delivered items are returned, the delivery date is cleared so records stay accurate.
Original PR description
- show the `delivery_date` of the serial number in the `stock.lot` form, list, and kanban views - show the `delivery_date` in `planning.slot` equipment notebook - product returns make delivery date to false if the returned quantity = the delivered one --- task-5184420
The online shop now shows out-of-stock status more accurately, only marking products as unavailable when all variants are sold out. Customers are guided to available variants when possible, and unavailable products show clearer notification and wishlist actions instead of a misleading add-to-cart option.
Original PR description
**Purpose:** Out of stock was not completely managed in eCommerce. The out of stock ribbon was not reflecting correctly the status of the partially out of stock products. The notification and…
**Purpose:** Out of stock was not completely managed in eCommerce. The out of stock ribbon was not reflecting correctly the status of the partially out of stock products. The notification and wishlists buttons were inconsistents with the rest of the features. **Specification:** Shop page: - Make the out of stock ribbon appear only if all variants are out of stock. - If a product if completely out of stock, hide the add to cart button. - If a variant is still available, select the first available variant in the configurator or when clicking on the tile to open the product page. Product page: - Make the notification button replace the Add to cart button. - Rationalise the wishlist button of out of stock products. - When clicking notify me, show form to enter email if not logged in, subscribe directly if logged in Task-6026756 See also: - https://github.com/odoo/enterprise/pull/130684 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update brings Odoo's spreadsheet engine up to its latest version, including improvements that help calculations run more efficiently by limiting evaluation to valid sheet areas. It also includes internal compatibility updates that support ongoing spreadsheet reliability and maintainability.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/54a0597b26 [REL] 19.5.0-alpha.18 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/54a0597b26 [REL] 19.5.0-alpha.18 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/4f0daee34e [IMP] index: export `owlPlugins` [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/532243ce63 [REL] 19.5.0-alpha.17 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/7907b8e368 [PERF] evaluation: clip range to sheet [Task: 6483083](https://www.odoo.com/odoo/2328/tasks/6483083) https://github.com/odoo/o-spreadsheet/commit/1fe87f3046 [IMP] owl3: remove `env.getPopoverContainerRect` [Task: 6510584](https://www.odoo.com/odoo/2328/tasks/6510584) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Swiss QR invoices can now be generated even when a company or customer address is missing street or building number details, since those fields are not required in Switzerland. Users are informed with a banner in the Send & Print flow and batch processing continues for other invoices if one invoice has a QR issue.
Original PR description
In Switzerland, the street and building number is not required to generate a valid QR invoice. To minimize friction, errors are no longer raised if they are missing from the address of the company or the customer during the creation of the QR Code. Instead, an info banner is now displayed in the Send & Print popup indicating to the user that the addresses of some of the customers are missing and allow the user to browse through those customers. task-4349496 opw-4317153 Forward-Port-Of: odoo/odoo#271534
The HR app menu order has been adjusted so new companies see related onboarding areas in a more logical sequence, with Fleet and Payroll placed directly after Time Off. This makes navigation clearer during setup and supports a smoother onboarding experience for business users.
Original PR description
Reorder menu sequence values to position Fleet and Payroll directly after Time Off while maintaining increments of 5 between bounds 185-230. Sequence changes: - Appraisals: 200 -> 190 - Attendances: 205 -> 200 - Recruitment: 210 -> 205 - Referrals: 215 -> 210 - Time off: 225 -> 215 - Fleet: 220 (unchanged, now following Time Off) - Payroll: 190 -> 225 task-6482852
Accounting reports now once again let users filter for unreconciled items while keeping the existing reconciliation date logic. This makes it easier for finance teams to review open partner balances accurately for a selected reporting date.
Original PR description
Restore the unreconciled filter while continuing to use the recon_date mechanism, applying the date to date_to. task-none
Belgian payroll now handles worker terminations with updated termination fee calculations and no employer holiday pay. It also generates the dedicated holiday attestation report for workers, helping payroll teams produce the correct departure documents and amounts.
Original PR description
1. No holiday pay from the employer. 2. Generate the delicated holiday attest report for wokers. 3. Update termination fees. Task-6006190
Odoo now stops silently shortening text that is longer than an allowed field size and instead relies on database validation to reject it clearly. This improves data accuracy and makes configuration or import issues easier to detect, with country codes now explicitly limited to the standard two-letter format.
Original PR description
Do not trim the value silently when storing the value in cache. postgres already enforces the size when writing values, let it enforce that constraint. This avoids silently truncating the value. The size attribute is not deprecated as it is used for UI. https://github.com/odoo/enterprise/pull/130315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The gift card design has been refreshed to use space more effectively and stay readable in dark mode. The related PDF layout is also adjusted, and mail previews in the chatter get more room for a clearer customer-facing presentation.
Original PR description
This PR redesigns the gift card template by improving the space utilization and adding a white background to enhance readability on dark mode. It also - slightly modifies the layout of the related…
This PR redesigns the gift card template by improving the space utilization and adding a white background to enhance readability on dark mode. It also - slightly modifies the layout of the related PDF - increases the minimum width to provide more space for the mail preview in the chatter. task-6246180 | Before | After | |--------|--------| | <img width="616" height="779" alt="Screenshot 2026-06-25 at 10 53 22" src="https://github.com/user-attachments/assets/b7f05c43-aaaa-4f4f-ba5b-fa93f4aaaad2" /> | <img width="504" height="595" alt="Screenshot 2026-06-25 at 10 25 22" src="https://github.com/user-attachments/assets/19bca54b-923a-44d7-9c08-3901ff08a532" /> | |--------|--------| | <img width="448" height="720" alt="Screenshot 2026-06-02 at 10 43 53" src="https://github.com/user-attachments/assets/d5fed6d0-1d05-44a2-9bc8-090259a10291" /> | <img width="555" height="721" alt="Screenshot 2026-06-25 at 10 26 34" src="https://github.com/user-attachments/assets/8e26db94-d654-4d18-8e34-8bee277a9f44" /> | |--------|--------| | <img width="798" height="884" alt="Screenshot 2026-06-25 at 10 54 39" src="https://github.com/user-attachments/assets/54bf2940-988c-4754-8677-19bc980a6684" /> | <img width="790" height="856" alt="Screenshot 2026-06-25 at 10 26 52" src="https://github.com/user-attachments/assets/f2ca78d5-97f8-456d-9416-fbd2f680b013" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Visitors who sign in during an active live chat can now keep the same conversation instead of starting over. This improves the customer support experience by preserving ongoing and previous chat access after login, including cases where extra authentication is required.
Original PR description
*=base, mail, portal, website_livechat Before this commit, when a visitor logged in while an active livechat session was ongoing, the session was lost and the user had to start a new one. Once logged in, access is checked on `partner_id` and no longer on `guest_id`. Add a post-session-login hook that runs only after authentication is fully finalized, including MFA. im_livechat uses this hook to replace the guest members of pinned livechat sessions with the logged-in partner. This allows visitors to continue active sessions and access previous ones. When a guest is present in the user context, both the user and guest are sent to the client so that guest messages continue to be recognized as self-authored after login. task-[3957100](https://www.odoo.com/odoo/project/1519/tasks/3957100)
Belgian payroll calculations now reduce payslip amounts based on time credit, parental time off, and partial incapacity while keeping the employee's contractual wage unchanged. This improves accuracy for regular pay, holiday-related calculations, and reporting by reflecting actual working time across fixed and variable schedules.
Original PR description
**Time Credit Work Entries :-** . LEAVE300 (Credit Time) . LEAVE301 (Parental Time Off) . LEAVE281 (Partial Incapacity) ### Regular Pay :- **1. Wage proration for time credit** The `wage proration`…
**Time Credit Work Entries :-**
. LEAVE300 (Credit Time)
. LEAVE301 (Parental Time Off)
. LEAVE281 (Partial Incapacity)
### Regular Pay :-
**1. Wage proration for time credit**
The `wage proration` applies only to the payslip calculation, not to the employee's contractual wage, the employee's full-time contractual wage remains unchanged. The wage displayed on the employee's version remains the original amount agreed in the contract, where **The proration is applied only when calculating the worked days and corresponding amounts on the payslip**. This ensures that the payslip reflects the employee's actual working time while preserving the contractual wage as the reference amount.
The used range to calculate the proration ratio depends on the schedule type :-
_. Fixed Calendars:_ The proration ratio is computed using a standard 1-week period (Monday to Sunday) from the attendance schedule, as fixed schedules repeat weekly.
> Fixed Calendar Example (1-Week):
> Schedule: 4 working days (30.4h) + 1 time credit day (7.6h) = 38h total schedule
> Calculation range: 1 week
> Proration ratio: $\frac{30.4\text{ actual working hours}}{38.0\text{ total schedule hours}} = 0.80$.
> Contractual Wage: €5,000 (Unchanged).
> Prorated Payslip Amount: $€5,000 \times 0.80 = €4,000$.
_. Variable Calendars:_ The proration ratio is computed over the entire target evaluation period to accurately capture work entries, taking the full month for a monthly payslip or the full 3-quarter/3-month period for DMFA reporting.
> Schedule: Alternating shifts across a monthly payslip period totaling 152 total scheduled calendar hours, of which 38 hours are marked as time credit and 114 hours are actual working hours.
> Calculation range: Full calendar month (e.g., 1st to 30th/31st).
> Proration ratio: $\frac{114\text{ actual working hours}}{152\text{ total schedule hours}} = 0.75$.
> Contractual Wage: €5,000 (Unchanged).
> Prorated Payslip Amount: $€5,000 \times 0.75 = €3,750$.
Ex: If an employee has a contractual wage of €5,000 and their schedule includes time credit:
Employee/contract wage: €5,000 → remains unchanged
Basic wage used as the contractual reference: €5,000 → remains unchanged
Payslip worked-days amount: prorated according to the actual working time
This distinction is important because time credit changes the amount paid for the payroll period, but it does not change the employee's underlying contractual full-time wage.
**2. Version Work Time Rate**
The `work_time_rate` is computed at the employee version level, where the time-credit situation belongs to the employee's version.
The existing behavior for flexible/variable calendars is preserved, **where currently the work_time_rate not computed for variable calendars and the user is expected to enter the appropriate work_time_rate manually for the variable calendars, So the overidden work_rime_rate computation deals with the `credit_time_fixed_calendars`**
For fixed calendars with time credit, the computation is handled specifically for the employee version:
. Only versions flagged with l10n_be_time_credit and using a fixed calendar are handled by the custom computation.
. The employee's reference calendar is used to determine the full-time weekly hours.
. The calculation considers both, regular working attendances & attendances marked as time credit.
The time-credit hours are therefore included when determining the employee's work_time_rate, **But Importantly, the actual working hours of the resource calendar are not changed.**, where The time-credit attendances are included only for the purpose of calculating work_time_rate. They are not treated as actual working hours, and hours_per_week continues to represent the employee's effective working hours without the time-credit period.
Ex: For a full-time reference calendar of 38 hours:
Actual working hours: 30.4h/week
Time-credit hours: 7.6h/week
Hours considered for work_time_rate: 30.4 + 7.6 = 38h
work_time_rate: 100%
Actual working hours remain: 30.4h/week
-----
### Double Holiday :-
The Double Holiday Pay calculation requires special handling for time-credit periods because two different rates need to be considered:
. The **computed work_time_rate** that used to normalize the wage "include credit_entries"
. The **effective/real work_time_rate** used to determine the assimilated months "not include credit_entries""
The used wage is the version wage itself that's not prorated. The calculation first uses the full contractual wage **(so no need to change the wage on the tests)** and divides it by the version's current computed work_time_rate. This is important for time-credit versions because their computed work_time_rate can include the time-credit attendances.
However, when calculating the _double_holiday_assimilated_months, the time-credit periods are treated differently. The calculation uses the effective working-time rate, where regular time-credit entries are not considered as working time. The exception is `LEAVE281 (Partial Incapacity),` which is considered in the assimilated-month calculation and therefore contributes with its corresponding rate.
Ex: An Employee works with wage €2,500
. January → June with Normal Schedule
. July → September with 4/5 Partial Incapacity (LEAVE281)
. October → December with 4/5 Credit Time (LEAVE300)
The employee's version wage remains €2,500 throughout the calculation and the used work_time_rate for the wage will be the current computed work_time_rate which will be 1.0
The Double Holiday Pay calculation can therefore be represented as:
€2,500 / 1.00 × [(6 × 1.0 / 12) + (3 × 1.0 / 12) + (3 × 0.8 / 12)]
. For the wage normalization: the computed work_time_rate of the relevant version is used. This rate can include time-credit attendances.
. For _double_holiday_assimilated_months: the calculation uses the effective/real working-time rate for each period. Regular time-credit (LEAVE300) is therefore reflected as 80%, while LEAVE281 (Partial Incapacity) is treated as an assimilated period and remains at 100% in this example.
check:-
```
def _l10n_be_get_paid_double_holiday()
def _compute_double_holiday_assimilated_months()
```
-----
### Eco Voucher :-
The Eco-voucher calculation depends directly on the employee version's work_time_rate.
The voucher amount is therefore automatically updated when the work_time_rate changes. This is particularly important for time-credit versions, because the work_time_rate now correctly represents the employee's contractual occupation rate, including the relevant time-credit periods.
This means that a time-credit version does not necessarily result in a reduced Eco-voucher entitlement. In particular, when the employee is on a reduced working schedule but the reduction is entirely due to time credit, the computed work_time_rate can remain at 100%, because the time-credit periods are included when calculating the rate.
Ex: An employee is entitled to a maximum of €250 in Eco-vouchers and has the following situation during the reference period:
01/06/2020 → 31/10/2020: Full-time schedule → work_time_rate = 100%
01/11/2020 → 31/05/2021: 3/5 schedule with Tuesday and Wednesday represented as credit-time entries.
Although the employee only has 22.8 actual working hours per week, the two non-working days are explicitly represented as time credit. Therefore, for the purpose of the employee version's work_time_rate, the time-credit hours are included and the rate remains 100%.
The Eco-voucher calculation consequently uses: €250 × 100% = €250
110 valid working days during the full-time period, out of 261 scheduled days.
82 valid working days during the 3/5 time-credit period, out of 157 scheduled days, after excluding 9 unpaid-time-off days.
Therefore: €250 × 110 / 261 + €250 × 82 / 157 = €235.94
This confirms that time credit does not incorrectly reduce the Eco-voucher amount simply because the resource calendar contains fewer actual working hours. The employee's work_time_rate correctly remains 100% when the missing hours are accounted for as time credit.
check:-
`def _get_eco_vouchers_amount(self, get_explanation=False):
`
-----
### Representation Fees :-
The REP.FEES calculation depends directly on the employee version's work_time_rate. Therefore, for time-credit versions, the newly computed work_time_rate is automatically taken into account when determining the amount.
For time-credit versions, the computed rate includes the time-credit hours. Therefore, a 4/5 schedule with one full day of time credit has a work_time_rate of 100% (the 4/5 worked hours + the 1/5 time-credit hours represent the full reference schedule). As a result, the existing representation-fee proration logic is not triggered, and the full representation-fee amount is maintained.
check :-
`def _get_representation_fees(self, localdict):
`
-----
### DMFA :-
The DMFA declaration requires two separate considerations for time credit:
**. Working days,** where the employee's days_per_week is preserved and the time-credit attendances are not considered as actual working days.
This is important because the time-credit hours may be included when determining the employee's work_time_rate, but they must not be reported as worked days in the DMFA declaration, So the time credit can affect work_time_rate, but it does not create additional working days for DMFA.
**. Termination contribution type,** The contribution type is determined based on the employee's yearly salary, which is accumulated from the amounts reported on the payslip worked-days lines, The resulting yearly salary is compared against the configured salary thresholds to determine the appropriate contribution type.
Because the yearly salary is based on the actual amounts coming from the payslip worked-days lines, a time-credit period can reduce the yearly salary used for this calculation.
As a result, the employee's contribution type can legitimately move to a lower category.
check:-
```
DMFAWorkerContribution() __init__ class
yearly_salary = payslips[0]._l10n_be_get_termination_yearly_salary()
```
-----
task-5126195Field Service planning now supports an additional Urgent priority for shifts, giving teams a clearer way to flag work that needs immediate attention. The website request form also adds a Minor Impact option, helping businesses capture issue severity with more precision from the start.
Original PR description
This PR adds a new "Urgent" priority level in Field Service shifts, and a new "Minor Impact" level in the website form, to allow more granularity. Task-6486321
Subscription users can now add recurring lines using only a description, without first creating a dedicated product. These lines are included in invoicing, renewals, upsells, plan counts, and recurring revenue metrics, while existing product-based subscription lines keep their current behavior.
Original PR description
Before this commit: Subscription lines needed a product. Lines with no product were not treated as recurring, so invoicing, renew, upsell, plan counts, and MRR ignored them. After this commit: A line…
Before this commit: Subscription lines needed a product. Lines with no product were not treated as recurring, so invoicing, renew, upsell, plan counts, and MRR ignored them. After this commit: A line with only a description on a subscription with a plan is recurring. It can be invoiced, renewed, upsold (with prorata when prepaid), counted on the plan, and included in MRR. Impact: Users can build subscriptions without creating a product for every line. Product lines keep the same behavior as before. Performance: Profiler on Subscription Report (list), product only dataset on master vs this branch (2000 subscriptions) Main report query (sale_subscription_report ... LIMIT 80): - master: 58.97 ms - this branch: 59.52 ms No meaningful difference on that path. Flame graphs: Current master- <img width="1920" height="1002" alt="image" src="https://github.com/user-attachments/assets/c81fd63a-c9b7-4506-a4a8-8f04b1427549" /> PR Branch- <img width="1920" height="1002" alt="image" src="https://github.com/user-attachments/assets/9b750b14-739f-4b1c-b661-e915dac60c5c" /> Task id: 6410240
Belgian payroll reporting now includes employer-owned pool vehicles in quarterly ONSS/DMFA CO2 contribution declarations when they were used during the period. This helps companies report company car contributions more accurately and avoid double-counting vehicles already handled through employee payslips.
Original PR description
**Description :-** This PR adds support for declaring ONSS/DMFA quarterly CO₂ contributions for pool vehicles (vehicles owned by the employer that are not assigned to am employee on a contract, but…
**Description :-** This PR adds support for declaring ONSS/DMFA quarterly CO₂ contributions for pool vehicles (vehicles owned by the employer that are not assigned to am employee on a contract, but are used during the period). According to Belgian social security (ONSS) regulations, CO₂ fees must be paid for all company vehicles used during the quarter: . Assigned Company Cars: CO₂ fees are calculated and declared directly via employee monthly payslips. . Pool Cars: Must be declared at the employer level for any month in which they had active assignment/driver logs (fleet.vehicle.assignation.log) and were not already declared on an employee payslip. **Implementation :-** . Vehicles declaration on the DMFA (_compute_vehicle_ids) Retains all active vehicles with valid license plates that have driver assignment logs during the DMFA quarter. Ensures eco-friendly and pool vehicles appear under the XML <CompanyVehicle> declaration block. . Month-by-Month Vehicles Contribution (_get_vehicles_contribution) Evaluates the DMFA quarter on a per-month basis rather than applying a static quarterly multiplier. Prevents double-counting by excluding vehicles already charged via an employee payslip for a specific month (covered_vehicle_ids). Dynamically checks driver log date overlaps (date_start and date_end) per month to properly handle mid-quarter acquisitions or transitions. Evaluates CO₂ indexation parameters historically per month by passing co2_fee_date in the context (vehicle.with_context(co2_fee_date=current_month)._get_co2_fee(...)). **Example :-** > CAR-001 (Diesel, CO₂=120): ((120 * 9 - 600) / 12) * (181.93 / 114.08) * 2.75 = 175.42 > CAR-002 (Gasoline, CO₂=100): ((100 * 9 - 768) / 12) * (181.93 / 114.08) * 2.75 = 48.24 > CAR-003 (Diesel, CO₂=110): ((110 * 9 - 600) / 12) * (181.93 / 114.08) * 2.75 = 142.53 > TEST (Class Default Car): = 33.22 > Payslips CO₂ Fees: > CAR-002 on Employee Payslips (Jan & Feb): 48.24 * 2 = 96.48 > Pool Cars Monthly CO₂ Fees (Iterating Jan, Feb, Mar): > > January: > CAR-001: 175.42 > TEST: 33.22 > Subtotal Jan: 208.64 > > February: > CAR-003: 142.53 > CAR-001: 175.42 > TEST: 33.22 > Subtotal Feb: 351.17 (Cumulative pool fees: 559.82) > > March: > CAR-003: 142.53 > CAR-001: 175.42 > CAR-002: 48.24 > TEST: 33.22 > Subtotal Mar: 399.41 (Cumulative pool fees: 959.23) > > Therefore, Total Vehicles Contribution: 96.48 (payslips) + 959.23 (pool) = 1055.71 task-6147532
Belgian payroll declarations now calculate withholding-tax exemptions for eligible overtime hours and include them in the 274.XX report. This helps companies apply annual hour caps correctly across the year and gives payroll teams clearer XLS and PDF reporting, including sector-specific rules and white-cash-register settings.
Original PR description
Compute the withholding-tax exemption for overtime hours (natures 44–59) within the Belgian 274.XX declaration. Overtime worked-day lines are collected from validated payslips, bucketed by rate and sector (CP124/CP302/immovable work), and allocated to the appropriate nature codes while respecting each employee's annual hour cap. Hours already declared in earlier months of the same year are carried forward so the cap is enforced cumulatively. The exemption rate is stored as an updatable rule parameter. A white-cash-register flag on the company controls the higher cap for CP302 employees. New work-entry types, an XLS extra-hours sheet, a PDF section, and extended tests are included. Task Id: 5430988
Spanish accounting users can now choose the abbreviated accounting plan template in Odoo. This makes the appropriate reports available for companies that use this lighter version of the standard Spanish chart of accounts.
Original PR description
Description of the issue/feature this PR addresses: Add abbreviated accounting plan There is an accounting plan called abbreviated that was not there. This is very similar to full that is why it has this template as parent. Now this template can be selected and access to its reports. task-6065347
Financial reports now use the new retained earnings account category when calculating cumulative translation adjustments. This improves the accuracy and consistency of balance sheets, general ledger, trial balance, and SAF-T reporting across affected localizations.
Original PR description
This commit uses the new Equity Retained account type with average CTA. It also adds the account type in the balance sheet and in SAFT. task-6374563
This update adds an equity retained earnings account and adjusts currency translation handling in accounting reports. It helps businesses produce more accurate financial reporting, especially when consolidating or translating balances across currencies.
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
This update prevents server connection errors when many background requests happen at the same time. It helps Odoo stay responsive during busy periods, especially for live messaging and websocket-related activity.
Original PR description
make gevent connection pool non-blocking to avoid 'The Connection Pool Is Full' error when too many coroutines are borrowing connections in gevent server. https://github.com/odoo/iap-apps/pull/1827 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 Forward-Port-Of: odoo/odoo#285423
Odoo now supports Turkish workflows where an e-Archive invoice is legally used as the dispatch document, avoiding a separate e-Dispatch submission. This reduces duplicate paperwork for e-commerce, marketplace fulfillment, and third-party logistics while keeping the standard e-Dispatch process available when needed.
Original PR description
Purpose: Turkish regulations allow an e-Archive invoice to serve directly as the dispatch document, eliminating the need to send a separate e-Dispatch XML. This is commonly used in e-commerce…
Purpose:
Turkish regulations allow an e-Archive invoice to serve directly as the
dispatch document, eliminating the need to send a separate e-Dispatch XML.
This is commonly used in e-commerce marketplace fulfillment or third-party
logistics scenarios.
This commit adds support for the "Invoice Serves as e-Dispatch" workflow:
- Extend `l10n_tr_nilvera_dispatch_type` on `stock.picking` with the new
option `IS_DESPATCH` ("Invoice Serves as e-Dispatch") and update its label
to "Dispatch Handling".
- When `IS_DESPATCH` is selected on linked pickings for e-Archive invoice, skip
sending separate e-Dispatch and instead inject '<cac:AdditionalDocumentReference>'
node with `<cbc:DocumentTypeCode>IS_DESPATCH</cbc:DocumentTypeCode>`
into e-Invoice XML.
- Hide the "Send GİB e-Dispatch (XML)" and "Update From GİB e-Dispatch (XML)"
buttons when Dispatch Handling is set to `IS_DESPATCH`.
- Vehicle and carrier information is not required when Dispatch Handling is
set to `IS_DESPATCH`.
- Replace the blocking warning for invoices with linked pickings but no
e-Dispatch orders with an info message, allowing the XML to be sent without
e-Dispatch information.
- Keep the existing flow when both linked delivery and e-Dispatch orders are
provided.
task-6369988Belgian payroll now recalculates company car benefit-in-kind at year-end or when a contract ends, so employees are not overtaxed when their car changes during the year. If too much benefit was already taxed because of monthly minimums, the system automatically applies a regularization to correct it.
Original PR description
**Description :-** The payroll system currently applies a minimum legal yearly BIK/ATN for company cars. So even if the employee’s theoretical calculated car benefit is lower than the legal minimum,…
**Description :-**
The payroll system currently applies a minimum legal yearly BIK/ATN for company cars.
So even if the employee’s theoretical calculated car benefit is lower than the legal minimum, payroll still taxes the employee on the legal minimum.
That is correct as long as the employee keeps that same car all year,
But if later in the same year the employee changes to a another car, with a lower or a bigger BIK, In that case, the employee may already have paid too much earlier in the year because the minimum was applied month-by-month indirectly.
So, in December, or in the Month that the contract ends, must:
1. recompute the true yearly ATN
2. compare it with what was already paid
3. refund/deduct the excess if too much ATN was charged.
. Add a salary rule to calculate the regularization amount in case of employee have paid too much for the car bik, which applied in December, or in the Month that the contract ends,
**Implementation :-**
. Min legal car ATN: this's minimum yearly ATN that need to be paid.
. Yearly Theoretical ATN: This's the sum of the real BIK calculated from the car formula without applying the min legal car atn per month
. Yearly ATN paid: this's the sum of ATN paid on the payslips during the year
∴ Yearly ATN to pay = MAX( Min legal car ATN, Yearly Theoretical ATN)
∴ Regularization amount = Yearly ATN to pay - Yearly ATN paid
If +ve ,then employee paid less and owes more ATN **(not our case)**
If -ve ,then employee paid too much and need to refund
**Example :-**
min_car_atn = 1,690€ / year _(in 2026)_
car1 (Volkswagen/Golf 8) from January to June:
car_value = 38,000 €
yearly_theoretical_atn = 1,938 €/year
yearly_paid_atn = 1,938 €/year
car2 (Nissan) July to December::
car_value = 20,000 €
yearly_theoretical_atn = 1,371.43 €/year
yearly_paid_atn = 1,690 €/year
Calculations:
∵ monthly_car_atn is calculated based on the month calendar days so need to get the car covered assignment on days
∵ car1 covered_days = 181 days
∵ car2 covered_days = 184 days
∴ Yearly Theoretical ATN = 1,938 * (181 / 365) + 1,371.43 * (184 / 365)
= 1,652.39 €
∴ Yearly ATN to pay = Max(min_legal_car_atn, yearly_theoretical_atn)
, where it's the final ATN that should have been paid after applying the legal minimum.
= Max(1,690, 1,652.37) = 1,690 €
∵ Yearly ATN paid _(payslips)_ =
car1 -> (1,938/365) * (31 + 28 + 31 + 30 + 31 + 30) = 961.035616438 €
car2 -> (1,690/365) * (31 + 31 + 30 + 31 + 30 + 31) = 851.945205479 €
= 1,812.98 €
∴ Regularization amount = yearly_atn_to_pay - yearly_atn_paid
= 1,690 - 1,812.97
= -122.97 €
**∴ Need to refund 122.97 € to the employee**
**Example :-**
min_car_atn = 1,690€ / year _(in 2026)_
Car 1 (Corolla) Jan-Jun:
Yearly Theoretical ATN = 1,748.57€
Yearly Paid ATN = 1,748.57€
Car 2 (Clio) Jul-Nov:
Yearly Theoretical ATN = 1,371.43€
Yearly Paid ATN = 1,690€
>>The contract end at 30th November
Calculations:
∵ monthly_car_atn is calculated based on the month calendar days so need to get the car covered assignment on days
∵ car1 covered_days = 181 days
∵ car2 covered_days = 152 days
∴ Yearly Theoretical ATN = 1,748.57 * (181 / 365) + 1,371.43 * (152 / 365)
= 1,438.215 €
∵ The regularization will be applied till the contract end not the full year, so the min_legal_car_atn will be prorated
∴ min_atn_prorated = 1,690 * ((181 + 152) / 365)
= 1,541.8356 €
∴ Yearly ATN to pay = Max(1,541.8356, 1,438.215) = 1,541.8356 €
∵ Yearly ATN paid (payslips) =
car1 -> (1,748.57/365) * (31 + 28 + 31 + 30 + 31 + 30) = 867.11 €
car2 -> (1,690/365) * (31 + 31 + 30 + 31 + 30 + 29) = 571.12 €
= 1,570.87 €
∴ Regularization amount = 1,541.8356 - 1,570.87
= -29.03 €
∴ Need to refund 29.03 € back to the employee
**Tests :-**
. Payslip Simulation for December & Termination Tests:
Updated all test cases covering December payslip computations and mid-year contract terminations
(e.g., test_274_declaration_december, test_end_of_contract, test_simple_n_holiday_pay_recovery_higher_salary)
to ensure that fully validated payslips exist for all preceding months of the active fiscal year, where The `ATNCARREGUL` salary rule computes regularization by inspecting historical payslips (_get_line_values / cumulative paid BIK from January up to the current month), so December or exit payslips in isolation without prior validated payslips skews the total paid BIK (atn_paid_before_current_payslip), which does not accurately reflect a real-world payroll state.
check:-
`def _get_holiday_pay_recovery()
`
. Updated Assertions (M.ONSS):
Adjusted expectations for year-to-date-dependent lines, for special ONSS contributions (M.ONSS) across these specific tests. **Because previous months' payslips are now added, processed and validated sequentially, which reflect exact real-life behavior.**
check:-
`def _l10n_be_get_special_social_contribution()
`
. Updated 274_xx december declarations
Make sure that the payslips are computed and validated **sequentially**, where all payslips from January through November is computed first then December payslips,
Before M.ONSS computed for December first which leads to Zero values, that makes taxable_amount_10 & pp_amount_10 not correct, **But now payslips are now processed and validated sequentially, which reflect exact real-life behavior.**
check:-
`def _compute_line_ids(self): "l10n_be_274.xx"
`
`def _l10n_be_get_special_social_contribution()
`
-----
task-6197625The salary configurator now prevents employees or candidates from selecting both a company car rental option and reimbursement for using a private car. When one option is selected, the other is reset and disabled, helping avoid incompatible benefit combinations and payroll mistakes.
Original PR description
In order to safe gaurd from employees (or candidates) from selecting both options for renting a company car and getting reimbursed for their private cars, the salary configurator now resets and disables one of the benefits if the other is selected. Task: 6515172
Payroll screens and reports now use the clearer term "Payslip Adjustment" consistently instead of "Salary Adjustment". The related forms and list views have also been simplified, making payroll adjustments easier for users to understand and manage.
Original PR description
- Updated all instances of "Salary Adjustment" to "Payslip Adjustment" across models, views, and reports for consistency. - simplify UI/UX across all form, list views Task: 6416223
Odoo no longer uses database-level text length limits for character fields, avoiding cases where values could be silently shortened and later produce confusing search or filter results. Length limits can still guide the user interface, while important business rules such as two-letter country codes are enforced explicitly with clearer validation messages.
Original PR description
Having a size of varchar is leading to subtle inconsistencies: silently truncating the value. For example, if size=2, you could insert "ABC" and a search with "ABF" would match that record, but filtering would match nothing. The property was already marked as deprecated. This change removes it. In terms of storage, this has no impact. https://github.com/odoo/enterprise/pull/129766 https://github.com/odoo/upgrade/pull/11134 https://github.com/odoo/upgrade-util/pull/505 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update brings Odoo's spreadsheet component up to the latest version. It improves spreadsheet calculation performance by limiting evaluations to relevant sheet ranges and includes internal compatibility updates that help keep the feature reliable.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/532243ce63 [REL] 19.5.0-alpha.17 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/532243ce63 [REL] 19.5.0-alpha.17 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/7907b8e368 [PERF] evaluation: clip range to sheet [Task: 6483083](https://www.odoo.com/odoo/2328/tasks/6483083) https://github.com/odoo/o-spreadsheet/commit/1fe87f3046 [IMP] owl3: remove `env.getPopoverContainerRect` [Task: 6510584](https://www.odoo.com/odoo/2328/tasks/6510584) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Copying existing attachments is now faster because the system reuses known file information instead of recalculating it. This reduces waiting time when duplicating large files and improves performance for workflows that copy attachments often.
Original PR description
Do not recompute the checksum and lookup indexed content if we copy an already known file.
Creation of an attachment of 100Mo takes approximately 3s. This reduces the copy less than 1s is the indexed content is huge and to a few milliseconds if it's small.
```py
att = env['ir.attachment'].create({'name': 'a.csv', 'raw': BinaryBytes(b'a,b,c,d,e,f,g\n' * 2000000)}) # 1.25s
att.copy() # before: 1.25s; after: 0.25s
```
task-2630381
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prSaudi companies will now keep global tax rounding enabled automatically, reducing the risk of accidental configuration changes. This helps maintain compliant and consistent tax calculations for Saudi localization users.
Original PR description
- Force "Round Globally" on Saudi companies to prevent accidental changes. task-6377776 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
Pricing rules that previously used percentage-based discounts now use the newer formula-based approach while keeping the same discount values. This keeps product, rental, subscription, point of sale, and website pricing behavior consistent after the old method was removed.
Original PR description
Follows the removal of the percentage price method. Rules defined with 'percentage' and a `percent_price` are redefined as 'formula' with the same value in `price_discount`, and the checks deciding whether a price can be shown as a discount now call `_is_plain_discount_rule`. See: - https://github.com/odoo/odoo/pull/273685
Belgian payroll worker code names have been simplified so users can find and select the right option more easily. The full official wording is still kept separately for reference, reducing clutter in daily payroll workflows without losing important details.
Original PR description
DMFA worker code names were overly long and detailed, making selection cumbersome for users in payroll workflows. Move the long official descriptions to a new `description` field on `l10n.be.worker.code` and update `name` with concise short names. Task: 6514465
Large Italian electronic invoices now import much faster by processing invoice lines more efficiently and reducing repeated checks. This can significantly shorten waiting times for businesses handling invoices with many lines, especially in accounting workflows.
Original PR description
### Description: When importing a large invoice, the process can take a lot of time. This is caused by how `l10n_it_edi` handles the creation and writing of each line of the bill. To improve performance, most of the process is now performed in memory and record creation is deferred to a single batch at the end. Additionally, the check related to `account_accountant` is cached to avoid superfluous calls. ### Benchmark: **For `history.limit`[^1] of 50 (= 21002 `account.move.line`):** | Invoice lines | Before | After | Speedup | |---------------|----------|---------|---------| | 33 | 4.75s | 2.23s | 2.1× | | 172 | 2.3min | 45.1s | 3.1× | | 1,934 | 44.4min | 6.8min | 6.6× | [^1]: System parameter `account.bill.predict.history.limit` ### Reference: opw-5937519 Forward-Port-Of: odoo/odoo#286357 Forward-Port-Of: odoo/odoo#282880
Bill field suggestions now run more efficiently on databases with many accounting entries. This improves responsiveness when processing supplier bills, especially in Peppol workflows where product, account, and tax matching is used frequently.
Original PR description
### Description: Predicting fields can be slow when the database has a large amount of move lines (AML). This is caused by the fact that `_predicted_field` will search on all these AMLs to find the…
### Description: Predicting fields can be slow when the database has a large amount of move lines (AML). This is caused by the fact that `_predicted_field` will search on all these AMLs to find the ones related to the searched fields. It can be an issue when using Peppol since it is used a lot in most localizations to match each line to its product/account/tax. To speed up the queries, the move IDs have been inlined in `_build_predictive_query` to avoid suboptimal execution plans caused by LIMIT and ORDER BY clauses. Additionally, materialization of the `account_move_line` CTE has been removed so the planner can inline filters and stream rows directly, which improves performance in most use cases. ### Benchmark: **For a `history.limit`[^1] of 100:** | Nb of invoice line | Before | After | AMLs scanned | |--------------------|-----------|---------|--------------| | 33 | 7s | 4s | 232 | | 172 | 11.39min | 5min | 99859 | | 1934 | 3h+ [^2] | 1h40min | 102503 | **For a `history.limit`[^1] of 50:** | Nb of invoice line | Before | After | AMLs scanned | |--------------------|---------|---------|--------------| | 33 | 6s | 4s | 187 | | 172 | 2.52min | 1.27min | 21002 | | 1934 | 40min | 20min | 21002 | [^1]: System parameter `account.bill.predict.history.limit` [^2]: Stopped manually after 3h; full runtime not measured ### Reference: opw-5937519 Forward-Port-Of: odoo/enterprise#130242 Forward-Port-Of: odoo/enterprise#128172
Marketing Automation now includes a Templates area for saving, finding, and reusing favorite marketing emails. Users can create email activities from scratch or start from an existing template, making campaign setup faster and more consistent.
Original PR description
This commit includes the `mass_mailing`'s mailing **templates** in the `marketing_automation` app.
This fix validates key French Flow 10 e-invoicing report fields before sending them to the public platform. It helps prevent full report rejections by flagging affected journal entries when text, tax, company, or address values do not meet required limits.
Original PR description
Some Flow 10 values are generated without applying the length and format constraints expected by the PPF. Long free-text values, oversized VAT numbers, and invalid address data can therefore cause an entire report to be rejected. Limit product names and invoice notes to their allowed lengths and normalize country codes. Validate the declarant SIREN, VAT number lengths, and address values before sending so affected journal entries are marked as errors and excluded from the report. No Task id Forward-Port-Of: odoo/odoo#286887 Forward-Port-Of: odoo/odoo#286536
Internal users assigned to tasks in invitation-only projects can now open their assigned task links without being blocked by project-level access errors. The fix preserves project privacy, so users can access only the task they are assigned to without exposing other project tasks.
Original PR description
Issue: Internal users assigned to a task in an "Invited internal users" project can read the task but may receive an access error when opening it. Adding them as project followers avoids the error…
Issue: Internal users assigned to a task in an "Invited internal users" project can read the task but may receive an access error when opening it. Adding them as project followers avoids the error but also exposes the project's other tasks. Steps to reproduce: - Set a project's visibility to "Invited internal users". - Assign an internal Project user to one of its tasks. - Keep the user out of the project's followers. - Open the assigned task through its access link. Cause: The task form loads feature flags whose computations read their values from the parent project. These computations run as the assignee, who can read the assigned task but not the invited-only project, causing a project access error. Additionally, the project many2one widget declares `is_template` as a related field. This makes web_read request `project_id.is_template` even though the widget uses the task's own `is_template` value. https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/models/project_task.py#L277 https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/models/project_task.py#L295 https://github.com/odoo/odoo/blob/8c1e139a8ffca9e9a82e90eb4a8a03a56b4aa660/addons/project/static/src/components/project_many2one_field/project_many2one_field.js#L36-L39 Solution: We need to compute the inherited task feature flags with elevated access so their values do not depend on the assignee's access to the parent project. declare `is_template` as a dependency of the current task instead of a related field of `project_id`. The task form therefore no longer reads the inaccessible project while its access restrictions remain intact. opw-6475880 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284196
The AI chat agent filter now loads and paginates results using the selected agent from the start, instead of filtering only what was already loaded. This prevents the chat list from getting stuck with too few conversations and keeps agent-specific chat views consistent when navigating back.
Original PR description
The AI chat tab has a dropdown allowing to filter it on a specific agent. The filter is applied client-side only, which is incompatible with lazy loading. A `load_more` batch fetched from the unscoped tab domain can come back mostly unrelated to the selected agent. Once filtered down it may render too little content to overflow the scrollable area. The bottom scroll trigger that requests the next batch then never fires again, leaving the tab stuck showing fewer matching channels than actually exist. The dropdown now sets its own filter through `mail`'s new `MessagingMenuUIState.pluginFilters`, which goes through the real fetch and pagination: the agent scope is resolved server-side and ANDed into the tab's domain community: https://github.com/odoo/odoo/pull/286451
This fixes an issue that prevented users from adding extra images to products from the eCommerce tab. Product teams can now upload additional product media without encountering an error during the add process.
Original PR description
Steps to reproduce: 1. Open a product form view. 2. Go to the eCommerce tab. 3. Click on 'Add Media'. 4. Upload an image. 5. Click on 'Add'. Issue: - Adding an image fails with `ERR_INVALID_URL` because the generated data URL contains `[object Object]`. Cause: - The `raw` value returned by `searchRead` is a binary object containing `filename`, `content`, and `size`, but `convertToWebpFormat` passes the whole object as the image data to `generateImageVariants`. Fix: - Pass the `content` of the binary value to `generateImageVariants` instead of the whole `raw` object. opw-6542393
This fixes Spanish TicketBAI reporting for point-of-sale orders that use gift cards. Gift card refund amounts are now shown with the correct sign, preventing mismatches between line totals and the overall invoice total.
Original PR description
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and…
The issue fixed in commit[1] is again reproducible after commit [2] the pos order line for gift card is now not considered as a refund Step to reproduce: - Install pos_loyalty and l10n_es_edi_tbai_pos with demo data - Create a gift card (add a tax to the discount product, any 0%) - start pos, add a product and use the gift card - fulfill the order - go to backend and open that order - In the TicketBAI XML, the values for the giftcard product will be positive, causing an inconsistency between the product line total and the invoice total [1] https://github.com/odoo/odoo/commit/0bbc5ebdcc7e014d87130b2ff9cee98e3aa7479a [2] https://github.com/odoo/odoo/commit/b17c9713e7a3305c240298fa54fcf1bc87a9bb8c FIX - we used to determine `sign` based on each order line's `is_refund` property - this property is quite sensitive as it depends on factors like line's qty, price, is reward or not. - so its better to depend on order's refund property for sign reversal https://github.com/odoo/odoo/blob/4fef2c5b69fac10594fac81b149d542ee4621b13/addons/point_of_sale/models/pos_order.py#L1768 opw-6226003 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286448 Forward-Port-Of: odoo/odoo#278042
Dark mode color palettes now load correctly and include the full set of colors used by the interface. This prevents missing or incorrect colors in items such as kanban cards, tags, badges, and color lists, improving visual consistency for users working in dark mode.
Original PR description
1) The "$o-colors" css variable was rebuilt in "secondary_variables.dark.scss", which loads after community's "primary_variables.scss" already assigned it via !default. The dark "$o-colors: ()!default;" reset was silently skipped, so dark colors were appended onto the light ones instead of replacing them, doubling "$o-colors" to 24 entries. => Moving this logic to "primary_variables.dark.scss", which correctly loads first. 2) "$o-colors-secondary-original" only listed 18 colors instead of the 44 used in the original "$o-colors-secondary" of light mode, meaning the dark mode's total palette had far fewer entries than the light mode leading to missing coloring in kanban, tags, badges and colorlist. => Extending the list so that the dark mode "$o-colors-secondary-original" matches the original "$o-colors-secondary" light mode's 44 colors. related: https://github.com/odoo/odoo/commit/1dd67666ce06a9ee44a193e8006cf61aa71479c3
When a contact linked to multiple active users is mentioned, all of those users now receive the notification immediately instead of only one seeing it right away. This ensures teams sharing a contact record do not miss timely mention alerts and avoids relying on a page reload to see them.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This happens because the notification is sent on the single user that _notify_get_recipients picks for a partner, and since "[REF] bus, mail: use user rather than partner as bus target" a user is its own bus channel, so the other users of that partner are no longer reached. The notification record is stored per partner, which is why a reload shows it. This commit fixes the issue by sending to every active user of the notified partner. https://github.com/odoo/enterprise/pull/129969 Forward-Port-Of: odoo/odoo#286290 Forward-Port-Of: odoo/odoo#283836
When a partner is mentioned, all active users connected to that partner now receive the notification immediately instead of only one user seeing it before reload. This improves reliability of real-time communication, with related test updates to reflect the extra processing needed.
Original PR description
Before this commit, mentioning a partner that has two users notified only one of them. The other user saw the mention on reload only. This commit raises the query counts of the activity tests: the fix in odoo resolves each notified partner to its active users, which costs one query per post with an inbox recipient. https://github.com/odoo/odoo/pull/283836 Forward-Port-Of: odoo/enterprise#130206 Forward-Port-Of: odoo/enterprise#129969
Users can now access the correct reconciliation models from bank statement lines when the bank journal uses a foreign currency. This fixes a search issue where currency labels in journal names prevented matching models from appearing, helping accounting teams manage bank reconciliation setup reliably.
Original PR description
### Issue before this commit: When clicking "Manage Models" from a bank statement line, the associated reconciliation models are not displayed when belonging to a foreign currency journal. ### Steps…
### Issue before this commit: When clicking "Manage Models" from a bank statement line, the associated reconciliation models are not displayed when belonging to a foreign currency journal. ### Steps to reproduce the issue: 1. Download Accounting 2. Go to Currencies and activate another currency like EUR 3. Go to Journals and create a new one with bank type and curency EUR 4. Go to dashboard > new test bank journal created > 3 dots in the upper-right corner > Models > create a new one (ex Tester) setting the new test bank created as journal 5. Go to test bank journal and create a new bank matching 6. After the line is created click the 3 dots and go to Manage Models 7. See that the new model Tester created does not appear ### Cause of the issue: Foreign currency journals append their currency to the display_name (e.g., "Bank (EUR)"). The JS search framework passes this full decorated string into the search domain. The backend then attempts to match "Bank (EUR)" exactly in the database name and code fields, which fails because the database name is "Bank" without the currency added. https://github.com/odoo/odoo/blob/9c67949be529eb86886b3d5bde08e81e048ecfe7/addons/account/models/account_journal.py#L1095-L1100 ### Reason to introduce the fix: The filter is not working correctly. In this case it's better to change it to a domain instead of a default filter. opw-6481970 Forward-Port-Of: odoo/enterprise#129992
Fixed an issue where embedded journal-entry actions in Documents could be removed by the cleanup process when users were working in a different company. This helps multi-company users keep their configured document shortcuts intact while preserving company-specific access behavior.
Original PR description
Step to reproduce: - You must have at least 2 companies with an account Journal - Create a New Journal Entry actions (child or parent) - Embed it to a folder - Set your company on a different one than the journal's one - Run the Garbage collector cron (Base: Auto-vacuum internal data) - The embed action has been removed The cause of this is that in the `_get_base_server_actions_domain` method in `documents_account` module there is a check on company to avoid using/running the actions when not in the right company. But the garbage collector don't need to have this check. Task-6147618 Forward-Port-Of: odoo/enterprise#122821
FedEx deliveries can now use a phone number from either the main customer contact or the selected delivery address. This prevents shipments from failing when one related contact record is missing a phone number but the other has it.
Original PR description
Issue ----- Users cannot deliver to a contact's delivery address if the contact address itself doesn't have a phone number. Steps to reproduce ----- - Setup Fedex - Create a contact with no phone number - Create a delivery address for the contact (with phone number) - Create a SO with the contact using Fedex & confirm - Change the partner on the picking to use the delivery address - Validate the picking > Error: missing phone number Cause ----- To populate the `soldTo` part of thepayload, we call `_get_contact_from_partner` with the contact specified on the SO https://github.com/odoo/enterprise/blob/8e60f910a52e3b836e997e54a0b704e5786a28f2/delivery_fedex_rest/models/delivery_fedex.py#L171 https://github.com/odoo/enterprise/blob/8e60f910a52e3b836e997e54a0b704e5786a28f2/delivery_fedex_rest/models/fedex_request.py#L447-L452 The phone number is then taken directly from the contact. ----- Ticket: opw-6427962 Forward-Port-Of: odoo/enterprise#127434
Fixed an issue where completed field service shifts linked to sales orders could incorrectly reset planned hours to zero. This prevents completed work from being shown as still needing planning, improving visibility of scheduling progress.
Original PR description
## before: When marking a shift linked to SO as complete. The `allocated_hours` of this shift is reset to 0. So when the `Planned` button tries to compute the `planning_hours_planned` it adds zero to the planned hours, making all the hours go to the `To Plan`, which is incorrect ## after: prevents the `allocated_hours` from being recomputed when making the shift as complete to avoid this issue. This will leave the hours to be calculated in the `Planned` stat button instead --- task-6425357 Forward-Port-Of: odoo/enterprise#129833 Forward-Port-Of: odoo/enterprise#126396
Fixed an issue where exporting time entries could fail for employees whose contract had multiple versions. This helps payroll users complete exports reliably after contract changes without encountering an error.
Original PR description
## Steps to Reproduce: - Install the hr_work_entry module. - Create an employee. - Payroll tab > create a contract by setting only the start date (leave the end date empty). - From the contract…
## Steps to Reproduce:
- Install the hr_work_entry module.
- Create an employee.
- Payroll tab > create a contract by setting only the start date (leave the end date empty).
- From the contract version timeline (navigation bar), click the "+" button and create a new version.
- Open the cog menu (gear icon) and click 'Export Time Entries'.
## Error:
`ValueError - Expected singleton: hr.version(257, 258)`
## Cause:
Method `_get_contract_versions()` returns multiple versions for the given period.
for example:
`contract_dict = {datetime.date(2026, 8, 1): hr.version(1, 2)}`
The code assumes each value is a singleton and builds the recordset using `c.id`,
`[c.id for c in contract_dict.values()]`
Since `c` contains multiple records, accessing the ID will raise an error.
## Fix:
Instead of accessing `id`, it will access `ids`, and it returns the list of all records (`[1, 2]`).
`chain.from_iterable()` flattens this list into one iterable sequence `(1, 2, ...)`, and
then it will convert into a list and be passed to `browse()` to fetch the corresponding recordset.
sentry-7623869169
Forward-Port-Of: odoo/odoo#278858Belgian CodaBox SODA imports now use the actual last import date when checking for new statements, instead of relying on accounting entry dates. This prevents valid payroll statements generated within the same accounting period from being skipped.
Original PR description
Before v19.1, we used to set the date on the journal entry based on the generation date of the SODA statement during the import. So it was possible to use the last date found in the salary journal as a `date_from` filter when fetching new SODA statements. Starting from v19.1, we now set the date on the journal entry as the last day of the accounting period referenced in the SODA file. However, we didn't change the fetching logic accordingly. If a SODA statement is generated on July 7 for the accounting period of July, the date on the journal entry would be July 31 and, consequently, any other SODA statement generated in-between those dates would be filtered out during the fetch. Ticket: opw-6214589 Forward-Port-Of: odoo/enterprise#130183
The stock allocation report has been refined to work better on mobile, avoid over-allocating already reserved quantities, and prevent errors from repeated quick actions. Users can now allocate or unallocate directly from the forecast report, while validation flows no longer open the allocation report automatically.
Original PR description
This PR fixes issues with [the recently merged](https://github.com/odoo/odoo/pull/264299) allocation report. Main changes are: - Add specific design for mobile device; - Don't allocate already reserved quantity; - Allocation report won't open itself automatically when validating an operation from the Barcode app, no matter the configuration (a setting is planned to be added in `master` to let the possibility if the user wants); - Add the possibility to allocate from the forecast report. For more details on these changes or other fixes, check the corresponding commit's message. _________ **Enterprise PR:** odoo/enterprise#122258 task-4894566 Forward-Port-Of: odoo/odoo#272722
The barcode app’s print button now prints labels for the allocated products instead of the allocation operation report. This helps warehouse users get the right labels directly from barcode lines, reducing confusion and manual reprints.
Original PR description
Before this commit, the print button on barcode line printed the allocated operation's report instead of the allocated products' labels. This commit fixes that. _________________ **Community PR**: odoo/odoo#272722 [task-4894566](https://www.odoo.com/odoo/966/tasks/4894566) Forward-Port-Of: odoo/enterprise#122258
Adds checks before sending Turkish Nilvera e-invoices so users are warned when invoice lines are missing required taxes or product/CTSP details. This helps prevent invoices from being rejected by Nilvera, while avoiding unnecessary warnings for note or section lines.
Original PR description
Nilvera does not accept invoices with lines that do not have taxes, so we added a valiation check for sending the invoice to warn the user. Additionally, we raise a warning when a line does not have a product and has an empty CTSP. However, if the line is a note or section, this warning should not be triggered. task-6404409 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 Forward-Port-Of: odoo/odoo#284969 Forward-Port-Of: odoo/odoo#284377
Restarting a live chat chatbot session now correctly shows the available answer choices again. This prevents visitors from getting stuck or confused when they restart a conversation before it has been fully saved.
Original PR description
Before this commit, after restating a chabot session, the chabot question answers were not shown. This happens since the change in [1], introducing the field `selectedAnswerEver` in order to solve problems of stale server writes. However when a session is restarted, the first chatbot steps without a "real" message record (before the session is persisted) resolve to the same records of the earlier session. In turn this leads to said step having a selected answer already and thus not showing the choice. This commit solves the issue by clearing the selected answer fields when going to the next step, which is acceptable against stale writes since it's a purely client side decision. task-6535116 [1] https://github.com/odoo/odoo/pull/278597
Turkish credit notes created from existing invoices now use the dedicated sales return account from the sales journal instead of incorrectly keeping the original sales account. This improves accounting accuracy for Turkish companies while preserving exact matching for cancellation reversals.
Original PR description
The Turkish chart of accounts keeps sales and sales returns on separate accounts, and the sales journal carries the account to use for returns. A credit note typed in by hand already lands on it, but one created from an existing customer invoice did not. Reversing an invoice copies `account_id` over from the invoice line, and since that field is a stored compute without depends, nothing ever recomputes it, so the return kept the sales account. Set the journal account on the copied product lines instead. Reversals made to cancel an entry are left alone, as those have to mirror the original move exactly for the two to net out, and a plain duplicate is untouched. Task-6438412 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284808 Forward-Port-Of: odoo/odoo#282858
E-invoice imports and exports no longer include internal deferred revenue dates that are only relevant to the vendor's accounting process. This prevents customers from receiving irrelevant date information and avoids creating deferred entries when importing vendor bills.
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). task-6014315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281348 Forward-Port-Of: odoo/odoo#265796
Fixes a Razorpay FPX payment issue that could cause checkout to fail when customers returned from the payment page. The payment flow now handles missing return details correctly, improving reliability for merchants using Razorpay FPX.
Original PR description
Issue: --- Paying with Razorpay using FPX raises `KeyError: 'amount'` when the customer returns from checkout. Steps to reproduce: 1- Enable Razorpay with FPX as a payment method. 2- Pay an order using FPX. Cause: --- In FPX, Razorpay returns without `amount`/`currency`. `_apply_updates` fetches the full payment from the API to determine the state, but that fetched entity is local to the method and never reused for amount validation, so `_process` still calls `_validate_amount` / `_extract_amount_data` with the original, amount-less redirect data. This issue is introduced after c34992ffd94ba4594731400839332b677fdc2b32, which removed the check in `_extract_amount_data` that returned `None` (skip validation) when `amount`/`currency` were absent. opw-6467815 Forward-Port-Of: odoo/odoo#286476
Stripe SEPA payments no longer use the order reference as the bank statement descriptor, avoiding failures when an order number contains only digits. The descriptor now uses the company name again, making SEPA payments more reliable for affected customers while preserving expected statement information.
Original PR description
**Steps to reproduce:** 1. Install Sales, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in…
**Steps to reproduce:** 1. Install Sales, l10n_be, payment_stripe and switch to belgian company 2. Switch the admin user's company to the belgian one, and update their contact address to be in Belgium 3. Enable stripe payment provider 4. Add SEPA payment method in stripe configuration 5. Create a sale order with a name that doesn't include any characters (numbers only), confirm, click preview and attempt to make a payment using SEPA **Issue:** `The statement descriptor must contain at least one Latin character.` **Cause:** The previous fix (4fde0232b821c9a1d46d589ff14495f4e19029f4) passed the order reference directly, assuming it will contain characters. The intended behavior is to actually have the company name used in the statement descriptor field: https://support.stripe.com/questions/what-is-a-statement-descriptor-and-how-do-i-update-it This was the existing behavior before the fix, so will revert back to it. opw-6497127 Forward-Port-Of: odoo/odoo#286620 Forward-Port-Of: odoo/odoo#286287
Colombian retention reports now calculate the taxable payment amount correctly when vendor bills include partial credit notes. This prevents credit notes from incorrectly increasing the reported tax base, improving accuracy for retention certificates and related tax reports.
Original PR description
**STEP TO REPRODUCE** 1. install l10n_co_reports and account_accountant 2. Create a bill, with a line with a retention tax (3.50% RteFte). 3. Create a partial credit note (unit price less than what's on the bill). 4. Goes to the report 'Certificado de Renteciòn en Fuente', and notice the Monto del Pago Sujeto Retenciòn is not correct. **CAUSE** The sql query multiply tax_base_amount by -1 if debit > 0, which means (because we are dealing with vendor bills) the line is from a credit note, but tax_base_amount is already a signed value so credit notes ends up contributing to the tax base amount while they should reduce it. opw-6235830 Forward-Port-Of: odoo/enterprise#130340 Forward-Port-Of: odoo/enterprise#119716
Invoice import and export now avoids using internal deferred revenue dates that are only relevant to the vendor. This prevents customers from receiving irrelevant accounting dates in Peppol invoice data while preserving the needed Colombian support document behavior.
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). But it is kept for the colombian localization in case of support documents though. task-6014315
Changing Peppol Reception Mode to receive invoices as documents no longer triggers an error. This helps Belgian companies using Peppol complete setup smoothly without interruption.
Original PR description
Steps to reproduce: - Install `documents_account_peppol` and `l10n_be` module - Switch to BE Company > `Activate Peppol` - Change `Peppol Reception Mode` -> `Receive as Documents` Traceback: `AttributeError: 'res.company' object has no attribute '_peppol_allows_document_reception'` Problem: Changing the `Peppol Reception Mode` to `Receive as Documents` causes an `AttributeError` because `_compute_peppol_purchase_journal_required()` calls `_peppol_allows_document_reception()` on `config.company_id`, but the method is defined on `res.config.settings`. Cause: The method is available on the `res.config.settings`, not on the `res.company`. Solution: Add `_peppol_allows_document_reception()` method in `res.company` and call company's method from the `res.config.settings` method. opw-6470552 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286517
Fixed an issue in Documents where choosing “Search More...” from fields like Owner or Customer could immediately close the selection window. Users can now interact with that window normally, making it possible to search, sort, and select the right related record without interruption.
Original PR description
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the…
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the field dropdown, click "Search More..." to open a modal dialog. 5. Click inside the "Search More..." modal (e.g., to sort columns or resize headers). Issue: - The modal dialog immediately closes, and the contact cannot be selected. Root cause: - When an inspector field is edited, the record row is put into edit mode. While in edit mode, the documents list renderer listens for global clicks. Clicking inside the "Search More..." modal dialog targets elements that have `.o_list_renderer` (since the modal dialog renders a list view). Because the click target is within a list renderer but is not a document row, `DocumentsListRenderer.onGlobalClick` executes and clears the selection of the main list view. Clearing the selection unmounts the edited field in the inspector, thereby destroying the modal dialog stack. Solution: - Modify DocumentsListRenderer.onGlobalClick to scope click handling to the current Documents list renderer. Ignore clicks outside this.root.el, so interactions in nested UI such as Search More... do not clear the main selection and destroy the inspector field. opw-6253360 Forward-Port-Of: odoo/enterprise#128812 Forward-Port-Of: odoo/enterprise#119262
Manual quality checks created from a picking can now record a partial failed quantity without blocking the transfer. This prevents validation errors and lets warehouse teams continue processing orders when only some units fail inspection.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `quality_control` module - Create a picking order with a product - From the gear menu, create an on-demand Quality Check -…
Version:
--------
- 19.0+
Steps to reproduce:
-------------------
- Install `quality_control` module
- Create a picking order with a product
- From the gear menu, create an on-demand Quality Check
- Set the check to *Control per Quantity* and back to the picking
- Set the done quantity to 10
- Open the Quality Check wizard
- Try to fail 3 units
Issue:
------
Validating the partial failure raises a `ValidationError`:
- Missing required value for the field 'Team' (team_id)
The quality check split is not performed and the picking cannot be processed.
Cause:
--------
Quality checks created on-demand from the picking (via the gear menu) have
no associated `quality.point` or `stock.move.line` — only
`picking_id` is set at creation time.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L457
In `_move_to_failure_location()`, the `move_line` branch assumes
`check.move_line_id` is populated. Since it is empty for on-demand
checks, the split logic operates on an empty recordset.
The new quality check for the split is then created via:
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L493
At this point both `failed_move_line` (a copy of the empty move line) and
`check.point_id` are empty. `_get_check_values(False)` cannot derive
fields normally sourced from the quality point (`team_id`, `company_id`,
`measure_on`, `test_type_id`, etc.), causing the `ValidationError` on record creation.
Fix:
----
- If the quality check is not linked to a move line, find the matching move line
from the picking before splitting the failed quantity.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/stock_move_line.py#L94-L97
- `_get_check_values()` normally takes values from a Quality Point.
Since on-demand quality checks do not have one, fill the missing
values (`team_id`, `measure_on`) from the original quality check instead.
This allows manually created quantity-based quality checks to be
split correctly after a partial failure.
---
opw-6428749
Forward-Port-Of: odoo/enterprise#130275
Forward-Port-Of: odoo/enterprise#126505Fixed an issue where importing multiple Belgian SODA files at once could copy accounting lines from the first file into the second. This helps ensure imported payroll accounting data stays accurate and avoids duplicate or incorrect entries.
Original PR description
Due to this commit: https://github.com/odoo/enterprise/commit/93c05b380e3c939e3c0b44eafcd7a41e86042d2d When importing 2 sodas from drag and drop. Due to the placement of the line_ids variable, the second move would have the line of first. By placing the variable in the loop we don't have that problem anymore task-6528101 Forward-Port-Of: odoo/enterprise#130190
The Shopee sales integration now continues processing shipment label batches even if one batch has incomplete or unexpected data from Shopee. This reduces failed background jobs and helps remaining shipments keep moving without manual intervention.
Original PR description
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch shipment labels for multiple batches of shipments. If some shipments do not contain the required data in the Shopee API…
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch
shipment labels for multiple batches of shipments. If some shipments do not
contain the required data in the Shopee API response, the error causes the
cron to stop, preventing the remaining batches from being processed.
Error:
`ValueError: KeyError('status') while evaluating 'model._sync_shopee_pickings()'`
This issue was introduced by a recent refactoring commit [1] focused on linting
and formatting the Python file. The commit replaced the generic `Exception`
with `UserError` when handling errors during batch label printing.
As a result, errors other than `UserError` are no longer handled at the batch
level. When such an error occurs, the entire cron process stops instead of
failing only the affected batch and continuing with the remaining batches.
This commit fixes the above issue by handling generic `Exception` during
shipment label generation, ensuring that the error is handled for the
affected batch while the remaining batches continue to be processed.
[1]: https://github.com/odoo/enterprise/commit/cfe5d947579739ad770ac3f1525ce157af530846#diff-e072c3ecf980add685bb4a4f25cf2b0ab5d4625988e4afc2c4d4faeae687ca88R199
sentry-7685943988
Forward-Port-Of: odoo/enterprise#130295
Forward-Port-Of: odoo/enterprise#130181