from datetime import timedelta SL = env['poynt.settlement.line'].sudo() Invoice = env['account.move'].sudo() refunds = SL.search([('state', '=', 'fetched'), ('action', '=', 'REFUND')]) print(f'Unmatched REFUND lines: {len(refunds)}', flush=True) matched = 0 matched_by_card = 0 no_match = 0 for sl in refunds: amount = abs(sl.amount) txn_date = sl.transaction_date.date() if sl.transaction_date else None if not txn_date: no_match += 1 continue partner = None invoice = None # Strategy 1: Find the original SALE with same card_last4 and same amount if sl.card_last4: original_sale = SL.search([ ('card_last4', '=', sl.card_last4), ('action', '=', 'SALE'), ('amount', '>=', amount - 0.50), ('amount', '<=', amount + 0.50), ('state', '=', 'matched'), ('partner_id', '!=', False), ], limit=1, order='transaction_date desc') if original_sale: partner = original_sale.partner_id matched_by_card += 1 # Strategy 2: Match against credit notes by amount if not partner: credit_notes = Invoice.search([ ('move_type', '=', 'out_refund'), ('amount_total', '>=', amount - 0.50), ('amount_total', '<=', amount + 0.50), ('invoice_date', '>=', str(txn_date - timedelta(days=30))), ('invoice_date', '<=', str(txn_date + timedelta(days=5))), ], limit=3) if len(credit_notes) == 1: partner = credit_notes[0].partner_id invoice = credit_notes[0] elif len(credit_notes) > 1: best = min(credit_notes, key=lambda i: abs((i.invoice_date - txn_date).days)) partner = best.partner_id invoice = best # Strategy 3: Match against regular invoices (might be a partial refund) if not partner: invs = Invoice.search([ ('move_type', '=', 'out_invoice'), ('amount_total', '>=', amount - 0.50), ('amount_total', '<=', amount + 0.50), ('invoice_date', '>=', str(txn_date - timedelta(days=60))), ('invoice_date', '<=', str(txn_date + timedelta(days=5))), ], limit=3) if len(invs) == 1: partner = invs[0].partner_id invoice = invs[0] elif len(invs) > 1: best = min(invs, key=lambda i: abs((i.invoice_date - txn_date).days)) partner = best.partner_id invoice = best if partner: vals = { 'partner_id': partner.id, 'state': 'matched', 'match_method': 'refund_card_match' if matched_by_card else 'refund_invoice', } if invoice: vals['invoice_id'] = invoice.id sl.write(vals) matched += 1 else: no_match += 1 env.cr.commit() print(f'Matched refunds: {matched} (by card: {matched_by_card})', flush=True) print(f'No match: {no_match}', flush=True) # Final print(f'\nFINAL:', flush=True) for state in ['matched', 'fetched']: print(f' {state}: {SL.search_count([("state", "=", state)])}', flush=True) print(f' With invoice: {SL.search_count([("invoice_id", "!=", False)])}', flush=True)