Fix misleading overpayment log for exact payments
- Only log 'Overpayment within 5% threshold' when received > expected - Skip the log message for exact payment matches - Prevents confusion when payment amount exactly matches expected amount
This commit is contained in:
parent
8326c7401f
commit
3ae1b9bed9
4 changed files with 37 additions and 16 deletions
|
|
@ -351,10 +351,7 @@ def _should_process_late_payment(payment, tx):
|
|||
return True
|
||||
|
||||
# Edge Case: First payment to a fresh quote (normal processing should handle this, but just in case)
|
||||
if payment.received_amount == 0 and payment.status in [
|
||||
CryptoPayment.STATUS_PENDING,
|
||||
CryptoPayment.STATUS_CONFIRMED,
|
||||
]:
|
||||
if payment.received_amount == 0 and payment.status == CryptoPayment.STATUS_PENDING:
|
||||
log.payment_info(payment, "Accepting first payment to fresh quote")
|
||||
return True
|
||||
|
||||
|
|
@ -680,8 +677,10 @@ def process_confirmed_payment(env_request, crypto_payment, client, payment_rescu
|
|||
results["final_status"] = CryptoPayment.STATUS_CONFIRMED_OVERPAY
|
||||
return results
|
||||
else:
|
||||
# Overpayment within threshold - will confirm normally at end
|
||||
log.payment_info(crypto_payment, "Overpayment within 5% threshold")
|
||||
# Check if there's actually an overpayment (not exact match)
|
||||
if received_crypto > expected_crypto:
|
||||
# Overpayment within threshold - will confirm normally at end
|
||||
log.payment_info(crypto_payment, "Overpayment within 5% threshold")
|
||||
else:
|
||||
# Normal payment - will confirm at end
|
||||
pass
|
||||
|
|
@ -3632,9 +3631,18 @@ def scan_wallet_for_double_or_late_payments(request, settings):
|
|||
)
|
||||
else:
|
||||
# First payment to this address - process normally
|
||||
# Determine if this is a late payment or double payment
|
||||
if payment.status in [
|
||||
CryptoPayment.STATUS_EXPIRED,
|
||||
CryptoPayment.STATUS_CANCELLED,
|
||||
]:
|
||||
payment_type = "late payment"
|
||||
else:
|
||||
payment_type = "double payment"
|
||||
|
||||
log.payment_info(
|
||||
payment,
|
||||
f"Found late payment to {payment.status} quote: "
|
||||
f"Found {payment_type} to {payment.status} quote: "
|
||||
f"{tx.get('amount', 0) / 1e12:.12f} XMR, "
|
||||
f"{tx.get('confirmations', 0)} confirmations, height {tx.get('height', 0)}",
|
||||
)
|
||||
|
|
@ -3771,9 +3779,18 @@ def scan_wallet_for_double_or_late_payments(request, settings):
|
|||
|
||||
if payment and _should_process_late_payment(payment, tx):
|
||||
late_payments_found += 1
|
||||
# Determine if this is a late payment or double payment
|
||||
if payment.status in [
|
||||
CryptoPayment.STATUS_EXPIRED,
|
||||
CryptoPayment.STATUS_CANCELLED,
|
||||
]:
|
||||
payment_type = "late payment"
|
||||
else:
|
||||
payment_type = "double payment"
|
||||
|
||||
log.payment_info(
|
||||
payment,
|
||||
f"Found late payment to {payment.status} quote: "
|
||||
f"Found {payment_type} to {payment.status} quote: "
|
||||
f"{tx.get('amount', 0)} {coin_type}, "
|
||||
f"{tx.get('confirmations', 0)} confirmations",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -858,15 +858,17 @@ class CryptoWatcherIntegrationTests(unittest.TestCase):
|
|||
# Check that payment_error was called for duplicate detection
|
||||
error_calls = mock_log.payment_error.call_args_list
|
||||
duplicate_detection_calls = [
|
||||
call for call in error_calls
|
||||
call
|
||||
for call in error_calls
|
||||
if "DUPLICATE PAYMENT DETECTED" in str(call[0][1])
|
||||
]
|
||||
self.assertTrue(len(duplicate_detection_calls) >= 1)
|
||||
|
||||
|
||||
# Verify duplicate payment record creation was logged
|
||||
info_calls = mock_log.payment_info.call_args_list
|
||||
duplicate_creation_calls = [
|
||||
call for call in info_calls
|
||||
call
|
||||
for call in info_calls
|
||||
if "Created duplicate payment" in str(call[0][1])
|
||||
]
|
||||
self.assertEqual(len(duplicate_creation_calls), 1)
|
||||
|
|
|
|||
|
|
@ -180,9 +180,9 @@ class TestInvoiceDeletion(unittest.TestCase):
|
|||
self.assertEqual(self.mock_crypto_payment.invoice, self.mock_invoice)
|
||||
|
||||
@patch("make_post_sell.lib.crypto_watcher.delete_invoice_by_id")
|
||||
@patch("make_post_sell.lib.crypto_watcher.logger")
|
||||
@patch("make_post_sell.lib.crypto_watcher.log")
|
||||
def test_handle_invoice_deletion_returns_false(
|
||||
self, mock_logger, mock_delete_invoice
|
||||
self, mock_log, mock_delete_invoice
|
||||
):
|
||||
"""Test that function handles when delete_invoice_by_id returns failure."""
|
||||
mock_delete_invoice.return_value = {
|
||||
|
|
@ -194,8 +194,8 @@ class TestInvoiceDeletion(unittest.TestCase):
|
|||
|
||||
delete_invoice_for_terminal_state(self.mock_dbsession, self.mock_crypto_payment)
|
||||
|
||||
# Verify warning was logged
|
||||
mock_logger.warning.assert_called_once()
|
||||
# Verify error was logged
|
||||
mock_log.error_with_context.assert_called_once()
|
||||
|
||||
# Verify invoice reference was NOT cleared since deletion failed
|
||||
self.assertEqual(self.mock_crypto_payment.invoice_id, "test-invoice-123")
|
||||
|
|
|
|||
|
|
@ -1415,7 +1415,9 @@ class TestCryptoPayment(unittest.TestCase):
|
|||
self.assertIn(self.payment.uuid_str[:8], result)
|
||||
self.assertIn("[pending]", result) # status shown as-is
|
||||
self.assertIn("XMR", result)
|
||||
self.assertIn("0/1", result) # received/expected in XMR (trailing zeros stripped)
|
||||
self.assertIn(
|
||||
"0/1", result
|
||||
) # received/expected in XMR (trailing zeros stripped)
|
||||
self.assertIn("conf:0/10", result)
|
||||
self.assertIn("addr:", result)
|
||||
self.assertIn("user:Alice", result)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue