Skip to content

[FIX] point_of_sale: do not unlink a reloaded orderline - #285662

Closed
fw-bot wants to merge 1 commit into
odoo:saas-18.4from
odoo-dev:saas-18.4-18.0-pos-opw-6401146-2-pebr-562103-fw
Closed

[FIX] point_of_sale: do not unlink a reloaded orderline#285662
fw-bot wants to merge 1 commit into
odoo:saas-18.4from
odoo-dev:saas-18.4-18.0-pos-opw-6401146-2-pebr-562103-fw

Conversation

@fw-bot

@fw-bot fw-bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Steps to reproduce:

  • Restaurant config with two POS devices on the same session
  • Device A: open a table, add two products, press Order (the order is synced as a draft, its lines get server ids)
  • Device A: remove both lines, without syncing
  • Device B: touch the same order, so device A re-reads it from the server through the synchronisation websocket
  • Device A: pay and validate the order

Issue:
The order is saved as paid, with its total and its payment, but without any orderline. The lines are deleted on the server: odoo.models.unlink: deleted pos.order.line records with IDs: [...]

Cause:
Removing an orderline queues an unlink command in
models.commands['pos.order'].unlink['lines_'] (delete_ in related_models.js). That command is only discarded by clearCommands(), which syncAllOrders() calls after a successful sync, so it stays pending in between.

Any read of the order in that window puts the line back: a deleted record counts as missing in missingRecursive(), so it is fetched again and loadData() re-creates it with its server id.

serialize() then emits both the update of the live line and the still pending unlink, and sync_from_ui writes
lines: [[1, id, {...}], [3, id]]. The ORM applies commands in order, and pos.order.line.order_id is ondelete='cascade', so Command.UNLINK deletes the line right after writing it.

Fix:
Skip a removal command when the record is still linked to the parent at serialization time. A record cannot be both linked and removed in the same payload, so the pending command is stale and dropping it keeps the local state. Genuine removals, where the record is no longer linked, are still sent.

opw-6401146


I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr

Forward-Port-Of: #285427
Forward-Port-Of: #284695

Steps to reproduce:
- Restaurant config with two POS devices on the same session
- Device A: open a table, add two products, press Order (the order is
  synced as a draft, its lines get server ids)
- Device A: remove both lines, without syncing
- Device B: touch the same order, so device A re-reads it from the
  server through the synchronisation websocket
- Device A: pay and validate the order

Issue:
The order is saved as paid, with its total and its payment, but without
any orderline. The lines are deleted on the server:
odoo.models.unlink: deleted pos.order.line records with IDs: [...]

Cause:
Removing an orderline queues an unlink command in
models.commands['pos.order'].unlink['lines_<order id>'] (delete_ in
related_models.js). That command is only discarded by clearCommands(),
which syncAllOrders() calls after a successful sync, so it stays
pending in between.

Any read of the order in that window puts the line back: a deleted
record counts as missing in missingRecursive(), so it is fetched again
and loadData() re-creates it with its server id.

serialize() then emits both the update of the live line and the still
pending unlink, and sync_from_ui writes
lines: [[1, id, {...}], [3, id]]. The ORM applies commands in order, and
pos.order.line.order_id is ondelete='cascade', so Command.UNLINK deletes
the line right after writing it.

Fix:
Skip a removal command when the record is still linked to the parent at
serialization time. A record cannot be both linked and removed in the
same payload, so the pending command is stale and dropping it keeps the
local state. Genuine removals, where the record is no longer linked, are
still sent.

opw-6401146

X-original-commit: 4001c60
@robodoo

robodoo commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Pull request status dashboard

@robodoo robodoo added the forwardport This PR was created by @fw-bot label Aug 31, 2026
@fw-bot

fw-bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

This PR targets saas-18.4 and is part of the forward-port chain. Further PRs will be created up to master.

More info at https://github.com/odoo/odoo/wiki/Mergebot#forward-port

@fw-bot

fw-bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

@pedrambiria @stva-odoo ci/runbot failed on this forward-port PR

robodoo pushed a commit that referenced this pull request Sep 1, 2026
Steps to reproduce:
- Restaurant config with two POS devices on the same session
- Device A: open a table, add two products, press Order (the order is
  synced as a draft, its lines get server ids)
- Device A: remove both lines, without syncing
- Device B: touch the same order, so device A re-reads it from the
  server through the synchronisation websocket
- Device A: pay and validate the order

Issue:
The order is saved as paid, with its total and its payment, but without
any orderline. The lines are deleted on the server:
odoo.models.unlink: deleted pos.order.line records with IDs: [...]

Cause:
Removing an orderline queues an unlink command in
models.commands['pos.order'].unlink['lines_<order id>'] (delete_ in
related_models.js). That command is only discarded by clearCommands(),
which syncAllOrders() calls after a successful sync, so it stays
pending in between.

Any read of the order in that window puts the line back: a deleted
record counts as missing in missingRecursive(), so it is fetched again
and loadData() re-creates it with its server id.

serialize() then emits both the update of the live line and the still
pending unlink, and sync_from_ui writes
lines: [[1, id, {...}], [3, id]]. The ORM applies commands in order, and
pos.order.line.order_id is ondelete='cascade', so Command.UNLINK deletes
the line right after writing it.

Fix:
Skip a removal command when the record is still linked to the parent at
serialization time. A record cannot be both linked and removed in the
same payload, so the pending command is stale and dropping it keeps the
local state. Genuine removals, where the record is no longer linked, are
still sent.

opw-6401146

closes #285662

X-original-commit: 4001c60
Signed-off-by: Stéphane Vanmeerhaeghe (stva) <stva@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
@robodoo robodoo closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

forwardport This PR was created by @fw-bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants