Add Database Status section to admin panel
- Added table_counts query in /admin route to get record counts for all tables * Reference tables (TrnsType, TrnsLkup, Footers, FileStat, Employee, etc.) * Core data tables (Rolodex, LegacyPhone, LegacyFile, Ledger, etc.) * Specialized tables (PlanInfo, Qdros, Pensions, etc.) * Modern models (Client, Phone, Case, Transaction, Payment, Document) - Created Database Status UI section in admin.html * Four-column layout showing all table categories * Color-coded badges (green=has data, gray=empty) * Check mark icons for populated tables * Table row highlighting based on data presence * Legend explaining the visual indicators - Helps users track import progress at a glance - Shows which tables have been successfully imported - Distinguishes between legacy and modern model data
This commit is contained in:
58
app/main.py
58
app/main.py
@@ -1846,11 +1846,69 @@ async def admin_panel(request: Request, db: Session = Depends(get_db)):
|
|||||||
files_by_type[import_type] = []
|
files_by_type[import_type] = []
|
||||||
files_by_type[import_type].append(file_info)
|
files_by_type[import_type].append(file_info)
|
||||||
|
|
||||||
|
# Get record counts for all legacy and modern tables
|
||||||
|
from .models import (
|
||||||
|
# Legacy tables
|
||||||
|
Rolodex, LegacyPhone, LegacyFile, FilesR, FilesV, FileNots,
|
||||||
|
Ledger, Deposits, LegacyPayment, TrnsType, TrnsLkup,
|
||||||
|
Footers, FileStat, Employee, GroupLkup, FileType,
|
||||||
|
Qdros, PlanInfo, Pensions, PensionMarriage, PensionDeath,
|
||||||
|
PensionSchedule, PensionSeparate, PensionResults,
|
||||||
|
RolexV, FVarLkup, RVarLkup,
|
||||||
|
# Modern tables
|
||||||
|
Client, Phone, Case, Transaction, Payment, Document
|
||||||
|
)
|
||||||
|
|
||||||
|
table_counts = {
|
||||||
|
'reference': {
|
||||||
|
'TrnsType': db.query(TrnsType).count(),
|
||||||
|
'TrnsLkup': db.query(TrnsLkup).count(),
|
||||||
|
'Footers': db.query(Footers).count(),
|
||||||
|
'FileStat': db.query(FileStat).count(),
|
||||||
|
'Employee': db.query(Employee).count(),
|
||||||
|
'GroupLkup': db.query(GroupLkup).count(),
|
||||||
|
'FileType': db.query(FileType).count(),
|
||||||
|
'FVarLkup': db.query(FVarLkup).count(),
|
||||||
|
'RVarLkup': db.query(RVarLkup).count(),
|
||||||
|
},
|
||||||
|
'core': {
|
||||||
|
'Rolodex': db.query(Rolodex).count(),
|
||||||
|
'LegacyPhone': db.query(LegacyPhone).count(),
|
||||||
|
'RolexV': db.query(RolexV).count(),
|
||||||
|
'LegacyFile': db.query(LegacyFile).count(),
|
||||||
|
'FilesR': db.query(FilesR).count(),
|
||||||
|
'FilesV': db.query(FilesV).count(),
|
||||||
|
'FileNots': db.query(FileNots).count(),
|
||||||
|
'Ledger': db.query(Ledger).count(),
|
||||||
|
'Deposits': db.query(Deposits).count(),
|
||||||
|
'LegacyPayment': db.query(LegacyPayment).count(),
|
||||||
|
},
|
||||||
|
'specialized': {
|
||||||
|
'PlanInfo': db.query(PlanInfo).count(),
|
||||||
|
'Qdros': db.query(Qdros).count(),
|
||||||
|
'Pensions': db.query(Pensions).count(),
|
||||||
|
'PensionMarriage': db.query(PensionMarriage).count(),
|
||||||
|
'PensionDeath': db.query(PensionDeath).count(),
|
||||||
|
'PensionSchedule': db.query(PensionSchedule).count(),
|
||||||
|
'PensionSeparate': db.query(PensionSeparate).count(),
|
||||||
|
'PensionResults': db.query(PensionResults).count(),
|
||||||
|
},
|
||||||
|
'modern': {
|
||||||
|
'Client': db.query(Client).count(),
|
||||||
|
'Phone': db.query(Phone).count(),
|
||||||
|
'Case': db.query(Case).count(),
|
||||||
|
'Transaction': db.query(Transaction).count(),
|
||||||
|
'Payment': db.query(Payment).count(),
|
||||||
|
'Document': db.query(Document).count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return templates.TemplateResponse("admin.html", {
|
return templates.TemplateResponse("admin.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"user": user,
|
"user": user,
|
||||||
"recent_imports": recent_imports,
|
"recent_imports": recent_imports,
|
||||||
"available_files": available_files,
|
"available_files": available_files,
|
||||||
|
"table_counts": table_counts,
|
||||||
"files_by_type": files_by_type
|
"files_by_type": files_by_type
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,162 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Database Status -->
|
||||||
|
{% if table_counts %}
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header bg-secondary text-white">
|
||||||
|
<h5 class="mb-0">
|
||||||
|
<i class="bi bi-database me-2"></i>Database Status - Imported Data
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="mb-3">View record counts for all tables to track import progress:</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Reference Tables -->
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<h6 class="text-primary"><i class="bi bi-bookmark me-2"></i>Reference Tables</h6>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Table</th>
|
||||||
|
<th class="text-end">Records</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for table_name, count in table_counts.reference.items() %}
|
||||||
|
<tr class="{{ 'table-success' if count > 0 else 'table-light' }}">
|
||||||
|
<td>
|
||||||
|
<small>{{ table_name }}</small>
|
||||||
|
{% if count > 0 %}
|
||||||
|
<i class="bi bi-check-circle-fill text-success ms-1"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<span class="badge {{ 'bg-success' if count > 0 else 'bg-secondary' }}">
|
||||||
|
{{ "{:,}".format(count) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Core Data Tables -->
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<h6 class="text-success"><i class="bi bi-folder me-2"></i>Core Data Tables</h6>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Table</th>
|
||||||
|
<th class="text-end">Records</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for table_name, count in table_counts.core.items() %}
|
||||||
|
<tr class="{{ 'table-success' if count > 0 else 'table-light' }}">
|
||||||
|
<td>
|
||||||
|
<small>{{ table_name }}</small>
|
||||||
|
{% if count > 0 %}
|
||||||
|
<i class="bi bi-check-circle-fill text-success ms-1"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<span class="badge {{ 'bg-success' if count > 0 else 'bg-secondary' }}">
|
||||||
|
{{ "{:,}".format(count) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Specialized Tables -->
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<h6 class="text-info"><i class="bi bi-file-earmark-medical me-2"></i>Specialized Tables</h6>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Table</th>
|
||||||
|
<th class="text-end">Records</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for table_name, count in table_counts.specialized.items() %}
|
||||||
|
<tr class="{{ 'table-success' if count > 0 else 'table-light' }}">
|
||||||
|
<td>
|
||||||
|
<small>{{ table_name }}</small>
|
||||||
|
{% if count > 0 %}
|
||||||
|
<i class="bi bi-check-circle-fill text-success ms-1"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<span class="badge {{ 'bg-success' if count > 0 else 'bg-secondary' }}">
|
||||||
|
{{ "{:,}".format(count) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modern Models -->
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<h6 class="text-warning"><i class="bi bi-stars me-2"></i>Modern Models</h6>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Table</th>
|
||||||
|
<th class="text-end">Records</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for table_name, count in table_counts.modern.items() %}
|
||||||
|
<tr class="{{ 'table-warning' if count > 0 else 'table-light' }}">
|
||||||
|
<td>
|
||||||
|
<small>{{ table_name }}</small>
|
||||||
|
{% if count > 0 %}
|
||||||
|
<i class="bi bi-check-circle-fill text-warning ms-1"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<span class="badge {{ 'bg-warning text-dark' if count > 0 else 'bg-secondary' }}">
|
||||||
|
{{ "{:,}".format(count) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-info mb-0">
|
||||||
|
<i class="bi bi-info-circle me-2"></i>
|
||||||
|
<strong>Legend:</strong>
|
||||||
|
<span class="badge bg-success ms-2">Green</span> = Has data imported |
|
||||||
|
<span class="badge bg-secondary ms-2">Gray</span> = No data yet |
|
||||||
|
<i class="bi bi-check-circle-fill text-success ms-3 me-1"></i> = Table populated
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- Import Order Guide -->
|
<!-- Import Order Guide -->
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header bg-info text-white">
|
<div class="card-header bg-info text-white">
|
||||||
|
|||||||
Reference in New Issue
Block a user