Daily updates from Odoo
Wednesday, March 18, 2026
10 changes · 18.0
New functionality added to Odoo
This update introduces a new report for Polish businesses that still need to file JPK_FA reports even when using the KSeF online invoicing system. The JPK_FA report generates an XML file listing invoices and lines not yet validated by KSeF, ensuring compliance with Polish tax regulations. This addition supports businesses adhering to older invoicing practices.
Original PR description
In Poland, if a business chooses to keep B2C invoicing outside of KSeF (online platform), the JPK_FA obligation remains. It is a XML report that lists all the invoices and the invoice lines that have not been validated by KSeF during a desired period of time. The report follows the JPK-FA(4) norms. task-5166047
Resolved issues and error corrections
This update resolves an issue where the bank statement import process would fail when the currency in a CAMT file didn't match the bank's journal currency. The fix now validates for missing currency data, preventing errors and ensuring accurate bank statement imports. This improves the reliability of the import process.
Original PR description
Currently, an error occurs when the currency in the CAMT file differs from the bank journal currency. **Steps to reproduce:** - Install `account_bank_statement_import` module. - Create a new country…
Currently, an error occurs when the currency in the CAMT file differs from the bank journal currency. **Steps to reproduce:** - Install `account_bank_statement_import` module. - Create a new country with EUR as currency and switch to it. - In the Bank journal, upload this CAMT file: https://drive.google.com/file/d/1hKZIUPwdtcWAvxcoTLPFGpW-F5LnqDy9/view?usp=drive_link **Error:** `TypeError - unsupported operand type(s) for /: 'NoneType' and 'float'` **Cause:** When the `<Bal>` or `<Ntry>` amounts in the CAMT file are in a different currency, `get_value_and_currency_name` [1] cannot fetch a matching amount for the journal currency. This returns `None`, which leads to an invalid division during exchange rate computation. **Fix:** This commit handles missing currency data in CAMT files by raising a validation error instead of throwing a traceback. [1] - https://github.com/odoo/enterprise/blob/e7ae981000a4e53dc608c76605d8b2dbfb972c6a/account_bank_statement_import_camt/lib/camt.py#L632-L638 sentry-6874016845
This update corrects an issue where the QR code generated for self-ordering pickup orders incorrectly included table information in the downloaded PDF. The fix ensures QR codes are generated without table IDs, resolving a problem that prevented proper order scanning at the pickup zone. This improves the reliability of the self-ordering process.
Original PR description
Step to reproduce: - setup Restaurant and do the following config - set "self-ordering" -> "Qr Menu + Ordering" - set "service At" -> "pickup zone" - save and print the qr-code ( option is right there below these configs) Observation: - in downloaded pdf, we see a wrong url, which includes table_id, which shouldn't be. - QRs do not have table_id Cause: - there is issue in `generate_qr_codes_page` method, which uses table_id even if ordering mode is "pickup zone" Fix: - we only use table_id when ordering_mode = 'table'. **Before:** <img width="1002" height="397" alt="image" src="https://github.com/user-attachments/assets/e6dc50e5-6384-45b8-8ee5-817526769dc2" /> **After** <img width="1021" height="405" alt="image" src="https://github.com/user-attachments/assets/0be9b902-3870-4fc7-a409-e01265b7a1b3" /> opw-5095607 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247184
This update resolves an issue preventing new employee creation when generating the BVG-LLP Basis Declaration report. The fix addresses a technical problem related to how Odoo processes multiple reports with the same month, ensuring correct employee data is recorded. This improves the reliability of payroll reporting for Swiss companies.
Original PR description
Steps to reproduce: ---------------------------------- 1. Install `l10n_ch_hr_payroll_elm_transmission` module 2. Switch to Swiss company 3. Navigate to Payroll > Transmission > BVG-LLP Basis…
Steps to reproduce:
----------------------------------
1. Install `l10n_ch_hr_payroll_elm_transmission` module
2. Switch to Swiss company
3. Navigate to Payroll > Transmission > BVG-LLP Basis Declaration
4. Create two Reports with same Year and Month
5. Now try to create new Employee from the employee app
Observation:
----------------------------------
Tracaback Occurs:
```
File '/home/odoo/src/enterprise/19.0/l10n_ch_hr_payroll/models/l10n_ch_employee_monthly_values.py', line 319, in _compute_bvg_lpp_annual_basis
existing_declaration = max(existing_declaration, key=lambda r: r.month) if existing_declaration else False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/src/odoo/19.0/odoo/orm/models.py', line 5934, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: l10n.ch.lpp.basis.report(1, 2)
```
Issue:
----------------------------------
In the following code:
https://github.com/odoo/enterprise/blob/44a26539093f9313d9cd5f823c11866e3c98ec97/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_employee_monthly_values.py#L319-L320
Python's max() function doesn't just call the key function once per item. When there are ties (equal key values), it may need to compare the original objects, and during this process, Odoo's recordset operations combine records, causing the lambda receives `r` as a combined recordset. To access `.month` on a multi-record recordset it gives singleton error.
Solution:
----------------------------------
Creates tuples of (month, recordset) pairs and uses max() to compare month integers directly, avoiding the singleton error.
opw-5391742
Forward-Port-Of: odoo/enterprise#102335This update corrects a bug in the Odoo portal's task search functionality. Previously, searching by assignees didn't return accurate results due to a naming error in the search criteria. This fix ensures that tasks assigned to a specific user are correctly displayed when searching by assignee, improving user task visibility.
Original PR description
# How to reproduce - On the website go to My Account > Tasks - In the search bar, select Search In Assignees - Search for an assignee # The problem Nothing shows up even if the is a task with the assignee that was searched # Why In the dictionnary of the different possible searches, the name of the Search in Assignee entry was "users" instead of "user_ids" opw-5503738 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a problem where Amazon listings were incorrectly syncing stock levels, leading to phantom orders. The fix allows users to manually specify the fulfillment channel (FBA or FBM) for each listing, resolving a known 'ghost listing' issue. This ensures accurate stock management and order fulfillment on Amazon.
Original PR description
When configuring a listing on Amazon Seller Central, the user must choose **one** of the available fulfillment channels that Amazon offers. We distinguish two kinds: Fulfillment by Amazon (FBA) and…
When configuring a listing on Amazon Seller Central, the user must choose **one** of the available fulfillment channels that Amazon offers. We distinguish two kinds: Fulfillment by Amazon (FBA) and Fulfillment by Merchant (FBM). However, Amazon suffers from a known issue of ghost listings. A ghost listing occurs when an offer is presumably sold via FBA, but in fact stores stock information for both FBM and FBA creating unwanted FBM orders. To avoid ghost listings, the first solution was to disable stock synchronization as soon as an offer contained stock in the Amazon location of Odoo. However, if a merchant decided to change the fulfillment channel, it became impossible to sync the stock anymore. See also e7c01c7097d90e731c5408cee4d3595ed810c8fa. To resolve this issue, we decided to use the Amazon API to fetch information about the fulfillment channel of a listing. However, Amazon doesn't give a clear answer for a given listing. Therefore, after some research, the assumption was that an offer was FBM if the listing contained a `merchant_shipping_group`, as the merchant shipping group is a setting specific to FBM listings. See also e6d620e4b200cadabb00ce37ab03289cfeb4ae58. However, this assumption was flawed because Amazon can keep the shipping group even if the listing switches to FBA. This in turn enabled stock synchronization, leading to ghost listings. To fix this issue we give the possibility to users to manually set the correct fulfillment channel of an offer when it becomes ambiguous. opw-5480254 See also: - https://github.com/odoo/upgrade/pull/9692 Forward-Port-Of: odoo/enterprise#106662
This update corrects a bug where compensation account move lines weren't created for dropshipped products when the purchase price differed from the bill price. The fix ensures accurate accounting for these transactions, preventing valuation discrepancies and ensuring proper expense recognition. This impacts dropshipping functionality.
Original PR description
**Problem:** compensation amls are not created for dropshipped products when there is a difference between the price of the PO and the price on the bill **Context:** For non dropship avco real time…
**Problem:** compensation amls are not created for dropshipped products when there is a difference between the price of the PO and the price on the bill **Context:** For non dropship avco real time products: When you create a PO for a product @ 10 - stock interim received is credited of 10 - stock valuation is debitted of 10 And you then validate a bill for a price of 8 - stock interim received is debitted of 8 - account payable is creditted of 8 This leaves stock interim received with credit of 2 and stock valuation is over valued by 2. So we create 2 extra account move lines - One debit of 2 for stock interim received - One credit of 2 for stock valuation (or Expenses if the product is not in stock anymore because then it's the expense account which was over valuated) nb: if the product is still in stock those 2 lines are created via stock valuation layer In the case of a dropshipped product, the product is not in stock anymore so it should be creditting expense, but no extra amls are created at all. **Steps to reproduce:** - enable the "dropshipping" and "anglo saxon accounting" settings - create a storable product with avco automated category - in the inventory tab, select the dropship route - in the purchase tab, set a vendor - create and a confirm a quotation for this product - on the linked purchase order, set a unit price of 10$ and confirm - validate the dropship move - create a bill for the purchase order - set the price to 8$ and confirm - navigate to journal items and search for your product **Current behavior:** no compensation account move lines were created **Expected behavior:** 2 account move lines should have been created: - One debitting 2 in stock interim received - One creditting 2 in expense **Cause of the issue:** *the following logic was introduced by* https://github.com/odoo/odoo/pull/126536 to create those extra amls and layers, _apply_price_difference() is called inside _post() https://github.com/odoo/odoo/blob/32408a8dea43f57bba1a56c775ae228131720749/addons/purchase_stock/models/account_invoice.py#L129 There we have 2 problems : Problem 1: When fetching the layers linked to the account move line, we fetch both the incoming and the outgoing valuation layers because they are both linked to the dropship move. https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L46 But we only want the incoming layer because the outgoing layer should not interfere with the bill. nb: In a standard case like the one of the steps to reproduce, it would work to leave both layers, but : - it works for the wrong reasons : the quantity of the aml would first be consumed on the incoming layer and nothing would happen with the second layer as the quantity of the incoming layer is the same as the one of the aml. - it would probably break in more complex use cases. So it feels unnecessarily risky to leave it like that. Problem 2: Inside _generate_price_difference_vals we call _replay_history which returns two values that are assigned to two variables. https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L82 The second variable, layers_and_invoices_qties is a default dict which keys are tuples (layer L, invoice I) mapped with [the initial quantity invoiced by I on L, the remanining qty invoiced by I on L] (here 'remaining' is related to invoice and has nothing to do with stock qties) https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L168-L171 So in our very basic use case, with a single invoice and a single layer, we should have a key (our layer, our invoice) linked to the value [1,1]. But this key is not in the dictonary. *The reason is the following :* inside _replay_history the parameter "history" contains the layers and the amls (in our case 1 layer and one aml which is self). Each layer is added to qty_to_invoice_per_layer https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L177-L178 https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L191-L192 Then, for each aml: the layers are added to layer_to_consume, alongside their remaining quantity. https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L215-L221 And for each layer which has a quantity billed by the invoice, a key is added to layers_and_invoices_qties https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L222-L231 In our case, the move linked to the layer is the dropship move so _is_in() will be false and the layer won't be added to layers_to_consume. https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L220-L221 So the key will not be created. *The consequence is the following:* Later in _generate_price_difference_vals() we acces the value of this key (the key that should be there (layer, invoice)) https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L91 to get the invoiced qty which will later be used to determine which quantity is still in stock and which is out of stock (giving us the quantities for the compensation layers and amls) but as the key does not exist, invoicing_layer_qty will have a value of 0 so we will exit the loop and no amls or svls will be created https://github.com/odoo/odoo/blob/455b289abd691ccb274dfce43c1b4347add20a41/addons/purchase_stock/models/account_move_line.py#L92-L93 opw-5498878
This update ensures that Odoo generates the correct XML format for Swiss payment transactions (iso20022_ch) according to industry standards. It addresses a mismatch in the XML schema used for payment validation, ensuring compliance with Swiss banking regulations and accurate payment processing. This resolves an issue where the payment XML was not properly structured.
Original PR description
**PROBLEM** According to documentation (https://www.six-group.com/dam/download/banking-services/standardization/sps/ig-credit-transfer-sps-2025-en.pdf) PstlAdr must be structured. This isn't the case when generating a xml for the payment method iso20022_ch. **STEP TO REPRODUCE** 1. install l10n_ch and account_iso20022. 2. Create a swiss contact with a full address. And activate payment on the bank account of this contact. 3. Select the Company CH, and set a bank account in the bank journal configuration. 4. Create a vendor payment to the swiss contact. 5. Create a batch payment with it, and validate to get the xml. 6. Open the xml, and notice the PstlAdr isn't structured. Ticket [link](https://www.odoo.com/odoo/project.task/5880247) opw-5880247
This update ensures that reason messages provided by Public Administrators when refusing invoices are now displayed on the invoice header. Previously, these messages were ignored. This change aligns with Italian tax regulations (Fattura Elettronica) and provides clearer information for users.
Original PR description
When a Public Administrator business refuses an invoice, they also give a reason message (EsitoCommittente/Descrizione), which comes through the IAP to Odoo as an XML tag aside the Outcome code (EsitoCommittente/Esito). Before this PR, the message was ignored, now we show it in the invoice's header. ref: https://www.fatturapa.gov.it/export/documenti/messaggi/v1.1/MessaggiTypes_v1.1.xsd <img width="823" height="232" alt="image" src="https://github.com/user-attachments/assets/8f222f6b-1615-4dd2-a5dd-25e0991ea037" /> <img width="942" height="206" alt="image" src="https://github.com/user-attachments/assets/cdf109ff-40d0-4c50-bdc7-51fb4ea15c98" /> Ticket [link](https://www.odoo.com/odoo/project.task/6041276) opw-6041276
This update fixes a vulnerability where email bots could automatically cancel meetings by visiting links in emails. We've changed how meeting acceptance and cancellation links are sent, now using post requests that email bots cannot trigger. This ensures meetings are only cancelled by users who explicitly click the 'decline' button.
Original PR description
Mails are sent to users containing an acceptation and cancellation link that accepts GET requests but performs an action on visit Some mail defender software analyzes urls in links by actually visiting the URL. This leads to both actions being triggered without user input. Instead we now send buttons with a neutralizing parameter in the mail. Recipients may then visit the url and click a form button to "accept" or "decline". As these are post requests, the email bots should avoid clicking them. task-4555579 Forward-Port-Of: odoo/odoo#198560