feat: enable logging of cancelled POS order lines to chatter for non-paid cancellations

This commit is contained in:
Suherdy Yacob 2026-06-15 23:11:41 +07:00
parent dc8bd772b3
commit 70457207a8
2 changed files with 32 additions and 4 deletions

View File

@ -60,11 +60,24 @@ class PosOrder(models.Model):
else: else:
employee_name = self.env.user.name employee_name = self.env.user.name
# Flush any pending x_cancelled_lines that were accumulated on the
# frontend but never sent via _process_order (i.e. the order was
# cancelled without payment). The JS passes these as a dict keyed by
# order ID: { "<order_id>": [...cancelled_lines...] }
cancelled_lines_map = self.env.context.get('cancelled_lines_map', {})
res = super().action_pos_order_cancel() res = super().action_pos_order_cancel()
for order in self: for order in self:
order.message_post(body=f"<strong>Order Cancelled</strong> by <strong>{employee_name}</strong>") order.message_post(body=f"<strong>Order Cancelled</strong> by <strong>{employee_name}</strong>")
# Log any frontend-tracked line deletions/reductions that happened
# before this cancellation. Use str(order.id) as the JS context key
# since JSON object keys are always strings.
pending_lines = cancelled_lines_map.get(str(order.id)) or cancelled_lines_map.get(order.id)
if pending_lines:
order._log_cancelled_lines_to_chatter(pending_lines)
# Prevent Odoo backend warning regarding custom action properties # Prevent Odoo backend warning regarding custom action properties
if isinstance(res, dict) and 'type' not in res: if isinstance(res, dict) and 'type' not in res:
res['type'] = '' res['type'] = ''

View File

@ -37,13 +37,28 @@ patch(PosStore.prototype, {
async deleteOrders(orders, serverIds = [], ignoreChange = false) { async deleteOrders(orders, serverIds = [], ignoreChange = false) {
const cashier = this.getCashier(); const cashier = this.getCashier();
const oldCall = this.data.call; const oldCall = this.data.call;
if (cashier) {
// Build a map of { order.id → x_cancelled_lines } for all synced orders
// that are being deleted. This lets the server flush the cancellation log
// to the order chatter even when the order is cancelled without payment
// (i.e. _process_order is never called for cancelled orders).
const cancelledLinesMap = {};
for (const order of orders) {
if (order && typeof order.id === "number" && order.x_cancelled_lines?.length) {
cancelledLinesMap[order.id] = order.x_cancelled_lines;
}
}
if (cashier || Object.keys(cancelledLinesMap).length > 0) {
this.data.call = async function(model, method, args, kwargs) { this.data.call = async function(model, method, args, kwargs) {
if (model === "pos.order" && method === "action_pos_order_cancel") { if (model === "pos.order" && method === "action_pos_order_cancel") {
kwargs = kwargs || {}; kwargs = kwargs || {};
kwargs.context = { kwargs.context = {
...(kwargs.context || {}), ...(kwargs.context || {}),
cancelled_by_employee_id: cashier.id ...(cashier ? { cancelled_by_employee_id: cashier.id } : {}),
...(Object.keys(cancelledLinesMap).length > 0
? { cancelled_lines_map: cancelledLinesMap }
: {}),
}; };
} }
return oldCall.apply(this, arguments); return oldCall.apply(this, arguments);