{% extends 'base.html' %} {% load humanize %} {% block title %}SasaPay Payment Issues{% endblock %} {% block content %}

⚡ SasaPay Payment Issues

Payments that could not be auto-processed — review and resolve them here.

Unmatched Payments
{{ stats.unknown_pending|intcomma }}
awaiting resolution
No Borrower Matched
{{ stats.gaps_no_match|intcomma }}
IPN gaps
No Active Loan
{{ stats.gaps_no_loan|intcomma }}
IPN gaps
Processed OK
{{ stats.ipn_processed|intcomma }}
total successful IPNs
{% if active_tab == 'unknown' %}
Payments received from SasaPay that couldn't be matched to a borrower. The customer's BillRef didn't match any phone, ID, or loan number.
{% if stats.unknown_pending > 0 %}
{% csrf_token %}
{% endif %} {% if show_resolved %} Show Unresolved Only {% else %} Show Resolved {% endif %}
{% for p in unknown_page %} {% empty %} {% endfor %}
📅 Date đŸ’ĩ Amount (KES) 👤 Paid By 📞 Paying Phone (MSISDN) 🔑 BillRef entered M-Pesa Ref â„šī¸ Reason Status Actions
{{ p.created_at|date:"d M Y" }}
{{ p.created_at|date:"H:i" }}
{{ p.amount|floatformat:2|intcomma }} {{ p.paid_by|default:"—" }} {{ p.msisdn|default:"—" }} {{ p.bill_ref|default:"(empty)" }} {% if not p.bill_ref %} EMPTY {% endif %} {{ p.reference|default:"—" }} {{ p.notes|truncatechars:80 }} {% if p.resolved %} Resolved {% else %} Pending {% endif %} {% if not p.resolved %}
{% csrf_token %}
{% csrf_token %}
{% else %} — {% endif %}
✅
No unmatched payments
Every SasaPay payment was matched to a borrower.
{% if unknown_page.has_other_pages %} {% endif %}
What does this mean? These are real M-Pesa payments SasaPay received and forwarded to the system, but the BillRef (what the customer typed at the M-Pesa till) didn't match any borrower's phone number, ID number, or loan number.
{% endif %} {% if active_tab == 'gaps' %}
IPN notifications that arrived but no repayment was created. Total: {{ gaps_total|intcomma }}
{% for gap in gaps_page %} {% empty %} {% endfor %}
📅 Date TransID M-Pesa Ref đŸ’ĩ Amount 👤 Name 🔑 BillRef entered 📞 MSISDN 🔍 Drop Reason
{{ gap.created_at|date:"d M Y" }}
{{ gap.created_at|date:"H:i" }}
{{ gap.trans_id }} {{ gap.mpesa_ref }} KSh {{ gap.amount|floatformat:2|intcomma }} {{ gap.name }} {{ gap.bill_ref|default:"(empty)" }} {% if not gap.bill_ref %} EMPTY {% endif %} {{ gap.msisdn }} {% if gap.raw_status == 'no_match' %} No borrower matched {% elif gap.raw_status == 'no_loan' %} No active loan {% elif gap.raw_status == 'no_balance' %} Loan already paid {% elif gap.raw_status == 'failed' %} Processing error {% elif gap.raw_status == 'pending' %} Stuck pending {% endif %} {% if gap.note != '—' %}
{{ gap.note|truncatechars:100 }} {% endif %}
✅
No IPN gaps found
Every IPN that arrived was processed into a repayment.
{% if gaps_page.has_other_pages %} {% endif %}
Why do IPN gaps happen?
{% endif %}
{% endblock %}