05/08 Phase 4
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
{% extends "tenant/layouts/base.html" %}
|
||||
{% block title %}Calculate Pay Period{% endblock %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header fw-semibold">Calculate Pay Period</div>
|
||||
<div class="card-body">
|
||||
<form method="POST" novalidate>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col">
|
||||
<label class="form-label">Period Start <span class="text-danger">*</span></label>
|
||||
<input type="date" class="form-control" name="period_start"
|
||||
value="{{ period_start.isoformat() if period_start else '' }}" required>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label class="form-label">Period End <span class="text-danger">*</span></label>
|
||||
<input type="date" class="form-control" name="period_end"
|
||||
value="{{ period_end.isoformat() if period_end else '' }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Staff Members <small class="text-muted">(leave blank for all)</small></label>
|
||||
<select class="form-select" name="staff_ids" multiple size="6">
|
||||
{% for s in staff_list %}
|
||||
<option value="{{ s.id }}">{{ s.name }} — {{ s.pay_type.title() }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-text">Hold Ctrl/Cmd to select multiple.</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Calculate</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if results %}
|
||||
<div class="col-md-7">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header fw-semibold">
|
||||
Results — {{ period_start.strftime('%b %d') if period_start else '' }}–{{ period_end.strftime('%b %d, %Y') if period_end else '' }}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr><th>Staff</th><th>Type</th><th>Hours</th><th>Base</th><th>Commission</th><th>Total</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in results %}
|
||||
<tr>
|
||||
<td class="fw-semibold">{{ row.staff.name }}</td>
|
||||
<td class="small">{{ row.calc.pay_type.title() }}</td>
|
||||
<td class="small">{{ "%.1f"|format(row.calc.total_hours) }}h</td>
|
||||
<td>${{ "%.2f"|format(row.calc.base_amount) }}</td>
|
||||
<td>${{ "%.2f"|format(row.calc.commission_amount) }}</td>
|
||||
<td class="fw-bold">${{ "%.2f"|format(row.calc.total_amount) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot class="table-light fw-bold">
|
||||
<tr>
|
||||
<td colspan="5">Grand Total</td>
|
||||
<td>${{ "%.2f"|format(results|sum(attribute='calc.total_amount')) }}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer text-muted small">
|
||||
Records saved as drafts. Go to <a href="{{ url_for('pay_periods.index') }}">Pay Periods</a> to approve and mark as paid.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,53 @@
|
||||
{% extends "tenant/layouts/base.html" %}
|
||||
{% block title %}Pay Periods{% endblock %}
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h4 class="fw-bold mb-0"><i class="bi bi-wallet2 me-2"></i>Pay Periods</h4>
|
||||
<a href="{{ url_for('pay_periods.calculate') }}" class="btn btn-primary btn-sm">Calculate Period</a>
|
||||
</div>
|
||||
|
||||
{% if periods %}
|
||||
<div class="card shadow-sm">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr><th>Staff</th><th>Period</th><th>Type</th><th>Base</th><th>Commission</th><th>Topup</th><th>Total</th><th>Status</th><th></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pp in periods %}
|
||||
<tr>
|
||||
<td class="fw-semibold">{{ pp.staff.name if pp.staff else pp.staff_id }}</td>
|
||||
<td class="small text-nowrap">{{ pp.period_start.strftime('%b %d') }}–{{ pp.period_end.strftime('%b %d, %Y') }}</td>
|
||||
<td class="small">{{ pp.pay_type.title() }}</td>
|
||||
<td>${{ "%.2f"|format(pp.base_amount) }}</td>
|
||||
<td>${{ "%.2f"|format(pp.commission_amount) }}</td>
|
||||
<td>{{ '$' ~ "%.2f"|format(pp.guarantee_topup) if pp.guarantee_topup > 0 else '—' }}</td>
|
||||
<td class="fw-bold">${{ "%.2f"|format(pp.total_amount) }}</td>
|
||||
<td>
|
||||
<span class="badge bg-{{ {'draft':'secondary','approved':'primary','paid':'success'}.get(pp.status,'secondary') }}">
|
||||
{{ pp.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="d-flex gap-1">
|
||||
{% if pp.status == 'draft' %}
|
||||
<form method="POST" action="{{ url_for('pay_periods.approve', pp_id=pp.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-outline-primary btn-sm">Approve</button>
|
||||
</form>
|
||||
{% elif pp.status == 'approved' %}
|
||||
<form method="POST" action="{{ url_for('pay_periods.mark_paid', pp_id=pp.id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button class="btn btn-outline-success btn-sm">Mark Paid</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-light">No pay periods calculated yet. Use <strong>Calculate Period</strong> to get started.</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user