render('layout/base.php', [ 'pageTitle' => 'Anlagevermögen', 'content' => $this->renderView('assets/list', [ 'assets' => $assets, ]), 'topbarActions' => '+ Wirtschaftsgut anlegen', ]); } 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(); } }