You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

422 lines
17 KiB

{% extends "base.html" %}
{% block title %}Payment Plan #{{ plan.id }} - Plutus{% endblock %}
{% block content %}
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="{{ url_for('main.index') }}">Dashboard</a></li>
<li><a href="{{ url_for('main.payment_plans_list') }}">Payment Plans</a></li>
<li class="is-active"><a href="#" aria-current="page">Plan #{{ plan.id }}</a></li>
</ul>
</nav>
<div class="level">
<div class="level-left">
<div>
<h1 class="title">Payment Plan #{{ plan.id }}</h1>
<p class="subtitle">Created: {{ plan.Created.strftime('%Y-%m-%d %H:%M:%S') if plan.Created else 'Unknown' }}</p>
</div>
</div>
<div class="level-right">
<div class="field is-grouped">
<div class="control">
<form method="POST" action="{{ url_for('main.payment_plans_toggle', plan_id=plan.id) }}" style="display: inline;">
<button class="button {% if plan.Enabled %}is-warning{% else %}is-success{% endif %}"
onclick="return confirm('Are you sure you want to {% if plan.Enabled %}disable{% else %}enable{% endif %} this payment plan?')">
<span class="icon">
<i class="fas {% if plan.Enabled %}fa-pause{% else %}fa-play{% endif %}"></i>
</span>
<span>{% if plan.Enabled %}Disable{% else %}Enable{% endif %}</span>
</button>
</form>
</div>
<div class="control">
<a class="button is-info" href="{{ url_for('main.payment_plans_edit', plan_id=plan.id) }}">
<span class="icon"><i class="fas fa-edit"></i></span>
<span>Edit</span>
</a>
</div>
<div class="control">
<a class="button is-light" href="{{ url_for('main.payment_plans_list') }}">
<span class="icon"><i class="fas fa-arrow-left"></i></span>
<span>Back to List</span>
</a>
</div>
</div>
</div>
</div>
<!-- Payment Plan Status Banner -->
<div class="box">
<div class="level">
<div class="level-left">
<div class="level-item">
{% if plan.Enabled %}
<span class="icon is-large has-text-success">
<i class="fas fa-calendar-check fa-2x"></i>
</span>
{% else %}
<span class="icon is-large has-text-warning">
<i class="fas fa-calendar-times fa-2x"></i>
</span>
{% endif %}
</div>
<div class="level-item">
<div>
{% if plan.Enabled %}
<h2 class="title is-4 has-text-success mb-2">Active Payment Plan</h2>
<p class="has-text-grey">This payment plan is currently active and processing payments.</p>
{% else %}
<h2 class="title is-4 has-text-warning mb-2">Inactive Payment Plan</h2>
<p class="has-text-grey">This payment plan is disabled and not processing payments.</p>
{% endif %}
</div>
</div>
</div>
<div class="level-right">
<div class="level-item">
<div class="has-text-right">
<p class="title is-3 has-text-primary mb-2">{{ plan.Amount | currency }}</p>
<p class="has-text-grey">{{ plan.Frequency }}</p>
</div>
</div>
</div>
</div>
</div>
<!-- Customer Information -->
<div class="columns">
<div class="column is-half">
<div class="box">
<h3 class="title is-5">
<span class="icon"><i class="fas fa-user"></i></span>
Customer Information
</h3>
<div id="customerInfo" data-splynx-id="{{ plan.Splynx_ID }}">
<div class="has-text-centered py-4">
<span class="icon is-large">
<i class="fas fa-spinner fa-spin"></i>
</span>
<p>Loading customer details...</p>
</div>
</div>
</div>
</div>
<div class="column is-half">
<div class="box">
<h3 class="title is-5">
<span class="icon"><i class="fas fa-cog"></i></span>
Plan Configuration
</h3>
<table class="table is-fullwidth">
<tbody>
<tr>
<td><strong>Plan ID</strong></td>
<td>#{{ plan.id }}</td>
</tr>
<tr>
<td><strong>Payment Amount</strong></td>
<td><strong class="has-text-success">{{ plan.Amount | currency }}</strong></td>
</tr>
<tr>
<td><strong>Frequency</strong></td>
<td>
<span class="tag {% if plan.Frequency == 'Weekly' %}is-warning{% elif plan.Frequency == 'Fortnightly' %}is-info{% else %}is-light{% endif %}">
{{ plan.Frequency }}
</span>
</td>
</tr>
<tr>
<td><strong>Start Date</strong></td>
<td>
{{ plan.Start_Date.strftime('%Y-%m-%d') if plan.Start_Date else '-' }}
{% if plan.Start_Date %}
<br><small class="has-text-grey">Payments occur every {{ plan.Frequency.lower() }} from this date</small>
{% endif %}
</td>
</tr>
<tr>
<td><strong>Payment Method</strong></td>
<td>
<code class="is-size-7">{{ plan.Stripe_Payment_Method[:20] }}{% if plan.Stripe_Payment_Method|length > 20 %}...{% endif %}</code>
</td>
</tr>
<tr>
<td><strong>Status</strong></td>
<td>
{% if plan.Enabled %}
<span class="tag is-success">Active</span>
{% else %}
<span class="tag is-danger">Inactive</span>
{% endif %}
</td>
</tr>
<tr>
<td><strong>Created</strong></td>
<td>{{ plan.Created.strftime('%Y-%m-%d %H:%M:%S') if plan.Created else '-' }}</td>
</tr>
<tr>
<td><strong>Created By</strong></td>
<td>{{ plan.created_by or 'Unknown' }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Associated Payments -->
<div class="box">
<div class="level">
<div class="level-left">
<h3 class="title is-5">
<span class="icon"><i class="fas fa-list"></i></span>
Associated Payments
</h3>
</div>
<div class="level-right">
<div class="field">
<p class="control has-icons-left">
<input class="input" type="text" id="paymentsSearchInput" placeholder="Search payments...">
<span class="icon is-small is-left">
<i class="fas fa-search"></i>
</span>
</p>
</div>
</div>
</div>
{% if associated_payments %}
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable" id="paymentsTable">
<thead>
<tr>
<th>Payment ID</th>
<th>Amount</th>
<th>Status</th>
<th>Payment Intent</th>
<th>Processed</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for payment in associated_payments %}
<tr data-payment-id="{{ payment.id }}"
data-amount="{{ payment.Payment_Amount }}"
data-status="{{ 'successful' if payment.Success == True else 'failed' if payment.Success == False else 'pending' }}">
<td>
<a href="{{ url_for('main.payment_detail', payment_id=payment.id) }}"
class="has-text-weight-semibold">
#{{ payment.id }}
</a>
</td>
<td>
<strong>{{ payment.Payment_Amount | currency }}</strong>
</td>
<td>
{% if payment.Refund == True %}
<span class="status-badge refund">
<i class="fas fa-undo"></i>
Refund
</span>
{% elif payment.Success == True %}
<span class="status-badge success">
<i class="fas fa-check"></i>
Success
</span>
{% elif payment.Success == False and payment.PI_FollowUp %}
<span class="status-badge pending">
<i class="fas fa-clock"></i>
Pending
</span>
{% elif payment.Success == False %}
<span class="status-badge failed">
<i class="fas fa-times"></i>
Failed
</span>
{% else %}
<span class="status-badge pending">
<i class="fas fa-clock"></i>
Pending
</span>
{% endif %}
</td>
<td>
{% if payment.Payment_Intent %}
<code class="is-size-7">{{ payment.Payment_Intent[:20] }}...</code>
{% else %}
-
{% endif %}
</td>
<td>{{ payment.Created.strftime('%Y-%m-%d %H:%M') if payment.Created else '-' }}</td>
<td>
<a class="button is-small is-info"
href="{{ url_for('main.payment_detail', payment_id=payment.id) }}">
<span class="icon"><i class="fas fa-eye"></i></span>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Payments Summary -->
<div class="level mt-4">
<div class="level-left">
<div class="level-item">
<div>
<p class="title is-6">Payment Summary</p>
<p class="subtitle is-7">Total: {{ associated_payments|length }} payments</p>
</div>
</div>
</div>
<div class="level-right">
<div class="level-item">
<div class="tags has-addons">
<span class="tag is-success">
{{ associated_payments|selectattr('Success', 'equalto', True)|list|length }} Successful
</span>
</div>
</div>
<div class="level-item">
<div class="tags has-addons">
<span class="tag is-danger">
{{ associated_payments|selectattr('Success', 'equalto', False)|list|length }} Failed
</span>
</div>
</div>
<div class="level-item">
<div class="tags has-addons">
<span class="tag is-warning">
{{ associated_payments|selectattr('Success', 'equalto', None)|list|length }} Pending
</span>
</div>
</div>
</div>
</div>
{% else %}
<div class="has-text-centered py-6">
<span class="icon is-large has-text-grey-light">
<i class="fas fa-receipt fa-3x"></i>
</span>
<p class="title is-5 has-text-grey">No Associated Payments</p>
<p class="subtitle is-6 has-text-grey">This payment plan hasn't processed any payments yet.</p>
</div>
{% endif %}
</div>
<script>
// Load customer information
document.addEventListener('DOMContentLoaded', function() {
const splynxId = {{ plan.Splynx_ID }};
const customerInfoDiv = document.getElementById('customerInfo');
fetch(`/api/splynx/${splynxId}`)
.then(response => response.json())
.then(data => {
if (data && data.id) {
displayCustomerInfo(data);
} else {
showCustomerError('Customer not found');
}
})
.catch(error => {
console.error('Error fetching customer:', error);
showCustomerError('Error loading customer details');
});
});
function displayCustomerInfo(customer) {
const customerInfoDiv = document.getElementById('customerInfo');
const infoHtml = `
<table class="table is-fullwidth">
<tbody>
<tr>
<td><strong>Customer ID</strong></td>
<td>
<a href="https://billing.interphone.com.au/admin/customers/view?id=${customer.id}"
target="_blank" class="tag is-info">${customer.id}</a>
</td>
</tr>
<tr>
<td><strong>Name</strong></td>
<td>${customer.name || 'N/A'}</td>
</tr>
<tr>
<td><strong>Email</strong></td>
<td>${customer.email || 'N/A'}</td>
</tr>
<tr>
<td><strong>Phone</strong></td>
<td>${customer.phone || 'N/A'}</td>
</tr>
<tr>
<td><strong>Status</strong></td>
<td>
${customer.status === 'active'
? '<span class="tag is-success">Active</span>'
: `<span class="tag is-warning">${customer.status || 'Unknown'}</span>`
}
</td>
</tr>
<tr>
<td><strong>Address</strong></td>
<td>
${customer.street_1 || ''} ${customer.street_2 || ''}<br>
${customer.city || ''} ${customer.zip_code || ''}
</td>
</tr>
</tbody>
</table>
`;
customerInfoDiv.innerHTML = infoHtml;
}
function showCustomerError(message) {
const customerInfoDiv = document.getElementById('customerInfo');
customerInfoDiv.innerHTML = `
<div class="has-text-centered py-4">
<span class="icon is-large has-text-danger">
<i class="fas fa-exclamation-triangle fa-2x"></i>
</span>
<p class="has-text-danger">${message}</p>
</div>
`;
}
// Search functionality for associated payments
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('paymentsSearchInput');
const table = document.getElementById('paymentsTable');
if (!table || !searchInput) return; // No table to search
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const rows = table.querySelectorAll('tbody tr');
rows.forEach(function(row) {
const paymentId = row.dataset.paymentId;
const amount = row.dataset.amount;
const status = row.dataset.status;
const rowText = row.textContent.toLowerCase();
const matches = !searchTerm ||
paymentId.includes(searchTerm) ||
amount.includes(searchTerm) ||
status.includes(searchTerm) ||
rowText.includes(searchTerm);
row.style.display = matches ? '' : 'none';
});
});
});
</script>
{% endblock %}