Friday, August 29, 2025
24 changes · saas-18.4
Enhancements to existing features
Installing the Manufacturing app on very large databases is now less likely to run out of memory or time out. The setup process initializes existing stock movement data more efficiently, improving reliability for customers with high transaction volumes.
Original PR description
Description ----------- On large databases with millions of already existing `stock.move`, the post-install computation of compute stored fields can be time-consuming and memory intensive. This commit extends the pre_init_hook that was done in `mrp` to: - Speed up computation of `stock.move.is_done` - Implement SQL query to initialize `stock.move.manual_consumption`. Reference --------- opw-4980036 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#222299
Odoo now treats ZATCA's duplicate-submission response for Saudi B2C invoices as a successful send. This prevents invoices from remaining uncertain or blocked after a timeout when ZATCA had already received them.
Original PR description
ZATCA introduced a new response code (409) to handle duplicate invoice submissions for B2C. This is helpful because when the submission timesout, we are left unsure whether ZATCA successfuly received the invoice or not. The next time Odoo tries to send the same invoice, Zatca will respond with a 409 error if it was received earlier. In which case, we mark the invoice as successfully sent. A similar flow applies for B2B, with a response code of 208 for duplicate invoices. However, for B2B, ZATCA accepts the duplicate with a warning instead of an error, So the invoice gets marked as sent in Odoo, and no changes need to be done there. task-id: 4745275 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#224478 Forward-Port-Of: odoo/odoo#223754
The shop floor now keeps track of the user's active work center when they leave and return through breadcrumbs. This prevents confusing changes in the displayed work centers and helps operators resume work in the same view, while preserving the existing behavior when opening from Manufacturing work centers.
Original PR description
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app:…
Description of the issue/feature this PR addresses: Incoherent selection of workcenters when using the breadcrumbs to come back to the shopfloor app: https://drive.google.com/file/d/1C1nVdDHgCss7s7zyXDOpbMj0k79HlJBH/view?usp=drivesdk Current behavior before PR: When leaving the shopfloor app via a WO (WO setting -> Open MO), we set the a **context flag workcenter_id** in the the currentCaller.action.context to save the selected workcenter for breadcrumb logic. The same **context flag workcenter_id** is used in the Manufacturing/workcenters view, when clicking on a workcenter. However, the intended use of the **workcenter_id flag** is different: - 1 From Manufacturing: Open shop floor with **only** workcenter_id selected + visible (no other workcenters visible). - 2 From Shopfloor breadcrumb : Go to shop floor with all previous workcenters same as when leaving. Additionally the current logic for setting the workcenter_id flag from the MrpDisplay record currently handles only the selection of isMyWO ([PR](https://github.com/odoo/enterprise/pull/52258)) Desired behavior after PR is merged: Keep the same behavior when coming from Manufacturing/workcenters ([PR](https://github.com/odoo/enterprise/pull/67318)) but make sure the user come back to same view when leaving shopfloor and coming back via breadcrumbs. task: [4629641](https://www.odoo.com/odoo/project/966/tasks/4629641) I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/enterprise#93345 Forward-Port-Of: odoo/enterprise#88073
Resolved issues and error corrections
This fix prevents open dialog windows from getting out of sync when one dialog is closed more than once. Users can now continue and close remaining dialogs normally, avoiding stuck windows and potential crashes during employee holiday attest workflows.
Original PR description
Have two dialogs opened, call twice `close` on one of them. From that point, the `stack` in dialog_service is empty (because the second time, the dialog can't be found in `stack`, so its index is -1,…
Have two dialogs opened, call twice `close` on one of them. From that point, the `stack` in dialog_service is empty (because the second time, the dialog can't be found in `stack`, so its index is -1, and calling `splice` with -1 removes from the end of the array), even though one of the 2 dialogs is still displayed. From that point, calling closeAll does not close the remaining dialog. In practice, this can be reproduced in Employees > Laurie Poiret (must be in BE company). In the cog menu, click on "Departure: Holiday Attest". In the dialog, click on the external button of the many2one. Close the second dialog by clicking on the X. At this point, `close` has been called twice for that dialog (once by the click on the cross, and once by an override of `dialogData.dismiss` in FormViewDialog), and `stack` is thus empty. Clicking on an action button in the first dialog (e.g. "Validate & Compute holiday attests") then no longer closes the remaining dialog as it should (as `closeAll` is called by the action service). Then, a crash can occur when manually trying to close that dialog, as the view in the background no longer exists, and closing the dialog calls its `onClose` callback, which tries to reload the view, thus leading to the "Component is destroyed" error. Issue introduced by https://github.com/odoo/odoo/pull/203169 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#224792
Fixes color selector issues in the HTML editor so floating color menus close properly when the toolbar is hidden. It also makes color changes more reliable for text using gradients, preventing confusing or broken color picker behavior.
Original PR description
**Current behavior before PR:** **Issue 1:** - Have a long text content in editable, making the container scrollable. - Select first line of the text, in toolbar open color selector. - Scroll down…
**Current behavior before PR:** **Issue 1:** - Have a long text content in editable, making the container scrollable. - Select first line of the text, in toolbar open color selector. - Scroll down until the toolbar overflows and becomes hidden. - Notice that the toolbar disappears when it overflows its container while color picker remains open, floating at the top of container. **Issue 2:** - Select a text having gradient text color. - Open text color selector, switch to custom color picker. - Notice that hex and rgba fields are empty and user is not able to apply color through it. In colorpicker.js, the convertCSSColorToRgba method fails when attempting to convert a gradient color to RGBA. As a result, colorComponents does not receive valid values and colorpicker doesn't work as expected. **Issue 3:** After merging commit [1], text color can be applied without removing or affecting the existing gradient color. In result, if gradient is fully selected then applying text color creates a new font tag inside gradient instead of replacing the gradient. **Desired behavior after PR:** **Issue 1:** Now, when the toolbar overflows and gets hidden, the color selector becomes hidden along with toolbar. **Issue 2:** Now, if `convertCSSColorToRgba` fails to convert selected color to rgba color then default color `#FF0000`is assigned to color components. This ensures that the colorpicker functions correctly. **Issue 3:** Now, if gradient is fully selected then, - Applying text color removes existing text gradient. - Applying background color removes existing background gradient. - Applying text color doen't remove the existing background gradient. - Applying background color doesn't remove the existing text gradient. [1]: https://github.com/odoo/odoo/commit/938995744b15f345958a2d78a6c844dd5bf1ae6c Enterprise PR: https://github.com/odoo/enterprise/pull/84579 task-4581884 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221381 Forward-Port-Of: odoo/odoo#202889
Google Merchant Center shipping price calculations now avoid overusing external carrier quote requests. This helps prevent hitting daily carrier rate limits, such as DHL limits, while keeping product shipping information available for online sales channels.
Original PR description
### Issue: The `Google Merchant Center` calls the method `_prepare_gmc_shipping_info` in order to compute the best shipping price for each published product in each possible country: https://github.com/odoo/odoo/blob/1ac89eb71aab48fa8d50fbae01d96bec23d88418/addons/website_sale/models/product_product.py#L352-L361 To achieve this, the method will request the shipping rate for each possible carrier, product, country. However, for external carriers, each such combination will require a request to the external api via the `rate_shipment`: https://github.com/odoo/odoo/blob/1ac89eb71aab48fa8d50fbae01d96bec23d88418/addons/website_sale/models/delivery_carrier.py#L44-L53 This is problematic as external carriers have a standard rate limit (maximal amount of rate requests allowed per day). For instance DHL standard rate limit is 250 requests per day. opw-5048969 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224649
This fixes exchange returns so serial-tracked products are treated as new incoming items instead of reusing existing serial numbers. It also corrects stock quantity calculations after exchanges and only shows the exchange return option where it is relevant.
Original PR description
When returning tracked-by-serial products from an incoming picking for an exchange, the exchange move will have selected existing serial numbers for the new incoming picking. This happens because…
When returning tracked-by-serial products from an incoming picking for an exchange, the exchange move will have selected existing serial numbers for the new incoming picking. This happens because `move_orig_ids` is set on the exchange move(s), then `_action_assign()` happens. If there's a `move_orig_ids`, it will use the available move lines from the move_orig_ids and so assign the corresponding serial number. Additionally, the buttons to generate/import serials/lots are invisible because `origin_returned_move_id` is set on the same exchange move(s). Again, the exchange move(s) should be considered 'new' move thus having no origin. task 4893860: Additionally (again), it fixes an issue where on-hand quantities and forecasted quantities of the exchanged product were incorrect after validating the exchange. task 4778066: Finally, this PR also hides the 'Return for Exchange' button for pickings that are neither `incoming` nor `outgoing`. tasks 4748294 (& 4778066 & 4893860) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224696 Forward-Port-Of: odoo/odoo#216111
The payroll leave handling now avoids changing work entries that have already been validated. This prevents installation or payroll setup failures when overlapping leave entries are processed, helping keep approved payroll-related records stable.
Original PR description
This logic of solving the overlapping between leave work entries has been adjusted to prevent editing the entries marked as validated. This error appears in the installation in task #4921300. You can refer to the error here: https://runbot.odoo.com/runbot/build/87127472 To reproduce: -Fake time a date in the future, for example :"2025-09-05 UTC". -Install the needed modules with demo data: -i "hr_payroll,project_timesheet_holidays" --with-demo.
This fixes an issue where a customer’s selected pricelist could change incorrectly when an individual contact was linked to a company. Sales quotations now keep pricing consistent between the individual and their company, reducing pricing mistakes and manual corrections.
Original PR description
Versions -------- - 18.0+ Steps ----- 1. Create an individual partner; 2. assign them a pricelist A; 3. create a new company partner for them; 4. create a new pricelist A & sort it on top; 5. open a…
Versions
--------
- 18.0+
Steps
-----
1. Create an individual partner;
2. assign them a pricelist A;
3. create a new company partner for them;
4. create a new pricelist A & sort it on top;
5. open a new quotation;
6. set new company as customer;
7. change customer to the individual partner.
Issue
-----
The quotation's pricelist changed from B to A. The pricelist used for the individual should be identical to the one used for their company.
Cause
-----
Commit de302c2d36305 added the `specific_property_product_pricelist` field to `res.partner`, as the way company-dependent fields are managed was changed on the database-level.
Commit 67cf577cd0a0 added the `_company_dependent_commercial_fields` method to enable syncing company-dependent commercial fields. The base method fetches all fields retrieved via `_commercial_fields`, and selects those whose `company_dependent` attribute is `True`.
In previous versions, the `_company_dependent_commercial_fields` override in `product` adds `property_product_pricelist`, as this field does not have the `company_dependent` attribute set, but it behaves as a company-dependent field. Starting from 18.0, the override adds `specific_property_product_pricelist` instead, which does have the `company_dependent` property set.
As a consequence, when `_company_dependent_commercial_sync` gets called, it does not sync the `specific_property_product_pricelist` as it's not included in the `_commercial_fields` override, nor does it sync when retrieving it from `_company_dependent_commercial_fields`, as it skips the current company, assuming the field was already handled by `_commercial_sync_from_company`: https://github.com/odoo/odoo/blob/c40760244d128cb57e11a233e89a93dd92b8fb56/odoo/addons/base/models/res_partner.py#L667-L668
Solution
--------
- Move `specific_property_product_pricelist` to `_commercial_fields`
- This enables it to sync in `_commercial_sync_from_company`
- Remove the `_company_dependent_commercial_fields` override
- `property_product_pricelist` shouldn't get synced by itself
- `specific_property_product_pricelist` is already included by the base method
opw-4988736
Forward-Port-Of: odoo/odoo#224133
Forward-Port-Of: odoo/odoo#222223This fixes an issue where archiving a loyalty program that was still applied to a Point of Sale order could cause errors when the POS interface was reloaded. Businesses can now archive old loyalty programs without interrupting checkout operations or affecting existing active orders.
Original PR description
Before this commit, archiving a loyalty program while it was actively applied to an order could lead to errors. Specifically, if a PoS order had an active loyalty program applied, and that program was subsequently archived from the backend, reloading the PoS interface would cause issues or prevent proper functionality due to the program's sudden unavailability. opw-4941044 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#218814
Early payment discounts are now applied based on the discount deadline saved on the posted invoice, not on later changes to the payment terms. This ensures customers keep the discount eligibility that was communicated to them when the invoice was issued, improving consistency in payment registration and reconciliation.
Original PR description
When a payment term with early payment discount is used on invoice the discount date is set on the payment term line based on the actual configuration of the payment term. When the invoice is posted,…
When a payment term with early payment discount is used on invoice the discount date is set on the payment term line based on the actual configuration of the payment term. When the invoice is posted, this date must not change anymore as it usually is what is communicated to the partner in order to apply EPD. However, if the payment term's delay for discount is modified, the discount date from the move line was not taken into account by the payment register wizard or by the reconciliation widget, as it was instead recalculating a discount limit date, based on the configuration of the payment term at the time the payment is registered on Odoo. Make sure it is the discount date that is stored on payment terms' account move line that is used to define if an early payment discount has to be applied. OPW-4895365 Description of the issue/feature this PR addresses: On runbot, create a new payment term with an early payment discount (eg 10% at 15 days, balance at 30 days). Create a customer invoice with a invoice line (eg 100 USD) for any customer with this payment term and set the date to 10 days before today. Post the invoice, you can see on the payment term line that the discount is valid until 5 days after today. Modify the payment term to set 10% at 5 days. If you go back to the invoice, you'll notice the discount date is still 5 days after today which is fine since this is what was communicated to the customer Current behavior before PR: Register a payment on this invoice and you'll notice the EPD is not applied because it gets the date from the actual configuration of the payment term instead of the date stored on the invoice's payment term line. Desired behavior after PR is merged: Register a payment on this invoice must apply the EPD as it is still valid based on the invoice's payment term line. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224044 Forward-Port-Of: odoo/odoo#215615
This fix prevents draft point-of-sale orders from being synchronized when a cashier validates another order after selecting a customer. It helps avoid unwanted draft orders appearing in the system and keeps sales data cleaner.
Original PR description
Before this commit, in a non-restaurant PoS, when selecting a partner in a draft order, validating an order would also sync the draft order. opw-5037759 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224041
This fixes an issue in Email Marketing where templates saved from a mailing were not shown as choices when creating a new mailing. Users can now reuse saved email content as expected, reducing duplicate work and confusion.
Original PR description
Step to reproduce: - install email marketing and open it - create a new record, add name and add something in email body - click on "Add to Templates" - click on new Observation: - The newly created template is not shown as option for new record. Cause: - https://github.com/odoo/odoo/pull/205486 convert arrays value to object, [exact change](https://github.com/odoo/odoo/commit/f79b2edb614fd08b19b18beeb16be38743f637b2#diff-0b4e81825324dc36e89543232f3f8f8704acddc4ec21031c6ccea78ee93b00eeR368-R379) but in this case, we actually return values_list, i.e. a tuple for m2o fields https://github.com/odoo/odoo/blob/ea1767e3a016f501d5bc4012cc5e964fc05955a3/addons/mass_mailing/models/mailing.py#L816-L834 - Hence, using a key evaluates to `undefined` - so, the values return by `action_fetch_favorites` are not rendered Fix: - use index instead of keys opw-4960103 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale now shows a clear Access Denied popup when a user lacks permission to load sample POS category data, instead of failing with a technical error. This helps store administrators understand the permission issue and avoid confusing crashes when opening a POS session.
Original PR description
Currently, an error occurs when a new user with the Member role and Administrator rights for the Point of Sale app attempts to open POS Category. Steps to reproduce: --- - Install the `point_of_sale`…
Currently, an error occurs when a new user with the Member role and Administrator rights for the Point of Sale app attempts to open POS Category.
Steps to reproduce:
---
- Install the `point_of_sale` module (without demo data).
- Create a new User and give Administrator rights for POS & Accounting
- Now log in with a new user in a different browser
- Open the pos session(Clothes or bar)
Traceback:
---
```py
AccessError: You are not allowed to modify 'Product Category' (product.category) records.
This operation is allowed for the following groups:
- Products/Admin en Products / Create
Contact your administrator to request access if necessary.
ParseError:while parsing /home/odoo/src/odoo/saas-18.3/addons/point_of_sale/data/scenarios/clothes_category_data.xml:5, somewhere inside <record id="product_category_clothes" model="product.category">
<field name="name">Clothes</field>
</record>
```
This commit prevents the error by displaying an "Access Denied" pop-up when a user with the "Member" role and Administrator rights attempts to open the POS Category.
sentry-6683335275, 6679363278, 6823710988
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#215429This fixes an issue where changes to a company’s Peppol email address were not being sent to the external Peppol service. Businesses can now rely on email updates made in the configuration wizard being properly applied, helping keep electronic invoicing contact details accurate.
Original PR description
Due to the config wizard email address field being a related field, and the control flow triggering actual API update only on gets hit when the wizard's email is different from company's email, this control flow never triggered. The email field in peppol config wizard is a related field to companies peppol email, so the API update ran only if the wizard's email differed from the company's email. Since both were always the same by definition, the update never triggered. Depends on https://github.com/odoo/iap-apps/pull/1167 no-task Forward-Port-Of: odoo/odoo#224615
Stopping a timesheet timer now matches the entry to the user's local calendar date instead of the UTC date. This prevents time from being added to the previous or next day for users working across time zones, improving accuracy in timesheet records.
Original PR description
Before this commit, if you were to log time on a timesheet using the timer start and stop buttons, you could potentially log time for the previous day's or the upcoming day's timesheet entry. This is because we were searching for previously-created timesheet entries based on the UTC Date of the timer's "stop" time. This fix uses the client's local time to get the Date of the timer stop. With this, we'll only find timesheet entries with the `date` field matching the client's local Date. opw-4967487 Forward-Port-Of: odoo/enterprise#93356 Forward-Port-Of: odoo/enterprise#92569
Swiss payroll sheet calculations no longer unnecessarily recalculate wage-related values after the occupation period is recomputed. This prevents manual payroll adjustments from being overwritten, helping payroll teams keep intentional corrections intact.
Original PR description
Following changes in 18.4, compute sheet introduces a recomputation of occupation period which introduces a recomputation of wages, this recomputation is not necessary as it overrides all introduced manual change.
Subscription invoices created after portal payments now trigger the required electronic document signing process. This restores expected government-compliant invoicing for customers using localized EDI flows, such as Mexican invoice signing.
Original PR description
## Steps to reproduce: - Make sure the Mexican localization is installed and properly set up for signing invoices - Make sure the payment providers are set up (it can be demo, the customer uses…
## Steps to reproduce: - Make sure the Mexican localization is installed and properly set up for signing invoices - Make sure the payment providers are set up (it can be demo, the customer uses Stripe but it can be reproduced with any - Make sure the online payment setting is active - Go to subscription module - Do a new order - In other info, add the online payment checkmark - Confirm the order - Generate the payment link or go into the preview - Make the payment ## Issue: The invoice is generated, but is not signed by the government (no edi is generated), as it used to. ## Cause: The flow works in 17.0 but for the wrong reason. Before this [commit](https://github.com/odoo/enterprise/pull/70562), two mails were sent. And during the chain of triggers of the second email, edi document was generated with `orders._send_success_mail(tx.invoice_ids, tx)`. https://github.com/odoo/enterprise/pull/70562/files#diff-8778c8dce7ca1c24de19f26f11ac0c5410c6c2a4d121c3815682a2323cbb09c2L177 After the removal of the method, it should still work since we still have `payment.transaction._send_invoice` which calls `_generate_and_send_invoices` and should trigger the sub calls necessary for generating the edi stuff. But in `_create_or_link_to_invoice`, we check that the transaction has no invoice_ids linked (make sense with the name of the method). However, at this stage, we already created the invoice in https://github.com/odoo/enterprise/blob/2f3698b250092ad376344e959d46bdc0eebf1a81/sale_subscription/controllers/portal.py#L419-L424 And unfortunately, it will be effectively possible to "let the post process of transaction create" the invoices only in Master (the code is not ready yet). For now it would be too risky for a stable version to make such change. ## Solution: We ensure EDI documents are generated whenever a `subscription_action` is set. To achieve this, modify the `_post_subscription_action` hook to call `_subscription_post_success_payment` for any `subscription_action`, including `assign_token`. From `_subscription_post_success_payment`, we can call `_generate_and_send_invoices` on any invoice that has an EDI associated with it, which sends & signs the required EDI documents. opw-4648189 Forward-Port-Of: odoo/enterprise#93130 Forward-Port-Of: odoo/enterprise#84815
Vendor bills with no taxes are now excluded from GSTR2B reconciliation. This prevents bills that were likely not filed by the vendor from appearing in the matching process, improving the accuracy of Indian GST reporting.
Original PR description
Before this commit- We included the Vendor bills without taxes for GSTR2B reconciliation After this commit- We exclude the Vendor bills without taxes for GSTR2B Because if no tax is there on the bill it means wasn't filed by the Vendor as well task-5023013 Forward-Port-Of: odoo/enterprise#93373 Forward-Port-Of: odoo/enterprise#92866
Fixed an Accounting issue that could block users from deleting a generated bank statement line when a journal entry involved multiple reconciliation models. This helps accounting users correct bank statement entries without encountering an unexpected error.
Original PR description
Currently, an error occurs when trying to remove a move line from a bank statement line if the journal entry contains lines with different reconciliation models. **Steps to Reproduce:** 1. Install…
Currently, an error occurs when trying to remove a move line from a bank statement line if the journal entry contains lines with different reconciliation models. **Steps to Reproduce:** 1. Install the Accounting module. 2. Duplicate the "Internal Transfer" reconciliation model. 3. Accounting dashboard > click on Bank > create new record. 4. Add the invoice, apply "Internal Transfer" reconciliation model. 5. Edit the balance of the line to lower, apply duplicated model(Internal Transfers (copy)). 6. Try deleting the generated Liquidity Transfer line. (Refer [this video](https://drive.google.com/file/d/1cz80Q5325x3rqYUlGahVzFIXH2iqrbRF/view?usp=drive_link) for steps to reproduce.) **Error:** ValueError - Expected singleton: account.reconcile.model(8, 6) **Cause:** In the method `delete_reconciled_line` at [1], the `reco_model_id` is fetched from `self.move_id.line_ids.reconcile_model_id`. If the move contains lines linked to multiple reconcile models, this causes a singleton error during subsequent processing. **Fix:** This commit uses the already computed `move_lines_to_remove` to retrieve `reconcile_model_id` instead of accessing it from `self.move_id.line_ids`, which may result in a multi-recordset. [1] - https://github.com/odoo/enterprise/blob/89aa58029a79928788277489414f8192aa5353e4/account_accountant/models/account_bank_statement.py#L1041-L1049 sentry-6781788260 Forward-Port-Of: odoo/enterprise#91619
Recurring subscriptions based on timesheets were sometimes treated as free when the sales order total or recurring revenue was zero, even though work had already been delivered. This fix ensures delivered timesheet-based services still generate invoices, helping businesses bill correctly for completed work.
Original PR description
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product…
### Steps to reproduce: - Install Helpdesk, Sale Subscription apps - Create a service recurring product and set its invoicing policy as 'Based on Timesheets' - Create a SO with the created product and set the qty to 0 - Create a Helpdesk ticket and link it to the SO - Record some timesheets in this SO - Run the cron for generating recurring invoices - Notice no invoice will be created for the SO and it will be considered as free renewal ### Cause: When trying to create a recurring invoice we check if the invoice that will get generated is free by checking the MRR and the total amount of the SO and if one of them are 0 we will flag this invoice as free so we won't generate it ### Fix: We check if the order lines to be invoiced is invoiced based on delivery and they have delivered quantity already and if so we create the invoice even if the MRR and the total amount is equal 0 opw-4990478 Forward-Port-Of: odoo/enterprise#93245 Forward-Port-Of: odoo/enterprise#93115
Portal users receiving published planning shift emails now get a link that opens the correct planning view instead of sending them to the portal dashboard. This helps external users access their schedules directly and avoids confusion after clicking the email button.
Original PR description
### Steps to reproduce: - Install Planning app - Create a portal user and an employee for this user - Create a shift for this user and Publish it - Go to the email that has been sent and click on…
### Steps to reproduce: - Install Planning app - Create a portal user and an employee for this user - Create a shift for this user and Publish it - Go to the email that has been sent and click on View Your planning - Notice you are redirected to the portal dashboard home ### Cause: Since this commit diff we removed the check if the user is having planning group https://github.com/odoo-dev/enterprise/commit/72afe1e14703f0a3eafd0cfaec10c67462db73ce#diff-293bc9f44292d19793981abbafbe2a55642d170bda5e3bf17d7654f7bffcbedaL62-L64 When getting the planning url that will be share in the email we don't check if the user is portal or not so we set the url with /odoo path and if a portal user is accessing a /odoo path it will redirect him to /my https://github.com/odoo/odoo/blob/1acf4b2ce2bdad27e7d32d1227698968148a5935/addons/portal/controllers/web.py#L25-L26 ### Fix: We check if the user is portal we set the url with /planning path which will redirect the portal user to the correct planning view opw-5045746 Forward-Port-Of: odoo/enterprise#93359 Forward-Port-Of: odoo/enterprise#93333
The GSTR document summary now ignores invoices that no longer have a valid sequence number. This prevents report generation errors and ensures only properly numbered invoices are included in the summary.
Original PR description
_* = l10n_in_reports_gstr_document_summary Issue: - The GSTR document summary included all invoices that were posted or cancelled with posted_before = True. - If a user manually cleared the invoice sequence (set it to null), such invoices were still picked up. - This caused errors during summary generation since those invoices no longer had valid sequence numbers. Fix: - Adjusted the document summary logic to only include invoices with a valid sequence number. - Ensures that entries without a sequence are ignored, even if they were once posted. Impact: - Prevents errors when generating GSTR document summaries. - Guarantees that only valid, numbered invoices are included in reports. opw-5005048 Forward-Port-Of: odoo/enterprise#93039
The POS IoT integration now selects the printer configured for receipts instead of accidentally using another connected printer, such as a kitchen preparation printer. This prevents receipts from being sent to the wrong device in setups with multiple printers.
Original PR description
Steps to reproduce: 1. Configure a POS with a receipt printer and a preparation printer. 2. Ensure that the preparation printer has a higher ID than the receipt printer (you can force this by deleting it and letting the IoT redetect it.) 3. Try to print a receipt. EXPECTED: The receipt is printed on the configured receipt printer. ACTUAL: The receipt is printed on the prepation printer. This was caused by the hardware proxy code assuming that there will only be 1 printer `iot.device` model loaded, and that it will correspond to the receipt printer. The fix is to ensure the hardware proxy only chooses the printer that is configured as the receipt printer. Forward-Port-Of: odoo/enterprise#93225