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.
 
 
 

267 lines
10 KiB

{% extends "base.html" %}
{% block title %}Payment Plans - Plutus{% endblock %}
{% block content %}
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="{{ url_for('main.index') }}">Dashboard</a></li>
<li class="is-active"><a href="#" aria-current="page">Payment Plans</a></li>
</ul>
</nav>
<div class="level">
<div class="level-left">
<div>
<h1 class="title">Payment Plans</h1>
<p class="subtitle">Recurring payment management</p>
</div>
</div>
<div class="level-right">
<a class="button is-primary" href="{{ url_for('main.payment_plans_create') }}">
<span class="icon"><i class="fas fa-plus"></i></span>
<span>New Payment Plan</span>
</a>
</div>
</div>
<!-- Summary Statistics -->
<div class="columns">
<div class="column is-3">
<div class="box has-text-centered">
<p class="title is-4 has-text-success">{{ summary.active_plans }}</p>
<p class="subtitle is-6">Active Plans</p>
</div>
</div>
<div class="column is-3">
<div class="box has-text-centered">
<p class="title is-4 has-text-warning">{{ summary.inactive_plans }}</p>
<p class="subtitle is-6">Inactive Plans</p>
</div>
</div>
<div class="column is-3">
<div class="box has-text-centered">
<p class="title is-4 has-text-info">{{ summary.total_plans }}</p>
<p class="subtitle is-6">Total Plans</p>
</div>
</div>
<div class="column is-3">
<div class="box has-text-centered">
<p class="title is-4 has-text-primary">{{ summary.total_recurring_amount | currency }}</p>
<p class="subtitle is-6">Monthly Recurring</p>
</div>
</div>
</div>
<!-- Payment Plans Table -->
<div class="box">
<div class="level">
<div class="level-left">
<h2 class="title is-4">Payment Plans</h2>
</div>
<div class="level-right">
<div class="field">
<p class="control has-icons-left">
<input class="input" type="text" id="searchInput" placeholder="Search Customer ID, Amount...">
<span class="icon is-small is-left">
<i class="fas fa-search"></i>
</span>
</p>
</div>
</div>
</div>
<!-- Filter Controls -->
<div class="field is-grouped is-grouped-multiline">
<div class="control">
<label class="label is-small">Filter by Status:</label>
<div class="select is-small">
<select id="statusFilter">
<option value="">All</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
</div>
<div class="control">
<label class="label is-small">Filter by Frequency:</label>
<div class="select is-small">
<select id="frequencyFilter">
<option value="">All</option>
<option value="Weekly">Weekly</option>
<option value="Fortnightly">Fortnightly</option>
</select>
</div>
</div>
</div>
{% if plans %}
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable" id="plansTable">
<thead>
<tr>
<th>Plan ID</th>
<th>Customer</th>
<th>Splynx ID</th>
<th>Amount</th>
<th>Frequency</th>
<th>Start Date</th>
<th>Status</th>
<th>Created</th>
<th>Created By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for plan in plans %}
<tr data-status="{{ 'active' if plan.Enabled else 'inactive' }}"
data-frequency="{{ plan.Frequency }}"
data-splynx-id="{{ plan.Splynx_ID }}"
data-amount="{{ plan.Amount }}"
data-customer-name="">
<td>
<a href="{{ url_for('main.payment_plans_detail', plan_id=plan.id) }}" class="has-text-weight-semibold">
#{{ plan.id }}
</a>
</td>
<td>
<span class="customer-name" data-splynx-id="{{ plan.Splynx_ID }}">
<span class="icon"><i class="fas fa-spinner fa-spin"></i></span>
Loading...
</span>
</td>
<td>
<a href="https://billing.interphone.com.au/admin/customers/view?id={{ plan.Splynx_ID }}"
target="_blank" class="tag is-info">{{ plan.Splynx_ID }}</a>
</td>
<td>
<strong>{{ plan.Amount | currency }}</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>
<td>{{ plan.Start_Date.strftime('%Y-%m-%d') if plan.Start_Date else '-' }}</td>
<td>
{% if plan.Enabled %}
<span class="tag is-success">Active</span>
{% else %}
<span class="tag is-danger">Inactive</span>
{% endif %}
</td>
<td>{{ plan.Created.strftime('%Y-%m-%d %H:%M') if plan.Created else '-' }}</td>
<td>{{ plan.created_by or 'Unknown' }}</td>
<td>
<div class="field is-grouped">
<div class="control">
<a class="button is-small is-info"
href="{{ url_for('main.payment_plans_detail', plan_id=plan.id) }}">
<span class="icon"><i class="fas fa-eye"></i></span>
</a>
</div>
<div class="control">
<a class="button is-small is-warning"
href="{{ url_for('main.payment_plans_edit', plan_id=plan.id) }}">
<span class="icon"><i class="fas fa-edit"></i></span>
</a>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="has-text-centered py-6">
<span class="icon is-large has-text-grey-light">
<i class="fas fa-calendar-alt fa-3x"></i>
</span>
<p class="title is-5 has-text-grey">No Payment Plans Found</p>
<p class="subtitle is-6 has-text-grey">Get started by creating your first payment plan.</p>
<a class="button is-primary" href="{{ url_for('main.payment_plans_create') }}">
<span class="icon"><i class="fas fa-plus"></i></span>
<span>Create Payment Plan</span>
</a>
</div>
{% endif %}
</div>
<script>
// Load customer names asynchronously
document.addEventListener('DOMContentLoaded', function() {
const customerElements = document.querySelectorAll('.customer-name');
customerElements.forEach(function(element) {
const splynxId = element.dataset.splynxId;
fetch(`/api/splynx/${splynxId}`)
.then(response => response.json())
.then(data => {
if (data && data.name) {
element.innerHTML = data.name;
// Update the row data attribute for search
const row = element.closest('tr');
row.dataset.customerName = data.name.toLowerCase();
} else {
element.innerHTML = '<span class="has-text-danger">Unknown Customer</span>';
}
})
.catch(error => {
console.error('Error fetching customer:', error);
element.innerHTML = '<span class="has-text-danger">Error Loading</span>';
});
});
});
// Search and filter functionality
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.getElementById('searchInput');
const statusFilter = document.getElementById('statusFilter');
const frequencyFilter = document.getElementById('frequencyFilter');
const table = document.getElementById('plansTable');
if (!table) return; // No table to filter
function filterTable() {
const searchTerm = searchInput.value.toLowerCase();
const statusValue = statusFilter.value;
const frequencyValue = frequencyFilter.value;
const rows = table.querySelectorAll('tbody tr');
rows.forEach(function(row) {
const splynxId = row.dataset.splynxId;
const amount = row.dataset.amount;
const customerName = row.dataset.customerName || '';
const status = row.dataset.status;
const frequency = row.dataset.frequency;
// Search filter
const searchMatch = !searchTerm ||
splynxId.includes(searchTerm) ||
amount.includes(searchTerm) ||
customerName.includes(searchTerm);
// Status filter
const statusMatch = !statusValue || status === statusValue;
// Frequency filter
const frequencyMatch = !frequencyValue || frequency === frequencyValue;
// Show/hide row
if (searchMatch && statusMatch && frequencyMatch) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
}
// Add event listeners
searchInput.addEventListener('input', filterTable);
statusFilter.addEventListener('change', filterTable);
frequencyFilter.addEventListener('change', filterTable);
});
</script>
{% endblock %}