Wednesday, June 3, 2026
18 changes · saas-19.2
New functionality added to Odoo
This update integrates with Cashmatic, a company providing self-service cash machines, through a new HTTP API connection. This allows Point of Sale (POS) systems to communicate with these machines for automated cash counting and dispensing, streamlining transactions. It's a key addition to support modern payment options.
Original PR description
Cashmatic is a company providing self-service cash machines, which can automatically count cash and dispense change. This commit adds basic support for Cashmatic cash machines via an HTTP REST API connection. Task-5887125 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253585
Resolved issues and error corrections
This update resolves an issue where dropshipping orders incorrectly displayed a negative delivered quantity. The change introduced a new functionality for returns that inadvertently caused this error. The fix ensures accurate delivery quantity calculations by preventing negative values when dropshipping isn't involved.
Original PR description
Currently, an error occurs when the user receives a dropship order instead of delivering it directly to the customer. As a result, the sale order shows a negative delivered quantity. ## Steps to…
Currently, an error occurs when the user receives a dropship order instead of delivering it directly to the customer. As a result, the sale order shows a negative delivered quantity. ## Steps to replicate: - Install Sales, Inventory, and Purchase. - Enable Dropshipping from Inventory settings. - Create a test product with the Dropship route enabled and set a vendor for it in the Purchase tab. - Create and confirm a quotation for a customer. - Go to Purchase > `Deliver To:` and set it to `My Company: Receipts.` - Confirm the Purchase Order and validate the receipt. - Go back to the Sale Order. ## Observed Behavior: The delivered quantity is -1, which is incorrect because the customer has not returned any products, nor has the user created a sale order line with a negative quantity (which would indicate a return). ## Root cause: When computing the delivered quantity at [1], the function `_get_outgoing_incoming_moves` [2] is called to retrieve the incoming and outgoing stock moves associated with the sale order lines. Inside this function, moves are filtered and categorized as incoming or outgoing. At [3], the condition is satisfied because the default value of `to_refund` is `True`, so the move is added to `incoming_move_ids`. Later, during the computation at [1], the code iterates through the incoming moves and subtracts their quantities from the delivered quantity. Since the initial delivered quantity is 0, including such a move in `incoming_move_ids` causes the delivered quantity to become -1. <h3> Why did this behavior not occur in lower versions?:</h3> This issue was introduced by [commit], which added the functionality for users to return products that are not listed in the purchase order. As a result, their quantities appear as negative received quantities on the purchase order. Before this change (in saas-18.2), the field `move.to_refund` had a default value of `False`. Because of this, the condition at [3] was not satisfied, and the move was not included in `incoming_move_ids`. Therefore, it was not subtracted when iterating through incoming moves, and the delivered quantity did not become negative. Starting from 18.3, the default value of `to_refund` was changed to `True`. This causes the condition at [3] to be satisfied, the move to be included in `incoming_move_ids`, and its quantity to be subtracted during the computation, resulting in a delivered quantity of -1. [1]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L193-L209 [2]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L316-L353 [3]- https://github.com/odoo/odoo/blob/1256875226436a854558a1334ffdc886fa4767a8/addons/sale_stock/models/sale_order_line.py#L346-L351 ## Solution: We can make the condition stricter by ensuring that only incoming moves that are actual returns are counted as negative in the quantity delivered on a sale order. Specifically, if an incoming move has no corresponding originating return move and the customer has not created a sale order line with a negative quantity (which could also indicate a return), it should not be considered when calculating the delivered quantity. [commit]: https://github.com/odoo/odoo/pull/209110/changes/c1c86182e4b28e929bf56e79f57f33aaa13e67f1 opw-5933594 Forward-Port-Of: odoo/odoo#267531 Forward-Port-Of: odoo/odoo#252383
This update resolves a bug that caused the 'Missing required fields' error when sending WhatsApp messages. The fix removes a dependency on automatic data pre-filling, ensuring the required fields are only checked when WhatsApp is enabled. This improves the user experience for sending messages via WhatsApp.
Original PR description
**Steps to reproduce** --- 1. Configure a follow-up level with a WhatsApp template with required variables. 2. On a contact open Send and Print. 3. Uncheck WhatsApp (keep Email checked) and click…
**Steps to reproduce** --- 1. Configure a follow-up level with a WhatsApp template with required variables. 2. On a contact open Send and Print. 3. Uncheck WhatsApp (keep Email checked) and click Send. **Issue** --- The wizard raises "Missing required fields" even though the WhatsApp section is hidden. The free-text inputs in the WhatsApp group of the manual reminder wizard are declared with `required="number_of_free_text >= N"` see https://github.com/odoo/enterprise/blob/17231450e90cc7465370b5fe0a138b7f93dde91c/whatsapp_account_followup/wizard/followup_manual_reminder_views.xml#L23-L33 The surrounding group hides them with `invisible="not whatsapp"`, so as soon as a WhatsApp template is loaded on the wizard the fields are required regardless of the WhatsApp toggle. This was masked until https://github.com/odoo/enterprise/commit/47369f696acd5c7e236e527deef890639017f2f1 removed the `_compute_free_text` prefill on `whatsapp.composer`: the free-text fields used to be auto-populated with each variable's demo value, so the required check was trivially satisfied. With the prefill gone the fields start empty and the latent constraint fires whenever WhatsApp is unchecked. Ticket [link](https://www.odoo.com/odoo/project.task/6227911) opw-6227911
This update resolves a technical issue preventing Viva payments in the POS kiosk. The Viva payment system requires a unique identifier for the cash register, and previously, this wasn't consistently provided. Now, the system automatically generates a valid 'cashRegisterId' based on the cashier's name, ensuring Viva payments process correctly.
Original PR description
When validating a payment in POS Kiosk with Viva payment method we get a Viva.com error Viva’s card-terminal API validates the JSON body with Pydantic and requires a non-empty ``cashRegisterId``. Steps to reproduce: ------------------- * Open POS in kiosk * Make an order and pay with Viva > Observation: Viva returns a validation error: ``cashRegisterId`` is missing or required in the request body (Pydantic ``missing`` on ``body.cashRegisterId``). Why the fix: ------------ Compute ``cashRegisterId`` in the POS client as cashier name, then ``pos.config.name`` so the value is always a non-empty string sent to ``viva_wallet_send_payment_request``. opw-6091223 Forward-Port-Of: odoo/odoo#267280 Forward-Port-Of: odoo/odoo#258605
This update fixes an issue where automation rules for sales orders weren't correctly assigning users to newly created activities. The change uses a more robust method to handle relationships between records, ensuring that the intended user is always associated with the activity. This improves the reliability of automated workflows.
Original PR description
Steps to reproduce: ------------------------------------ 1. Install `base_automation` and the Sales module 2. Create an automation rule for a sale order as follows: * Trigger: State set to Sale order…
Steps to reproduce:
------------------------------------
1. Install `base_automation` and the Sales module
2. Create an automation rule for a sale order as follows:
* Trigger: State set to Sale order
* Add a Create Activity action
* Change User Type to Dynamic
* Set User Field to Customer > Users
3. Create and confirm a sale order with Admin as the customer
Observation:
------------------------------------
The activity is created in Chatter, but it was not assigned to any user
Issue:
------------------------------------
The condition `self.activity_user_field_name in record` uses the `__contains__` check which only looks for direct fields on the record's model. A dotted path like 'partner_id.user_id' is not a field name on the record itself, so the check evaluated to `False`, skipping the user assignment entirely https://github.com/odoo/odoo/blob/2bafcebfaba01e46856d6eb2a440ede95b9c0a4a/addons/mail/models/ir_actions_server.py#L378-L379
Solution:
------------------------------------
Use `record.mapped()` as a fallback when the field name is not directly present on the record. `mapped()` natively supports dotted paths by traversing the relational chain (e.g. record -> partner_id -> user_id)
opw-6191715
Related Enterprise PR: https://github.com/odoo/enterprise/pull/118921
Forward-Port-Of: odoo/odoo#263530This update resolves an issue where changes made within nested editable areas of the description field weren't consistently saved. The fix replaces a specific event listener with one that correctly triggers a save when the focus leaves the editable area, ensuring all updates are recorded accurately. This improves the reliability of description updates.
Original PR description
Problem: When the selection is inside a `contenteditable="true"` element that is not the root editable, focusing away does not trigger a save. Cause: When the DOM contains a nested contenteditable…
Problem:
When the selection is inside a `contenteditable="true"` element that is not the root editable, focusing away does not trigger a save.
Cause:
When the DOM contains a nested contenteditable structure like:
```html
<div class="odoo-editor-editable" contenteditable="true">
abc
<div contenteditable="false">
ac
<div contenteditable="true">a</div>
</div>
</div>
```
With the selection inside the inner `contenteditable="true"`, the `blur` event is not triggered on `.odoo-editor-editable` when focusing away, because the active element is the inner div and `blur` does not bubble.
Solution:
Replace the `blur` listener with `focusout`, which bubbles from the inner `contenteditable="true"` up to `.odoo-editor-editable`, allowing `onBlur` to be called correctly.
Steps to reproduce:
- Open Project > Task.
- Add a `/column` block in the description.
- Focus inside any column and write some text.
- Click away to change tab.
- Reopen the description tab.
- The latest changes inside the columns were not saved.
opw-6227922
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#266367This update fixes an issue where manually added analytic distributions on purchase orders were lost when the line's account was changed. Now, when a purchase order line's account is modified, the associated analytic distribution remains intact, ensuring accurate tracking of costs. This prevents data inconsistencies and simplifies reporting.
Original PR description
__ ## Short functional explanation of the error When confirming a Purchase Order holding lines with an analytic distribution that has been manually added, and creating a vendor bill out of this PO…
__ ## Short functional explanation of the error When confirming a Purchase Order holding lines with an analytic distribution that has been manually added, and creating a vendor bill out of this PO using the Auto-Complete field. When we change the account of that line, the line loses the manually added Analytic Distribution. ## Reproduction Steps 1. Go to Accounting. Click on the tab Configuration; under the Analytic Accounting section, click on Analytic Distribution Models. 2. Create an Analytic Distribution Model for a product. 3. Go to Purchase. Create a new PO, set a Vendor and select the product you created the Analytic Distribution Model for. On the right side of the form, click on the view menu and check Analytic Distribution to make it appear. 4. Click on the Analytic Distribution of the product and add a new one; for example, select Administrative in the Departments section. 5. Confirm order. 6. Go to Accounting and click on the Vendors tab > Bills. Create a new bill, and in the field Auto-Complete, select the PO you just created. 7. Change the account of the line. ### Expected behavior Only the account should be changed on the line. ### Unexpected behavior The manually added Analytic Distribution has disappeared. ## Origin of the issue When we change the `account_id` field, the compute method `_compute_analytic_distribution` is triggered. This method retrieves the related distributions of the line: https://github.com/odoo/odoo/blob/af32885ec5f07d492f3b8e8fff1785996a739f72/addons/account/models/account_move_line.py#L1154 which, in the context of Purchase, calls this method: https://github.com/odoo/odoo/blob/af32885ec5f07d492f3b8e8fff1785996a739f72/addons/purchase/models/account_invoice.py#L540-L545 We retrieve the distribution of the related line using `self.purchase_line_id.analytic_distribution`. However, this code isn't triggered when the move line has an analytic distribution, even though the related line `purchase_line_id` might have one! Therefore, we need to execute that code whether or not our move line has an analytic distribution. Note: the same behavior is to avoid when creating invoices for quotations. __ opw-6062466 Forward-Port-Of: odoo/odoo#267274 Forward-Port-Of: odoo/odoo#258380
This update resolves an issue where currency amounts in Arabic RTL (right-to-left) views were incorrectly formatted, appearing with the minus sign positioned to the left of the currency symbol. The fix ensures that currency amounts are displayed correctly, aligning with standard left-to-right formatting in Arabic locales. This improves the user experience for Arabic-speaking users.
Original PR description
Steps to reproduce 1. Create a company with Egypt localization, currency EGP 2. On a bank journal, set Outstanding Receipt and Outstanding Payment accounts 3. Register a customer payment so the…
Steps to reproduce 1. Create a company with Egypt localization, currency EGP 2. On a bank journal, set Outstanding Receipt and Outstanding Payment accounts 3. Register a customer payment so the journal dashboard shows the Payments row with a negative amount 4. Switch the user language to Arabic 5. Open the Accounting dashboard Issue The Payments amount renders as "LE 5,000.00-" instead of "-5,000.00 LE". formatCurrency returns the string "-5,000.00 LE". In an Arabic page the leading "-" has no intrinsic direction, so the browser attaches it to the surrounding right-to-left Arabic text and visually moves it past the symbol. Sibling rows on the same dashboard render correctly because they already wrap the amount in dir="ltr", see https://github.com/odoo/odoo/blob/d0424f2ffcf99ee59befe288150f1643b3fa0112/addons/account/views/account_journal_dashboard_view.xml#L252 opw-6183749 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267582 Forward-Port-Of: odoo/odoo#266742
This update resolves an issue where large product weights (over 150kg) in the e-commerce system caused errors when calculating shipping rates through Sendcloud. The fix ensures that the system accurately determines if multiple packages are needed and correctly processes orders with heavy items, improving order fulfillment reliability.
Original PR description
Issue ----- Traceback when trying to get a rate through the e-commerce if the order has to be split into multiple packages due to weight being too high. Steps to reproduce ----- - Setup Sendcloud…
Issue ----- Traceback when trying to get a rate through the e-commerce if the order has to be split into multiple packages due to weight being too high. Steps to reproduce ----- - Setup Sendcloud delivery method - make it available in e-commerce - Create a 150kg product and publish it - Go to e-commerce - Add the product to cart - Checkout the cart > Traceback Cause ----- We retrieve the order's weight through the context. https://github.com/odoo/enterprise/blob/d9a9339e1f30f1e5cc37ebb88949451a6652f83b/delivery_sendcloud/models/delivery_carrier.py#L108 If the call to `_get_shipping_rate` returns that the delivery requires multiple packages, we go into https://github.com/odoo/enterprise/blob/d9a9339e1f30f1e5cc37ebb88949451a6652f83b/delivery_sendcloud/models/delivery_carrier.py#L126-L128 If `order_weight` was not present in the context, this will cause an error in `sendcloud_convert_weight` since it expects a numerical value but receives the `None` fallback. This context key is only present when going through `choose.delivery.carrier` (so not in the e-commerce flow). https://github.com/odoo/odoo/blob/058e640e6687ed3f709dc846f0fa7a1f45226849/addons/delivery/wizard/choose_delivery_carrier.py#L69 ----- Ticket: opw-6210398 Forward-Port-Of: odoo/enterprise#119048 Forward-Port-Of: odoo/enterprise#117028
This update resolves an issue where importing Peppol XML invoices through newly created purchase journals (using only the Invoicing app) fails due to a missing default account. The fix automatically assigns a default account, mirroring the behavior for bank/cash journals, ensuring successful invoice imports.
Original PR description
When a user installs only the Invoicing app and creates a new purchase journal, no default_account_id is set on the journal. The Invoicing app does not expose account configuration, so the user…
When a user installs only the Invoicing app and creates a new purchase journal, no default_account_id is set on the journal. The Invoicing app does not expose account configuration, so the user cannot fix this manually. As a result, importing a Peppol XML invoice through that journal fails with a database constraint error because the generated account.move.line has a null account_id. https://github.com/odoo/odoo/blob/16245530f0e3e9be21c8b96baaecd3a679420cac/addons/account/models/account_journal.py#L776-L805 This already auto-creates accounts for bank/cash journals, but does nothing for sale/purchase journals. Steps to reproduce: - Install the Invoicing app (no full Accounting) - Create a new purchase journal with type 'purchase' - Go to Vendors -> Bills and Upload a Peppol XML file - Error importing attachment as invoice (decoder=_import_invoice_ubl_cii) Ticket [link](https://www.odoo.com/odoo/action-4043/6014363) opw-6014363 Forward-Port-Of: odoo/odoo#267552 Forward-Port-Of: odoo/odoo#252859
This pull request resolves an error preventing CFDI (Mexican tax) documents from being generated correctly when an employee has an IMSS disability. The fix adds the required 'Incapacidades' node to the XML, accurately reflecting disability time off and ensuring compliance with Mexican law. This prevents validation failures and ensures accurate tax reporting.
Original PR description
Several error are logged in the chatter when signing a payslip that includes an IMSS disability time off. Steps to reproduce: * Install l10n_mx_hr_payroll_account modules * Switch to "INNOVACION…
Several error are logged in the chatter when signing a payslip that includes an IMSS disability time off.
Steps to reproduce:
* Install l10n_mx_hr_payroll_account modules
* Switch to "INNOVACION VALOR Y DESARROLLO SA SA" company
* Go to Employees and open Cesar Osbaldo Cruz Solorzano
* Click on "Time Off" smart button and create a new time off with "Disability due to illness (IMSS)" type for "02/01/2026"(Any date).
* Go to Payroll > Payslips > Payslips and create a new pay run
* Select Salary Structure 'Mexico: Regular Pay', Pay Schedule 'Monthly' and the Period '01/01/2026 -> 01/31/2026'
* Click on Continue, select Cesar and click on Select
* Open the payslip, click on "Validate" and "Ok"
* Mark as paid, open the "Journal Entry" from the smart button and click on "Post".
* Back to the payslip, and click on "Generate CFDI" button.
* An error is added to the chatter.
### Missing node to declare disabilities
Original message
```py
An error occurred while signing the CFDI document with the government:
Code : NOM111 Message : Error no clasificado. Extra Info : El nodo
"Incapacidades" se debera informar si se incluye en percepciones la
clave 014 "Subsidios por Incapacidad" o bien en deducciones la clave 006
"Descuento por incapacidad".
```
Translated message
```py
An error occurred while signing the CFDI document with the government:
Code: NOM111 Message: Unclassified error. Extra Info: The "Incapacidades"
(Disabilities) node must be reported if the perception key 014
"Subsidios por Incapacidad" (Disability Subsidies) is included, or if
the deduction key 006 "Descuento por incapacidad" (Disability Deduction)
is included.
```
Legal Context:
According to Mexican law, IMSS disabilities must be declared in a specific XML node.
There are two primary scenarios for reporting these amounts:
* Deduction (Type 006): The employer does not pay for these days, as the IMSS is responsible for the payment to the employee.
This is the most common scenario.
* Perception (Type 014): The employer pays for these days as a superior benefit. For example, by law, the IMSS does not pay for the first 3 days of a disability due to illness, and employers are not obligated to cover them either. However, companies offering superior benefits may choose to pay these days as a "Disability Subsidy."
Solution:
The chosen approach is to configure the Deduction node.
For the `l10n_mx_regular_pay_imss_disabilities` rule, the `l10n_mx_concept` has been set to `l10n_mx_concept_d6` (D06 - Disability Deduction). This ensures the required node is added.
### Missing "ImporteMonetario" attribute
Original message
```
An error occurred while signing the CFDI document with the government:
Code : NOM95 Message : El atributo Deduccion:Importe no es igual a la
suma de los nodos Incapacidad:ImporteMonetario, ya que la clave
expresada en Nomina.Deducciones.Deduccion.TipoDeduccion es "006".
```
Translated message
```
An error occurred while signing the CFDI document with the government:
Code: NOM95 Message: The attribute "Deduccion:Importe" does not match
the sum of the "Incapacidad:ImporteMonetario" nodes, as the key
expressed in "Nomina.Deducciones.Deduccion.TipoDeduccion" is "006".
```
Problem:
The "Incapacidades" node requires the "ImporteMonetario" attribute, which should represent the sum of the monetary value associated with the disabilities.
Solution:
Add the "ImporteMonetario" attribute and calculate its value using `l10n_mx_daily_salary`.
### Invalid "DiasIncapacidad" format
```py
An error occurred while signing the CFDI document with the government:
Code : 301 Message : XML mal formado Extra Info : Element
'{[http://www.sat.gob.mx/nomina12}Incapacidad](http://www.sat.gob.mx/nomina12%7DIncapacidad)', attribute
'DiasIncapacidad': '4.0' is not a valid value of the local atomic type.
```
Problem:
Altough the defaultdict where the values are sum up, `number_of_days` is
a float field, and when we get back the value, it is a float, adding for
example 4.0 instead of 4, which is not a valid value.
Solution:
Cast the value to int.
### Duplicate deduction on disabilities
```py
Wrong python code defined for:
- Employee: Cesar Osbaldo Cruz Solorzano
- Version: False
- Payslip: Salary Slip - Cesar Osbaldo Cruz Solorzano - 05/01/2026 - 05/15/2026
- Salary rule: ISR (Income Tax) (ISR)
- Error: TypeError('cannot unpack non-iterable NoneType object') while
evaluating
"
def find_rates(x, rates):
for low, high, fix, rate in rates:
if low <= x <= high:
return low, high, fix, rate
gross = categories['GROSS']
result = 0
if gross:
isr_table = payslip._rule_parameter('l10n_mx_isr_tables')[version.schedule_pay]
low, high, fix, rate = find_rates(gross, isr_table)
result = -((gross - low) * rate + fix)
period_factor = payslip._rule_parameter('l10n_mx_schedule_table')[version.schedule_pay]
if period_factor >= 15:
period_factor = (period_factor / 30) * (365 / 12)
min_wage = payslip._rule_parameter('l10n_mx_daily_min_wage') * period_factor
if gross <= min_wage:
result_qty = 0.0
"
```
Problem:
The IMSS disability amount is being deducted twice:
1. During "Worked Days" calculation, the IMSS disability is already not considered because the work entries belong to the "Unpaid Work Entry Types" of "Mexico: Regular Pay" structure.
2. During "Salary Computation", the `IMSS_DISABLE` salary rule deducts another time because it is in the `TAXABLE_ALW` category, and this one is deducted in the `NET` rule.
When the disability covers more than half of the period (e.g., 20 days in a monthly schedule), the double deduction causes the NET to become negative. This prevents the ISR rule from finding a correct stage in the tax tables, leading to a traceback.
Example: For a monthly wage of 30,000.0 and 5 disability days:
- The total amount in "Worked Days" is 25,000.0 (disabilities already deducted).
- The IMSS_DISABLE rule calculates -5,000.0, and when the NET rule is calculated, the disabilities are deducted again. Total NET becomes 16,843.84 instead of the expected 20,834.85.
Solution:
Change the rule category to `INTERMEDIARY_COMPUTATION` and avoid the double deduction when the `NET` is calculated, as it is already considered in the "Worked Days".
### Incorrect values in the XML
The signing process completes without errors, but some amounts in the generated XML are incorrect.
Problem:
The introduction of the Deduction 006 (Disability) directly impacts the calculation of the SubTotal and Total attributes in the Comprobante node.
For a monthly payslip with a wage of 30,000.00 (daily salary of 1,000.00) and 5 disability days (work risk), the values are calculated incorrectly as follows:
Attribute | Calculation | Actual Value | Correct Value
---------------------|----------------------------------|--------------|--------------
Comprobante:SubTotal | Sum of Perceptions (P01) | 25000.00 | 30000.00 (1)
Comprobante:Total | SubTotal - Total Deductions (2) | 15803.74 | 20803.74
(1) Must include the 5,000.00 from disabilities to balance the deduction.
(2) Total Deductions = D06 (5,000.00) + ISR (3,451.65) + IMSS (744.61) = 9,196.26.
The Total is currently undercalculated because the 5,000.00 is being
deducted from the SubTotal that already had those 5,000.00 excluded.
Solution:
Since the `SubTotal` is derived from Perceptions, and the "(P01)
Salaries, Wages, Stripes, and Day Labor" amount is driven by the
`GROSS_WITHOUT_HOLIDAY` rule, the disability amount must be added. This
balances the Deduction 006, ensuring `SubTotal` is correct.
### Absenteeism and Disabilities
By law, the calculation of IMSS contributions depends on these two types of unpaid days:
* Disabilities: Refers to medical leave issued by the Institute (IMSS).
* Absenteeism: Refers to unjustified leave; apply for periods of fewer than 8 days.
Source: [Artículo 31](https://www.imss.gob.mx/sites/all/statics/pdf/leyes/LSS.pdf)
Translated text:
Article 31. When wages are not paid due to the employee's absence from work, but the employment relationship persists, the monthly contribution shall be adjusted according to the following rules:
I. If the employee's absences are for periods of fewer than eight consecutive or non-consecutive days, contributions shall be calculated and paid for such periods only for the sickness and maternity insurance...
If the employee's absences are for periods of eight consecutive days or more, the employer shall be released from the payment of employer-employee contributions...
IV. In the case of absences covered by medical disabilities issued by the Institute, it shall not be mandatory to cover the employer-employee contributions, except regarding the retirement branch.
The following table summarizes the contribution requirements based on the type of absence:
Insurance Branch (RAMA) | Section I (Absenteeism) | Section IV (Disability)
--------------------------------|-------------------------|------------------------
Sickness and Maternity | Paid | Not Paid
Disability and Life | Not Paid | Not Paid
Severance and Old Age | Not Paid | Not Paid
Work Risk | Not Paid | Not Paid
Daycare and Social Benefits | Not Paid | Not Paid
INFONAVIT | Not Paid | Paid
Retirement | Not Paid | Paid
The type of unpaid day to be considered depends on the specific insurance branch being calculated within the employer-employee contributions.
### Add test for cfdi with disabilities.
target: 19.0
task-6066160
Forward-Port-Of: odoo/enterprise#116819This update resolves an issue where time off requests with the 'Both' approval type didn't send notifications to the designated responsible parties (e.g., Time Off Officer). The fix ensures that notifications are correctly sent, streamlining the approval process and preventing delays. This improves the reliability of the HR leave management system.
Original PR description
…cer') no fallback for responsible_ids
Issue:
When ('both','By Employee's Approver and Time Off Officer') is selected on a new HR Leave Type it does not fall back to the responsible_ids or “Notify HR”.
Steps:
1) Setup a neutralized outgoing mail server
2) install hr_holidays
3) make a new hr.leave.Type (Approval) with ('both','By Employee's Approver and Time Off Officer') and select a 'Notified Time Off Officer'(responsible_ids) 4) select an emplyee with a reelated user and remove the coach, manager, and responsible 'Time Off'. 5) save
6) Sign in as the employee, make a time off request under the new Type 7) No email
Fix:
Add a conditional with the lowest priority to fall back to responsible_ids
opw-6101637
Forward-Port-Of: odoo/odoo#265075
Forward-Port-Of: odoo/odoo#261853This update fixes an issue where purchase bills were created in the company's default currency, regardless of the original purchase order's currency. Now, bills automatically inherit the currency from the corresponding purchase order, ensuring accurate financial reporting and reducing potential discrepancies. This improves the reliability of our accounting processes.
Original PR description
**Steps to reproduce:** - create a storable product - confirm a PO in another currency than the main for this product - click on the "bill matching" smart button - select only the purchase order line from your PO - click on match **Current behavior:** this creates on Bill in the main currency **Expected behavior:** the currency should be inherited from the POL **Cause of the issue:** Inside action_match_lines() if there is no amls selected we call _action_create_bill_from_po_lines(). https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/addons/purchase/models/purchase_bill_line_match.py#L157 Inside this method, there's currently no mechanism to take the currency from the POL when we create the bill. **fix:** If multiple different other currencies we take the main currency of the company opw-6131314 Forward-Port-Of: odoo/odoo#266013
This update ensures that duplicated website pages accurately reflect the most current content, regardless of the user's language setting. Previously, duplication didn't account for 'delayed translations,' leading to outdated versions. Now, the system correctly uses the latest translation data for duplicated pages.
Original PR description
**Steps to Reproduce:** 1. Configure the website default language different from the user’s current language. 2. Go to Website → Site → Pages. 3. Duplicate an existing page. 4. Edit the duplicated…
**Steps to Reproduce:**
1. Configure the website default language different from the user’s current language.
2. Go to Website → Site → Pages.
3. Duplicate an existing page.
4. Edit the duplicated page and save the changes.
5. Duplicate the edited page again.
6. Observe that the newly duplicated page is generated from the original page content instead of the updated duplicated page.
**Issue:**
When duplicating a website page, the website default language was not passed in the context. As a result, the duplication was performed using the active user language.
The root cause is that `copy()` does not simply duplicate the existing `arch_db` translation dictionary. Instead, it copies the field value in the current language and then rebuilds all translations through `copy_translations()`.
This behavior becomes problematic when `delayed translations` are involved. After a page is modified in a non-default language, the latest changes may be stored in a delayed translation entry (`_{lang}`) while the regular translation value remains unchanged. During the copy process, these delayed translation entries are intentionally discarded because they are considered temporary data and are not treated as valid language translations.
As a result, when the page is duplicated from a non-default language, `copy()` rebuilds the translations using an outdated translation value instead of the most recent content stored in the delayed translation. The newly
duplicated page therefore does not accurately reflect the current state of the source page.
**Solution:**
The fix enables `check_translation=True` during page duplication so that the copy operation uses the latest translation state, including delayed translations when available. This ensures duplicated pages are generated
from the most recent version of the source page and keeps translated content consistent across languages.
**opw-5914281**
Forward-Port-Of: odoo/odoo#264656This update fixes an issue where group allocations with past start dates incorrectly showed zero accrual amounts. The change ensures that accrual calculations are properly triggered when group allocations are created, regardless of the start date, ensuring accurate time-off tracking. This improves the reliability of the group allocation feature.
Original PR description
Problem ------------------ When creating group allocations, when the allocation type is accrual and the start date is set in the past, the newly created allocations have the accrual amounts at 0. To…
Problem ------------------ When creating group allocations, when the allocation type is accrual and the start date is set in the past, the newly created allocations have the accrual amounts at 0. To reproduce: 1. Create an accrual plan with an easily measurable milestone (e.g. 1 day every day) 2. From the allocations view -> New Group Allocation 3. Enter the following values: Grant -> By Employee Employees -> select your employee Time Off Type -> Paid Time Off (doesn't matter too much) Allocation Type -> Based on Accrual Plan Validity Period -> any date a few days in the past (Personally I tested with 1/1/2025 and no end date) Allocation -> Keep at 0 Allocate Time Off 4. Go to the newly created allocation The allocation amount is 0. Reason ---------------------- When creating group allocations, the `hr.leave.allocation.generate.multi.wizard` calls the `_process_accrual_plans()` method to compute the accruals, but when the allocations are created, the nextcall and lastcall fields are set, so the accruals are not computed and the scheduled action also does nothing until the nextcall date. The onchange method manually sets the nextcall date to False so the accruals are processed. Solution ------------------ Created a method to get the fields that need to be set to calculate the initial accrual amounts from the start date, which is called both in the onchange and to batch write in the wizard before accrual plans are processed. The wizard checks the duration values before overwriting the number_of_days field, since user manually setting the amount should overwrite the calculations. task-4938695 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#267305 Forward-Port-Of: odoo/odoo#265783
This update ensures that mass mailing background colors remain consistent across emails, even after website color palettes are updated. Previously, changes to primary colors would cause emails to display the new color, but this fix removes the conflicting class, guaranteeing the designed color is always used. This improves email consistency and brand alignment.
Original PR description
When a mass mailing block uses a `bg-o-color-N` theme color class, the mailing's `body_arch` stores the class and `convert_inline` correctly inlines the resolved color into `body_html`, matching the…
When a mass mailing block uses a `bg-o-color-N` theme color class, the mailing's `body_arch` stores the class and `convert_inline` correctly inlines the resolved color into `body_html`, matching the website palette at save time. The class also stays on the element in `body_html`. The stylesheet rule that gives `bg-o-color-N` its color is declared with `!important`. When the website palette is later rebuilt (any change to the primary colors), the new `bg-o-color-N` rule wins over the inline color whenever `body_html` is rendered. So an already-sent mailing reopened in the backend shows the new palette's color instead of the one that was picked, and resaving the mailing bakes that new color into `body_html`. `classToStyle` already does the right thing for the property value. What was missing is dropping the class itself from `body_html` once its style has been inlined, so no future `!important` palette rule can override the inline color. `body_arch` keeps the class, so the editor preview stays theme-aware while editing, but `body_html` is now stable across palette rebuilds. Steps to reproduce: 1. Open Email Marketing and create a new mailing using the Welcome Message template 2. Select a content block, open Customize, set the background to the 5th theme color 3. Save the mailing 4. Open the Website editor and change the 5th primary color to a different value 5. Reopen the saved mailing in the backend => the block's rendered background follows the new website color instead of the one picked at design time Ticket [link](https://www.odoo.com/odoo/project.task/5892350) opw-5892350 Forward-Port-Of: odoo/odoo#267570 Forward-Port-Of: odoo/odoo#253934
This update fixes a bug preventing the 'NABN' document type from being used for GT vendor credit notes. Previously, this option was restricted to regular vendor bills. Now, users can correctly select 'NABN' when reversing a GT credit note, ensuring accurate electronic payment processing according to local regulations.
Original PR description
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Navigate to Invoicing > Vendors > Bills. - Create a new vendor bill. - Observe that `GT Document Type`…
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Navigate to Invoicing > Vendors > Bills. - Create a new vendor bill. - Observe that `GT Document Type` includes `NABN - Nota de Pago Electrónica` option. - `Confirm` the bill. - Click `Credit Note`, add a reason, and click `Reverse`. - Observe the available options in the `GT Document Type` field. **Observation:** The `NABN - Nota de Pago Electrónica` option is not available for vendor credit notes (`in_refund`), even though `NABN` is a GT-specific credit note document type. **Root Cause:** At [1], `NABN` is added for vendor bills (`in_invoice`, `in_receipt`) instead of vendor credit notes (`in_refund`). **Fix:** This commit ensures users can correctly select `NABN - Nota de Pago Electrónica` on GT vendor credit notes. [1]: https://github.com/odoo/enterprise/blob/c7fa8c9c6f6830f5702fab4f6efaf3ac33f7fe72/l10n_gt_edi/models/account_move.py#L159-L160 opw-6252256 Forward-Port-Of: odoo/enterprise#119215 Forward-Port-Of: odoo/enterprise#118711
This update fixes an issue where EDI invoices were incorrectly assigned to individual contacts due to shared VAT numbers. The change prioritizes main companies and active vendors during matching, ensuring invoices are routed to the correct business entity. This improves data accuracy and reduces manual intervention in invoice processing.
Original PR description
### Description of the issue/feature this PR addresses: **Issue:** When processing incoming EDI/Peppol invoices, multiple contacts (parent companies, joint ventures, child contacts) frequently share…
### Description of the issue/feature this PR addresses: **Issue:** When processing incoming EDI/Peppol invoices, multiple contacts (parent companies, joint ventures, child contacts) frequently share the same VAT number. Because the parser's tie-breaker relies primarily on VAT, invoices are often incorrectly assigned to individual child contacts or newly created joint ventures rather than the correct vendor. **Solution:** Prepend is_company DESC, supplier_rank DESC to the SQL search order in the _import_retrieve_customer fallback domain. This ensures that the matching logic explicitly prioritizes business entities over individual contacts, and active vendors over other records. ### Current behavior before PR: When searching by VAT with limit=1, the parser uses order='company_id, parent_id DESC, id DESC'. If a parent company and a child contact share a VAT, the query frequently returns the child contact or a newer joint venture due to the id DESC fallback. ### Desired behavior after PR is merged: The parser will correctly prioritize main companies over individual contacts when VAT numbers are shared. If multiple companies share the same VAT, the most active vendor will be selected. opw-6174628 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#266224