changes
This commit is contained in:
135
match_poynt_v2.py
Normal file
135
match_poynt_v2.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
SL = env['poynt.settlement.line'].sudo()
|
||||
Invoice = env['account.move'].sudo()
|
||||
|
||||
# Reset name-matched ones that don't have invoices — they might be wrong
|
||||
bad_name_matches = SL.search([
|
||||
('state', '=', 'matched'),
|
||||
('match_method', '=', 'cardholder_name'),
|
||||
('invoice_id', '=', False),
|
||||
])
|
||||
if bad_name_matches:
|
||||
bad_name_matches.write({'state': 'fetched', 'partner_id': False, 'match_method': False})
|
||||
print(f'Reset {len(bad_name_matches)} name-only matches without invoices', flush=True)
|
||||
env.cr.commit()
|
||||
|
||||
lines = SL.search([('state', '=', 'fetched'), ('action', '=', 'SALE')])
|
||||
print(f'Unmatched SALE lines to process: {len(lines)}', flush=True)
|
||||
|
||||
matched_invoice = 0
|
||||
matched_card_history = 0
|
||||
no_match = 0
|
||||
|
||||
# --- Build card history: which card_last4 has paid for which partner before? ---
|
||||
# From already-matched lines
|
||||
card_partner_map = {}
|
||||
matched_lines = SL.search([('state', '=', 'matched'), ('partner_id', '!=', False)])
|
||||
for ml in matched_lines:
|
||||
if ml.card_last4:
|
||||
key = (ml.card_brand, ml.card_last4)
|
||||
card_partner_map.setdefault(key, set()).add(ml.partner_id.id)
|
||||
|
||||
# Also from payment.transaction (Odoo-processed payments with card tokens)
|
||||
env.cr.execute("""
|
||||
SELECT pt.payment_method_code, pt.provider_reference, pt.partner_id,
|
||||
tok.provider_ref
|
||||
FROM payment_transaction pt
|
||||
LEFT JOIN payment_token tok ON pt.token_id = tok.id
|
||||
WHERE pt.provider_code = 'poynt' AND pt.state = 'done' AND pt.partner_id IS NOT NULL
|
||||
""")
|
||||
for row in env.cr.fetchall():
|
||||
pass # Token data doesn't reliably have last4
|
||||
|
||||
print(f'Card history: {len(card_partner_map)} unique cards mapped to partners', flush=True)
|
||||
|
||||
for sl in lines:
|
||||
amount = 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: Match by exact amount against open invoices ---
|
||||
if amount > 20:
|
||||
invs = Invoice.search([
|
||||
('move_type', '=', 'out_invoice'),
|
||||
('payment_state', 'in', ('not_paid', 'partial')),
|
||||
('amount_residual', '>=', amount - 0.50),
|
||||
('amount_residual', '<=', amount + 0.50),
|
||||
('invoice_date', '>=', str(txn_date - timedelta(days=90))),
|
||||
('invoice_date', '<=', str(txn_date + timedelta(days=5))),
|
||||
], limit=5)
|
||||
|
||||
if len(invs) == 1:
|
||||
# Unique match — confident
|
||||
partner = invs[0].partner_id
|
||||
invoice = invs[0]
|
||||
elif len(invs) > 1:
|
||||
# Multiple invoices with same amount — try card history to pick one
|
||||
card_key = (sl.card_brand, sl.card_last4)
|
||||
known_partners = card_partner_map.get(card_key, set())
|
||||
for inv in invs:
|
||||
if inv.partner_id.id in known_partners:
|
||||
partner = inv.partner_id
|
||||
invoice = inv
|
||||
break
|
||||
|
||||
# --- Strategy 2: Card history (same card paid before for same partner) ---
|
||||
if not partner and sl.card_last4:
|
||||
card_key = (sl.card_brand, sl.card_last4)
|
||||
known_partners = card_partner_map.get(card_key, set())
|
||||
if len(known_partners) == 1:
|
||||
pid = list(known_partners)[0]
|
||||
# Check if this partner has any open invoice close to this amount
|
||||
invs = Invoice.search([
|
||||
('partner_id', '=', pid),
|
||||
('move_type', '=', 'out_invoice'),
|
||||
('payment_state', 'in', ('not_paid', 'partial')),
|
||||
('amount_residual', '>=', amount - 5),
|
||||
('amount_residual', '<=', amount + 5),
|
||||
], limit=1)
|
||||
if invs:
|
||||
partner = invs[0].partner_id
|
||||
invoice = invs[0]
|
||||
matched_card_history += 1
|
||||
|
||||
if partner:
|
||||
vals = {
|
||||
'partner_id': partner.id,
|
||||
'state': 'matched',
|
||||
'match_method': 'invoice_amount' if invoice else 'card_history',
|
||||
}
|
||||
if invoice:
|
||||
vals['invoice_id'] = invoice.id
|
||||
matched_invoice += 1
|
||||
sl.write(vals)
|
||||
|
||||
# Update card history
|
||||
if sl.card_last4:
|
||||
card_key = (sl.card_brand, sl.card_last4)
|
||||
card_partner_map.setdefault(card_key, set()).add(partner.id)
|
||||
else:
|
||||
no_match += 1
|
||||
|
||||
if (matched_invoice + matched_card_history + no_match) % 100 == 0:
|
||||
env.cr.commit()
|
||||
|
||||
env.cr.commit()
|
||||
|
||||
print(f'\nRESULTS:', flush=True)
|
||||
print(f' Matched by invoice amount: {matched_invoice}', flush=True)
|
||||
print(f' Matched by card history: {matched_card_history}', flush=True)
|
||||
print(f' No match: {no_match}', flush=True)
|
||||
|
||||
# Final stats
|
||||
print(f'\nFINAL STATE:', flush=True)
|
||||
for state in ['matched', 'fetched']:
|
||||
cnt = SL.search_count([('state', '=', state)])
|
||||
print(f' {state}: {cnt}', flush=True)
|
||||
inv_cnt = SL.search_count([('invoice_id', '!=', False)])
|
||||
print(f' With invoice linked: {inv_cnt}', flush=True)
|
||||
Reference in New Issue
Block a user