Wednesday, September 9, 2026
2 changes · 18.0
Enhancements to existing features
Point of Sale sessions with many pay-later customer balances now close more reliably by limiting reconciliation work to the relevant open items. This prevents excessive memory use and worker crashes while keeping the resulting payments and balances the same.
Original PR description
At session close, the pay later receivable lines are reconciled with every unreconciled posted line of the same partners in the PoS journal and PoS invoices, searched with no bound. A customer buying…
At session close, the pay later receivable lines are reconciled with every unreconciled posted line of the same partners in the PoS journal and PoS invoices, searched with no bound. A customer buying on credit accumulates one open line per order and none of them is ever matched until a settlement comes in, so this set only grows. On a database with 48k open items for a single partner, the close hands `_reconcile_plan` 55k lines over 28k moves; `_sync_dynamic_lines` then evaluates `m.line_ids.tax_ids` on every move of the container, prefetching the 262k lines of those moves. That is about 1 GiB: the worker is killed and the session cannot be closed. All of this to reconcile nothing most of the time: reconciliation only pairs opposite signs, and a session that merely adds charges brings no credit to allocate. When there is one, the engine consumes the open items oldest first (`date_maturity` or `date`) and stops when the credit is used up, so anything past that point is loaded for nothing. Look the open items up per partner, account and currency, and only call `_reconcile_plan` when the session's lines or the customer's open credits give something to allocate. Take the open debits in the order the engine consumes them - the PoS lines have no `date_maturity`, so the ordering is done in Python on `date_maturity or date` - and hand over only as many as the credits cover. Both lookups are capped at 2000 lines: a settlement larger than the oldest 2000 open items leaves its remainder as an open credit, allocated by the next close. The partials created are the same as before, only the size of the batch given to `_reconcile_plan` changes. opw-6529792
Resolved issues and error corrections
Large marketing emails with several WebP images could fail to save or silently lose the end of the message. This fix preserves the full email content by handling oversized embedded images safely during save, reducing the risk of broken campaigns and lost work.
Original PR description
Root cause: Webp images are not supported by Outlook, so the editor turns each one into an inline base64 image before the body is saved. A mailing with a few webp images ends up with a body of more…
Root cause: Webp images are not supported by Outlook, so the editor turns each one into an inline base64 image before the body is saved. A mailing with a few webp images ends up with a body of more than 10 million characters, and each background image is copied a second and a third time for the Outlook fallback. lxml stops reading a document that big and gives back what it read so far, without raising anything. The body is cut in the middle of one of those base64 images. base64.b64decode then gets a piece of an image and raises, which is the error in the ticket. When the cut lands between two elements instead, there is no error at all and the end of the body is simply gone. On the customer's mailing the body is 16.5 million characters and 6.9 million of them are dropped on save. Fix: Put the base64 images aside in _convert_inline_images_to_urls before the body is read, and leave a short placeholder in their place. lxml then only reads the tags, which stays small. The image is given back when the attachment is created, and any placeholder still in the body is put back at the end. This method is the right place because it is the one that reads the body while the images are still inside it. Steps to reproduce: 1. Install Email Marketing. 2. Go to Email Marketing > Mailings > New. 3. Set a subject, pick a mailing list, then open the Mail Body tab. 4. Pick the Start From Scratch theme. 5. Drag a Cover block and replace its background image with a webp image of about 1 MB. 6. Drag three Text - Image blocks and replace each image with a webp image of about 1 MB. 7. Type four lines of text under the last image. 8. Click Save. => Odoo Server Error, binascii.Error: Invalid base64-encoded string: number of data characters cannot be 1 more than a multiple of 4 Ticket [link](https://www.odoo.com/odoo/project.task/6450151) opw-6450151