Files
kimai2/templates/reporting/team_summary.html.twig
root 3cd198c12c
Some checks failed
Frontend / Frontend verification (push) Has been cancelled
Lint PHP / Linting (8.2) (push) Has been cancelled
Check .lock files / Verify lock file integrity (push) Has been cancelled
Release Drafter / Verify repository (push) Has been cancelled
Release Drafter / Draft next release (push) Has been cancelled
Tests / Integration (8.2) (push) Has been cancelled
Tests / Integration (8.3) (push) Has been cancelled
Tests / Integration (8.4) (push) Has been cancelled
Tests / Integration (8.5) (push) Has been cancelled
Actions Security Analysis / Scan workflows (push) Has been cancelled
Fix billable mapping (0=billable, 1=non-billable, 2=unproductive)
- Swapped billable/non-billable SQL values to match migrated data
- All 3 pivot tables always render (empty ones show 'No data')
- Added grand total row to pivot tables
- Initialize unprodRows/userColumnsUP to prevent undefined var error
2026-06-18 23:08:43 +00:00

114 lines
5.5 KiB
Twig
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'reporting/layout.html.twig' %}
{% block report %}
<div class="card">
<div class="card-header">
<form method="get" class="row g-2 align-items-center">
<div class="col-auto">
<select name="team" class="form-select form-select-sm" onchange="this.form.submit()">
<option value="">-- Select Team --</option>
{% for t in teams %}
<option value="{{ t.id }}" {% if selectedTeamId == t.id %}selected{% endif %}>{{ t.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-auto">
<input type="date" name="from" value="{{ from }}" class="form-control form-control-sm" onchange="this.form.submit()">
</div>
<div class="col-auto">
<input type="date" name="to" value="{{ to }}" class="form-control form-control-sm" onchange="this.form.submit()">
</div>
</form>
</div>
{% if team %}
<div class="card-body">
<h3>Time Analysis — {{ team.name }}</h3>
<small class="text-muted">{{ from }} {{ to }}</small>
{% if rows is empty %}
<div class="alert alert-info mt-3">No time entries found for this period.</div>
{% else %}
<table class="table table-striped table-hover table-sm mt-3">
<thead>
<tr>
<th>Name</th>
<th class="text-end">Billable</th>
<th class="text-end">Non-Billable</th>
<th class="text-end">Unproductive</th>
<th class="text-end">Total Hours</th>
</tr>
</thead>
<tbody>
{% set tb = 0 %}{% set tn = 0 %}{% set tu = 0 %}{% set tt = 0 %}
{% for r in rows %}
{% set tb = tb + r.billable_hours %}
{% set tn = tn + r.nonbillable_hours %}
{% set tu = tu + r.unproductive_hours %}
{% set tt = tt + r.total_hours %}
<tr>
<td>{{ r.alias ?: r.username }}</td>
<td class="text-end">{{ r.billable_hours|number_format(2) }}</td>
<td class="text-end">{{ r.nonbillable_hours|number_format(2) }}</td>
<td class="text-end">{{ r.unproductive_hours|number_format(2) }}</td>
<td class="text-end"><strong>{{ r.total_hours|number_format(2) }}</strong></td>
</tr>
{% endfor %}
<tr class="table-active fw-bold">
<td>TOTAL</td>
<td class="text-end">{{ tb|number_format(2) }}</td>
<td class="text-end">{{ tn|number_format(2) }}</td>
<td class="text-end">{{ tu|number_format(2) }}</td>
<td class="text-end">{{ tt|number_format(2) }}</td>
</tr>
</tbody>
</table>
{% macro pivot(rows, cols, title) %}
<h4 class="mt-4">{{ title }}</h4>
<div class="table-responsive">
<table class="table table-striped table-hover table-sm" style="font-size:11px">
<thead><tr>
<th>Company</th><th>Project</th>
{% for uc in cols %}<th class="text-end">{{ uc }}</th>{% endfor %}
<th class="text-end">TOTAL</th>
</tr></thead>
<tbody>
{% if rows is empty %}
<tr><td colspan="{{ cols|length + 3 }}" class="text-center text-muted">No data for this period</td></tr>
{% else %}
{% for pr in rows %}
<tr>
<td>{{ pr.company }}</td>
<td>{{ pr.project }}</td>
{% for uc in cols %}
<td class="text-end">{{ pr.users[uc]|default(0) > 0 ? pr.users[uc]|number_format(1) }}</td>
{% endfor %}
<td class="text-end"><strong>{{ pr.total|number_format(1) }}</strong></td>
</tr>
{% endfor %}
<tr class="table-active fw-bold">
<td colspan="2">TOTAL</td>
{% set gt = 0 %}
{% for uc in cols %}
{% set ct = 0 %}{% for pr in rows %}{% set ct = ct + pr.users[uc]|default(0) %}{% endfor %}
<td class="text-end"><strong>{{ ct > 0 ? ct|number_format(1) }}</strong></td>
{% set gt = gt + ct %}
{% endfor %}
<td class="text-end"><strong>{{ gt|number_format(1) }}</strong></td>
</tr>
{% endif %}
</tbody>
</table></div>
{% endmacro %}
{% import _self as self %}
{{ self.pivot(projectRows, userColumns, 'Billable Projects') }}
{{ self.pivot(nonbillRows, userColumnsNB, 'Non-Billable Projects') }}
{{ self.pivot(unprodRows, userColumnsUP, 'Unproductive Projects') }}
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}