Merge pull request 'Feature: Zahlart-Filter im Personenreport' (#12) from fds2610-bot/FSCash:main into main

Reviewed-on: https://codeberg.org/fds2610/FSCash/pulls/12
This commit is contained in:
fds2610 2026-07-26 14:19:32 +02:00
commit efae709868
5 changed files with 110 additions and 9 deletions

View file

@ -97,10 +97,20 @@ h1 {
outline: none;
}
#categories_rep_person {
.category-checkbox-list {
font-size: 12px;
}
.filter-columns {
display: flex;
flex-wrap: wrap;
gap: 40px;
}
.filter-column {
min-width: 160px;
}
.btn-submit {
display: inline-block;
background: var(--primary-color);

View file

@ -94,6 +94,7 @@ foreach ($entries as $entry) {
$presetZahler = isset($_GET['zahler']) ? $_GET['zahler'] : '';
$presetKategorie = isset($_GET['kategorie']) ? $_GET['kategorie'] : '';
$presetKategorien = isset($_GET['kategorien']) && is_array($_GET['kategorien']) ? $_GET['kategorien'] : [];
$presetZahlweisen = isset($_GET['zahlweisen']) && is_array($_GET['zahlweisen']) ? $_GET['zahlweisen'] : [];
$filterZahler = array_keys($filterZahler);
$filterPersonen = array_keys($filterPersonen);
@ -240,6 +241,8 @@ document.querySelector('.hamburger').addEventListener('click', function() {
const sumValue = document.getElementById('sum-value');
// Mehrfach-Kategorie-Vorauswahl, z. B. per Link aus dem Personenreport (Kategorie-Select kann nur einen Wert anzeigen)
const presetKategorien = <?= json_encode(array_map('strtolower', $presetKategorien)) ?>;
// Mehrfach-Zahlweise-Vorauswahl, z. B. per Link aus dem Personenreport (Zahlweise-Select kann nur einen Wert anzeigen)
const presetZahlweisen = <?= json_encode(array_map('strtolower', $presetZahlweisen)) ?>;
function applyFilters() {
const activeFilters = Array.from(filters)
@ -253,7 +256,8 @@ document.querySelector('.hamburger').addEventListener('click', function() {
const cell = cells[f.col];
if (!cell) return true;
return cell.textContent.trim().toLowerCase().includes(f.value);
}) && (presetKategorien.length === 0 || (cells[3] && presetKategorien.includes(cells[3].textContent.trim().toLowerCase())));
}) && (presetKategorien.length === 0 || (cells[3] && presetKategorien.includes(cells[3].textContent.trim().toLowerCase())))
&& (presetZahlweisen.length === 0 || (cells[4] && presetZahlweisen.includes(cells[4].textContent.trim().toLowerCase())));
row.style.display = visible ? '' : 'none';
if (visible) {
const amountCell = cells[6];

View file

@ -123,6 +123,23 @@ function fscash_resolve_selected_categories(array $allCategoryIds, $requestedCat
return $allCategoryIds;
}
/**
* Ermittelt die im Personenreport ausgewählten Zahlweise-IDs: die per
* Request übergebenen, sofern vorhanden, sonst alle verfügbaren.
*
* @param int[] $allPaymentMethodIds Alle in der DB vorhandenen Zahlweise-IDs.
* @param mixed $requestedPaymentMethodIds Roher Wert aus $_GET['payment_methods'] (oder null, falls nicht gesetzt).
* @return array<int,mixed>
*/
function fscash_resolve_selected_payment_methods(array $allPaymentMethodIds, $requestedPaymentMethodIds): array
{
if (is_array($requestedPaymentMethodIds) && $requestedPaymentMethodIds !== []) {
return $requestedPaymentMethodIds;
}
return $allPaymentMethodIds;
}
/**
* Extrahiert den aktuellen Kurs aus einer Alpha-Vantage GLOBAL_QUOTE-Antwort.
*

View file

@ -32,8 +32,18 @@ $selectedCategories = fscash_resolve_selected_categories(
$_GET['categories'] ?? null
);
// Zahlweisen aus der Datenbank abrufen
$paymentMethodStmt = $pdo->query("SELECT payment_method_id, name FROM payment_methods ORDER BY name");
$paymentMethods = $paymentMethodStmt->fetchAll();
// Daten abrufen für den ausgewählten Monat und die ausgewählten Kategorien
// Standardmäßig alle Zahlweisen auswählen, falls keine Auswahl getroffen wurde
$selectedPaymentMethods = fscash_resolve_selected_payment_methods(
array_column($paymentMethods, 'payment_method_id'),
$_GET['payment_methods'] ?? null
);
// Daten abrufen für den ausgewählten Monat, die ausgewählten Kategorien und Zahlweisen
$sql = "
SELECT
u.id AS user_id,
@ -46,11 +56,12 @@ entries e ON e.user_id = u.id
AND MONTH(e.date) = ?
AND YEAR(e.date) = ?
AND e.category IN (" . implode(',', array_fill(0, count($selectedCategories), '?')) . ")
AND e.payment_method IN (" . implode(',', array_fill(0, count($selectedPaymentMethods), '?')) . ")
GROUP BY
u.id, u.username;
";
$params = array_merge([$month, $year], $selectedCategories);
$params = array_merge([$month, $year], $selectedCategories, $selectedPaymentMethods);
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$entries = $stmt->fetchAll();
@ -62,6 +73,14 @@ foreach ($categories as $category) {
$selectedCategoryNames[] = $category['name'];
}
}
// Namen der aktuell ausgewählten Zahlweisen ermitteln (für den Link zum Dashboard)
$selectedPaymentMethodNames = [];
foreach ($paymentMethods as $paymentMethod) {
if (in_array($paymentMethod['payment_method_id'], $selectedPaymentMethods)) {
$selectedPaymentMethodNames[] = $paymentMethod['name'];
}
}
?>
<!DOCTYPE html>
<html lang="de">
@ -93,10 +112,13 @@ foreach ($categories as $category) {
<h2><?= strftime('%B %Y', mktime(0, 0, 0, $month, 1, $year)) ?></h2>
<!-- Multiselect für Kategorien -->
<!-- Multiselect für Kategorien und Zahlweisen -->
<form method="get" action="rep-person.php" class="category-filter">
<input type="hidden" name="year" value="<?= $year ?>">
<input type="hidden" name="month" value="<?= $month ?>">
<div class="filter-columns">
<div class="filter-column">
<label for="categories">Kategorien:</label>
<div class="category-checkbox-list" id="categories_rep_person">
@ -113,6 +135,27 @@ foreach ($categories as $category) {
</label><br/>
<?php endforeach; ?>
<br/></div>
</div>
<div class="filter-column">
<label for="payment_methods">Zahlweisen:</label>
<div class="category-checkbox-list" id="payment_methods_rep_person">
<?php foreach ($paymentMethods as $paymentMethod): ?>
<label class="category-checkbox">
<input
type="checkbox"
name="payment_methods[]"
value="<?= $paymentMethod['payment_method_id'] ?>"
<?= in_array($paymentMethod['payment_method_id'], $selectedPaymentMethods) ? 'checked' : '' ?>
onchange="this.form.submit()"
>
<?= htmlspecialchars($paymentMethod['name']) ?>
</label><br/>
<?php endforeach; ?>
<br/></div>
</div>
</div>
<!-- button type="submit">Filtern</button -->
</form>
@ -130,10 +173,11 @@ foreach ($categories as $category) {
<td><?= htmlspecialchars($entry['username'] ?? '') ?></td>
<td class="align-right">
<a href="dashboard.php?<?= http_build_query([
'year' => $year,
'month' => $month,
'zahler' => $entry['username'] ?? '',
'kategorien' => $selectedCategoryNames,
'year' => $year,
'month' => $month,
'zahler' => $entry['username'] ?? '',
'kategorien' => $selectedCategoryNames,
'zahlweisen' => $selectedPaymentMethodNames,
]) ?>">
<?= htmlspecialchars(number_format($entry['gesamtbetrag'], 2, ',', '.')) ?>
</a>

View file

@ -187,6 +187,32 @@ final class FscashTest extends TestCase
);
}
// --- fscash_resolve_selected_payment_methods --------------------------
public function testResolveSelectedPaymentMethodsMitAuswahl(): void
{
$this->assertSame(
[2, 3],
fscash_resolve_selected_payment_methods([1, 2, 3, 4], [2, 3])
);
}
public function testResolveSelectedPaymentMethodsOhneAuswahlLiefertAlle(): void
{
$this->assertSame(
[1, 2, 3, 4],
fscash_resolve_selected_payment_methods([1, 2, 3, 4], null)
);
}
public function testResolveSelectedPaymentMethodsBeiLeeremArrayLiefertAlle(): void
{
$this->assertSame(
[1, 2, 3, 4],
fscash_resolve_selected_payment_methods([1, 2, 3, 4], [])
);
}
// --- fscash_extract_quote_price --------------------------------------
public function testExtractQuotePriceLiestPreisAus(): void