# -*- coding: utf-8 -*- from odoo import models, api class PosPayment(models.Model): _inherit = 'pos.payment' @api.model_create_multi def create(self, vals_list): # 1. Extract and sort unique uuids to prevent deadlocks uuids = [] for vals in vals_list: if isinstance(vals, dict) and vals.get('uuid'): uuids.append(vals['uuid']) sorted_uuids = sorted(list(set(uuids))) # 2. Acquire transaction-level PostgreSQL advisory locks on the sorted hashes of uuids for uuid in sorted_uuids: self.env.cr.execute("SELECT pg_advisory_xact_lock(hashtext(%s))", (uuid,)) # 3. Check for concurrent updates/creations of these payments if sorted_uuids: with self.env.registry.cursor() as fresh_cr: fresh_cr.execute("SELECT uuid, write_date FROM pos_payment WHERE uuid IN %s", (tuple(sorted_uuids),)) fresh_res = dict(fresh_cr.fetchall()) self.env.cr.execute("SELECT uuid, write_date FROM pos_payment WHERE uuid IN %s", (tuple(sorted_uuids),)) curr_res = dict(self.env.cr.fetchall()) if fresh_res != curr_res: from odoo.exceptions import ConcurrencyError raise ConcurrencyError("Concurrent update/insertion detected for payment uuids. Retrying transaction.") # 4. Check which payments already exist in the database using the current snapshot existing_payments_map = {} if sorted_uuids: existing_payments = self.search([('uuid', 'in', sorted_uuids)]) for payment in existing_payments: existing_payments_map[payment.uuid] = payment # 4. Prepare values to create (only those that don't already exist) final_payments_list = [None] * len(vals_list) vals_to_create = [] create_indices = [] for i, vals in enumerate(vals_list): uuid = vals.get('uuid') if isinstance(vals, dict) else None if uuid and uuid in existing_payments_map: final_payments_list[i] = existing_payments_map[uuid] else: vals_to_create.append(vals) create_indices.append(i) # 5. Create new payments if vals_to_create: created_payments = super(PosPayment, self).create(vals_to_create) for idx, payment in zip(create_indices, created_payments): final_payments_list[idx] = payment # 6. Reconstruct and return the final combined recordset final_payments = self.env['pos.payment'] for payment in final_payments_list: if payment: final_payments += payment return final_payments