Steuerkram/src/Controllers/AssetController.php

252 lines
8.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Steuerkram\Controllers;
use Steuerkram\Models\Asset;
use Steuerkram\Models\AssetDepreciation;
use Steuerkram\View;
class AssetController
{
public function index(array $params): void
{
$assets = Asset::all();
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Anlagevermögen',
'content' => $this->renderView('assets/list', [
'assets' => $assets,
]),
'topbarActions' => '<a href="/assets/new" class="btn btn-primary">+ Wirtschaftsgut anlegen</a>',
]);
}
public function create(array $params): void
{
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Wirtschaftsgut anlegen',
'content' => $this->renderView('assets/form', [
'asset' => [],
'errors' => [],
'action' => '/assets',
'anlagearten' => Asset::anlagearten(),
'scheduleRows' => [],
]),
]);
}
public function store(array $params): void
{
$data = $this->extractPost();
$errors = $this->validate($data);
if ($errors) {
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Wirtschaftsgut anlegen',
'content' => $this->renderView('assets/form', [
'asset' => $data,
'errors' => $errors,
'action' => '/assets',
'anlagearten' => Asset::anlagearten(),
'scheduleRows' => [],
]),
]);
return;
}
$id = Asset::create($data);
$asset = Asset::find($id);
if ($asset && (int)($asset['automatisch_berechnet'] ?? 1) === 1) {
AssetDepreciation::generateAndSave($asset);
}
View::redirect('/assets/' . $id . '/edit', 'Wirtschaftsgut erfolgreich angelegt.');
}
public function edit(array $params): void
{
$asset = Asset::find((int)$params['id']);
if (!$asset) { http_response_code(404); return; }
$scheduleRows = AssetDepreciation::findByAsset((int)$asset['id']);
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Wirtschaftsgut bearbeiten',
'content' => $this->renderView('assets/form', [
'asset' => $asset,
'errors' => [],
'action' => '/assets/' . $asset['id'],
'anlagearten' => Asset::anlagearten(),
'scheduleRows' => $scheduleRows,
]),
]);
}
public function update(array $params): void
{
$id = (int)$params['id'];
$asset = Asset::find($id);
if (!$asset) { http_response_code(404); return; }
$data = $this->extractPost();
$errors = $this->validate($data);
if ($errors) {
$scheduleRows = AssetDepreciation::findByAsset($id);
$view = new View();
$view->render('layout/base.php', [
'pageTitle' => 'Wirtschaftsgut bearbeiten',
'content' => $this->renderView('assets/form', [
'asset' => array_merge($asset, $data),
'errors' => $errors,
'action' => '/assets/' . $id,
'anlagearten' => Asset::anlagearten(),
'scheduleRows' => $scheduleRows,
]),
]);
return;
}
// Wenn Parameter geändert und Tabelle war manuell: Flag beibehalten
$wasAutomatisch = (bool)(int)($asset['automatisch_berechnet'] ?? 1);
Asset::update($id, $data);
$updatedAsset = Asset::find($id);
$isAutomatisch = (bool)(int)($updatedAsset['automatisch_berechnet'] ?? 1);
if ($isAutomatisch) {
AssetDepreciation::generateAndSave($updatedAsset);
}
View::redirect('/assets/' . $id . '/edit', 'Wirtschaftsgut aktualisiert.');
}
public function destroy(array $params): void
{
$id = (int)$params['id'];
AssetDepreciation::deleteByAsset($id);
if (!Asset::delete($id)) {
View::redirect('/assets', 'Wirtschaftsgut konnte nicht gelöscht werden.', 'error');
return;
}
View::redirect('/assets', 'Wirtschaftsgut gelöscht.');
}
/**
* AJAX: Abschreibungstabelle vorschau berechnen (ohne DB-Speicherung)
* GET /assets/depreciation-preview?anschaffungskosten=...&nutzungsdauer=...&...
*/
public function depreciationPreview(array $params): void
{
header('Content-Type: application/json; charset=utf-8');
$asset = [
'anschaffungskosten' => (float)($_GET['anschaffungskosten'] ?? 0),
'zugaenge' => (float)($_GET['zugaenge'] ?? 0),
'abgaenge' => (float)($_GET['abgaenge'] ?? 0),
'nutzungsdauer' => (int)($_GET['nutzungsdauer'] ?? 0),
'cent_im_ersten_jahr'=> !empty($_GET['cent_im_ersten_jahr']) ? 1 : 0,
'anschaffungsdatum' => $_GET['anschaffungsdatum'] ?? date('Y-01-01'),
];
$rows = AssetDepreciation::calculate($asset);
echo json_encode(['rows' => $rows]);
}
/**
* AJAX: Manuell bearbeitete Abschreibungstabelle speichern
* POST /assets/{id}/depreciation
*/
public function saveDepreciation(array $params): void
{
header('Content-Type: application/json; charset=utf-8');
$id = (int)$params['id'];
$asset = Asset::find($id);
if (!$asset) {
http_response_code(404);
echo json_encode(['error' => 'Asset nicht gefunden']);
return;
}
$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body) || !isset($body['rows'])) {
http_response_code(400);
echo json_encode(['error' => 'Ungültige Daten']);
return;
}
$rows = [];
foreach ($body['rows'] as $i => $row) {
$rows[] = [
'jahr' => (int)($row['jahr'] ?? 0),
'abschreibungsbetrag' => (float)str_replace(',', '.', $row['abschreibungsbetrag'] ?? 0),
'restwert' => (float)str_replace(',', '.', $row['restwert'] ?? 0),
'position' => $i,
];
}
AssetDepreciation::saveForAsset($id, $rows);
// Flag setzen: wenn Rows manuell geändert
$automatisch = !empty($body['automatisch']) ? 1 : 0;
\Steuerkram\Database::execute(
'UPDATE assets SET automatisch_berechnet = ? WHERE id = ?',
[$automatisch, $id]
);
echo json_encode(['ok' => true]);
}
// ── Private helpers ──────────────────────────────────────────
private function extractPost(): array
{
return [
'bezeichnung' => trim($_POST['bezeichnung'] ?? ''),
'account_id' => trim($_POST['account_id'] ?? ''),
'anschaffungsdatum' => trim($_POST['anschaffungsdatum'] ?? ''),
'anschaffungskosten' => $_POST['anschaffungskosten'] ?? '0',
'zugaenge' => $_POST['zugaenge'] ?? '0',
'abgaenge' => $_POST['abgaenge'] ?? '0',
'abschreibung_jahr' => $_POST['abschreibung_jahr'] ?? '0',
'nutzungsdauer' => trim($_POST['nutzungsdauer'] ?? ''),
'automatisch_berechnet'=> isset($_POST['automatisch_berechnet']) ? (int)(bool)$_POST['automatisch_berechnet'] : 1,
'cent_im_ersten_jahr' => isset($_POST['cent_im_ersten_jahr']) ? 1 : 0,
'notizen' => trim($_POST['notizen'] ?? ''),
];
}
private function validate(array $data): array
{
$errors = [];
if ($data['bezeichnung'] === '') {
$errors['bezeichnung'] = 'Pflichtfeld';
}
if ($data['anschaffungsdatum'] === '') {
$errors['anschaffungsdatum'] = 'Pflichtfeld';
} elseif (!strtotime($data['anschaffungsdatum'])) {
$errors['anschaffungsdatum'] = 'Ungültiges Datum';
}
if (!is_numeric($data['anschaffungskosten']) || (float)$data['anschaffungskosten'] < 0) {
$errors['anschaffungskosten'] = 'Muss eine positive Zahl sein';
}
return $errors;
}
private function renderView(string $template, array $data): string
{
extract($data, EXTR_SKIP);
ob_start();
include dirname(__DIR__) . '/Views/' . $template . '.php';
return ob_get_clean();
}
}