diff --git a/src/Controllers/AssetController.php b/src/Controllers/AssetController.php index 8108981..cbc6c65 100644 --- a/src/Controllers/AssetController.php +++ b/src/Controllers/AssetController.php @@ -17,13 +17,17 @@ class AssetController extends BaseController { public function index(array $params): void { - $assets = Asset::all(); + $assets = Asset::all(); + $nurUnzugeordnet = ($_GET['filter'] ?? 'unzugeordnet') !== 'alle'; + $anlageBookings = Asset::anlagekontoBookings($nurUnzugeordnet); $view = new View(); $view->render('layout/base.php', [ 'pageTitle' => 'Anlagevermögen', 'content' => $this->renderView('assets/list', [ - 'assets' => $assets, + 'assets' => $assets, + 'anlageBookings' => $anlageBookings, + 'nurUnzugeordnet' => $nurUnzugeordnet, ]), 'topbarActions' => '' . '' @@ -35,11 +39,25 @@ class AssetController extends BaseController public function create(array $params): void { + $prefill = []; + if (!empty($_GET['bk_booking_id'])) { + $prefill['bk_booking_id'] = (int)$_GET['bk_booking_id']; + } + if (!empty($_GET['bk_account_id'])) { + $prefill['account_id'] = (int)$_GET['bk_account_id']; + } + if (!empty($_GET['bk_datum'])) { + $prefill['anschaffungsdatum'] = $_GET['bk_datum']; + } + if (isset($_GET['bk_betrag']) && $_GET['bk_betrag'] !== '') { + $prefill['anschaffungskosten'] = number_format((float)$_GET['bk_betrag'], 2, '.', ''); + } + $view = new View(); $view->render('layout/base.php', [ 'pageTitle' => 'Wirtschaftsgut anlegen', 'content' => $this->renderView('assets/form', [ - 'asset' => [], + 'asset' => $prefill, 'errors' => [], 'action' => '/assets', 'anlagearten' => Asset::anlagearten(), @@ -74,6 +92,14 @@ class AssetController extends BaseController AssetDepreciation::generateAndSave($asset); } + $bkBookingId = (int)($_POST['bk_booking_id'] ?? 0); + if ($bkBookingId > 0) { + \Steuerkram\Database::execute( + 'UPDATE bookings SET asset_id = ? WHERE id = ? AND asset_id IS NULL', + [$id, $bkBookingId] + ); + } + View::redirect('/assets/' . $id . '/edit', 'Wirtschaftsgut erfolgreich angelegt.'); } @@ -93,6 +119,8 @@ class AssetController extends BaseController ); $previousAfaKontoId = $prevAfaKonto ? (int)$prevAfaKonto['kategorie_konto_id'] : null; + $bookingHints = $this->buildBookingHints($asset); + $view = new View(); $view->render('layout/base.php', [ 'pageTitle' => 'Wirtschaftsgut bearbeiten', @@ -105,10 +133,33 @@ class AssetController extends BaseController 'abschreibungskonten' => $abschreibungskonten, 'previousAfaKontoId' => $previousAfaKontoId, 'testMode' => Setting::isTestMode(), + 'bookingHints' => $bookingHints, ]), ]); } + private function buildBookingHints(array $asset): array + { + $hints = []; + + $bkAccountId = isset($_GET['bk_account_id']) && $_GET['bk_account_id'] !== '' + ? (int)$_GET['bk_account_id'] : null; + $bkDatum = $_GET['bk_datum'] ?? ''; + + if ($bkAccountId !== null && (int)($asset['account_id'] ?? 0) !== $bkAccountId) { + $bkAccount = Account::find($bkAccountId); + $hints['account_id'] = $bkAccount + ? $bkAccount['kontonummer'] . ' – ' . $bkAccount['bezeichnung'] + : 'Konto-ID ' . $bkAccountId; + } + + if ($bkDatum !== '' && ($asset['anschaffungsdatum'] ?? '') !== $bkDatum) { + $hints['anschaffungsdatum'] = View::formatDate($bkDatum); + } + + return $hints; + } + public function update(array $params): void { $id = (int)$params['id']; @@ -150,9 +201,14 @@ class AssetController extends BaseController public function destroy(array $params): void { - $id = (int)$params['id']; - AssetDepreciation::deleteByAsset($id); - if (!Asset::delete($id)) { + $id = (int)$params['id']; + $result = Asset::delete($id); + + if ($result === 'hat_buchungen') { + View::redirect('/assets', 'Das Wirtschaftsgut kann nicht gelöscht werden, da noch Buchungen damit verknüpft sind.', 'error'); + return; + } + if (!$result) { View::redirect('/assets', 'Wirtschaftsgut konnte nicht gelöscht werden.', 'error'); return; } diff --git a/src/Models/Asset.php b/src/Models/Asset.php index 69bae38..b7fe502 100644 --- a/src/Models/Asset.php +++ b/src/Models/Asset.php @@ -203,11 +203,54 @@ class Asset ); } - public static function delete(int $id): bool + public static function anlagekontoBookings(bool $nurUnzugeordnet = true): array + { + $extraWhere = $nurUnzugeordnet ? 'AND (b.asset_id IS NULL OR a.id IS NULL)' : ''; + + return Database::fetchAll( + "SELECT + b.id, b.buchungs_nr, b.buchungs_datum, b.buchungstext, + b.betrag_netto, b.betrag_brutto, b.is_reversal, b.reversed_by, + b.asset_id, b.beleg_id, b.kategorie_konto_id, + ac.kontonummer AS kategorie_kontonummer, + ac.bezeichnung AS kategorie_bezeichnung, + zk.kontonummer AS zahlungs_kontonummer, + zk.bezeichnung AS zahlungs_bezeichnung, + a.bezeichnung AS asset_bezeichnung, + a.anlage_nr AS asset_anlage_nr + FROM bookings b + JOIN accounts ac ON b.kategorie_konto_id = ac.id + AND ac.kontenart = 'Anlagevermögen' + JOIN accounts zk ON b.zahlungskonto_id = zk.id + LEFT JOIN assets a ON b.asset_id = a.id + WHERE b.buchungstyp != 'AfA' + AND b.is_reversal = 0 + AND b.reversed_by IS NULL + $extraWhere + ORDER BY b.buchungs_datum DESC", + [] + ); + } + + /** + * Löscht ein Wirtschaftsgut inklusive AfA-Buchungen und Abschreibungstabelle. + * Gibt 'hat_buchungen' zurück, wenn noch reguläre Buchungen verknüpft sind. + */ + public static function delete(int $id): bool|string { $asset = self::find($id); if (!$asset) return false; + $linked = Database::fetchOne( + "SELECT COUNT(*) AS cnt FROM bookings WHERE asset_id = ? AND buchungstyp != 'AfA'", + [$id] + ); + if ($linked && (int)$linked['cnt'] > 0) { + return 'hat_buchungen'; + } + + Database::execute("DELETE FROM bookings WHERE asset_id = ? AND buchungstyp = 'AfA'", [$id]); + AssetDepreciation::deleteByAsset($id); Database::execute('DELETE FROM assets WHERE id = ?', [$id]); return true; } diff --git a/src/Views/assets/form.php b/src/Views/assets/form.php index af132b5..9908d6c 100644 --- a/src/Views/assets/form.php +++ b/src/Views/assets/form.php @@ -2,13 +2,27 @@ use Steuerkram\View; $h = fn($v) => View::h($v); -$assetId = (int)($asset['id'] ?? 0); -$isEdit = $assetId > 0; -$nutzung = isset($asset['nutzungsdauer']) && $asset['nutzungsdauer'] !== '' ? (int)$asset['nutzungsdauer'] : null; -$predefined = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 20, 25, 50]; -$isCustom = $nutzung !== null && !in_array($nutzung, $predefined, true); -$centFlag = !empty($asset['cent_im_ersten_jahr']); -$autoFlag = isset($asset['automatisch_berechnet']) ? (bool)(int)$asset['automatisch_berechnet'] : true; +$assetId = (int)($asset['id'] ?? 0); +$isEdit = $assetId > 0; +$nutzung = isset($asset['nutzungsdauer']) && $asset['nutzungsdauer'] !== '' ? (int)$asset['nutzungsdauer'] : null; +$predefined = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 20, 25, 50]; +$isCustom = $nutzung !== null && !in_array($nutzung, $predefined, true); +$centFlag = !empty($asset['cent_im_ersten_jahr']); +$autoFlag = isset($asset['automatisch_berechnet']) ? (bool)(int)$asset['automatisch_berechnet'] : true; +$bkHints = $bookingHints ?? []; + +$conflictBadge = function(string $field, string $label) use ($bkHints, $h): string { + if (!isset($bkHints[$field])) return ''; + $val = $h($bkHints[$field]); + return '' + . '' + . '' + . '' + . 'Buchung: ' . $val . ''; +}; ?>
@@ -16,7 +30,7 @@ $autoFlag = isset($asset['automatisch_berechnet']) ? (bool)(int)$asset['automa
- +
+ + + + + diff --git a/src/Views/assets/list.php b/src/Views/assets/list.php index 3e831d6..d5e7fa5 100644 --- a/src/Views/assets/list.php +++ b/src/Views/assets/list.php @@ -1,4 +1,17 @@ - View::h($v); ?> + View::h($v); + +$assetsJson = json_encode(array_map(fn($a) => [ + 'id' => (int)$a['id'], + 'lfd_nr' => (int)$a['lfd_nr'], + 'anlage_nr' => $a['anlage_nr'], + 'bezeichnung' => $a['bezeichnung'], + 'anschaffungsdatum' => $a['anschaffungsdatum'], + 'anschaffungskosten' => (float)$a['anschaffungskosten'], + 'account_id' => $a['account_id'] !== null ? (int)$a['account_id'] : null, +], $assets), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT); +?>
@@ -67,3 +80,244 @@
+
+
+

Buchungen auf Anlagevermögens-Konten

+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DatumBeleg-Nr.KontoBuchungstextBetragAnlagegut
+ + + + + + + + + + + € + + + + + + – + + + + + +
+ +
+
+
+
+ + + + + diff --git a/src/Views/tax/euer_show.php b/src/Views/tax/euer_show.php index d97d9e1..e168520 100644 --- a/src/Views/tax/euer_show.php +++ b/src/Views/tax/euer_show.php @@ -142,15 +142,15 @@ $fmt = fn($v) => View::formatMoney($v); - - - - - - - - - + + + + + + + + + @@ -170,17 +170,17 @@ $fmt = fn($v) => View::formatMoney($v); if ($al['nutzungsdauer'] === '0' || $al['nutzungsdauer'] === 0) $nd = 'sofort'; ?> - - - - - - - - - + + + + + + + +
Anlage-IDBezeichnungAnschaffungsdatumAnschaffungskostenNutzungsdauerAfA VorjahreRestbuchwert VorjahrAfA Restbuchwert 31.12.Anlage-IDBezeichnungAnschaff.-datumAnschaff.-kostenNutzungs-dauerAfA VorjahreRestbuch-wert VorjahrAfA Restbuch-wert 31.12.
+