252 lines
8.9 KiB
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();
|
|
}
|
|
}
|