$basis, 'afa_vorjahre' => $afaVorjahre, 'afa_jahr' => $afaJahr, 'restbuchwert_vorjahr' => $restbuchwertVorjahr, 'restbuchwert' => $restbuchwert, ]); } return $result; } public static function all(?int $fiscalYearId = null): array { $where = '1=1'; $params = []; if ($fiscalYearId !== null) { $where = 'a.fiscal_year_id = ?'; $params[] = $fiscalYearId; } return Database::fetchAll( "SELECT a.*, ac.kontonummer AS anlageart_kontonummer, ac.bezeichnung AS anlageart_bezeichnung FROM assets a LEFT JOIN accounts ac ON a.account_id = ac.id WHERE $where ORDER BY a.lfd_nr ASC, a.id ASC", $params ); } public static function find(int $id): array|false { return Database::fetchOne( 'SELECT a.*, ac.kontonummer AS anlageart_kontonummer, ac.bezeichnung AS anlageart_bezeichnung FROM assets a LEFT JOIN accounts ac ON a.account_id = ac.id WHERE a.id = ?', [$id] ); } public static function anlagearten(): array { return Database::fetchAll( "SELECT id, kontonummer, bezeichnung FROM accounts WHERE kontenart = 'Anlagevermögen' ORDER BY kontonummer ASC" ); } public static function nextLfdNr(): int { $row = Database::fetchOne('SELECT COALESCE(MAX(lfd_nr), 0) + 1 AS next FROM assets'); return (int)($row['next'] ?? 1); } public static function generateAnlageNr(): string { $settings = Database::fetchOne( 'SELECT anlage_nr_prefix, anlage_nr_next FROM company_settings WHERE id=1' ); $prefix = $settings['anlage_nr_prefix'] ?? 'ANL'; $next = (int)($settings['anlage_nr_next'] ?? 1); $year = date('Y'); $nr = sprintf('%s-%s-%04d', $prefix, $year, $next); Database::execute( 'UPDATE company_settings SET anlage_nr_next = anlage_nr_next + 1 WHERE id=1' ); return $nr; } public static function create(array $data): int { $fyId = null; if (!empty($data['anschaffungsdatum'])) { $year = (int)date('Y', strtotime($data['anschaffungsdatum'])); $fy = FiscalYear::findOrCreateByYear($year); $fyId = $fy['id']; } $anlageNr = $data['anlage_nr'] ?? self::generateAnlageNr(); Database::execute( 'INSERT INTO assets (lfd_nr, anlage_nr, bezeichnung, account_id, anschaffungsdatum, anschaffungskosten, zugaenge, abgaenge, abschreibung_jahr, nutzungsdauer, automatisch_berechnet, cent_im_ersten_jahr, notizen, fiscal_year_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ $data['lfd_nr'] ?? self::nextLfdNr(), $anlageNr, $data['bezeichnung'], isset($data['account_id']) && $data['account_id'] !== '' ? (int)$data['account_id'] : null, $data['anschaffungsdatum'], $data['anschaffungskosten'] ?? 0, $data['zugaenge'] ?? 0, $data['abgaenge'] ?? 0, $data['abschreibung_jahr'] ?? 0, isset($data['nutzungsdauer']) && $data['nutzungsdauer'] !== '' ? (int)$data['nutzungsdauer'] : null, isset($data['automatisch_berechnet']) ? (int)(bool)$data['automatisch_berechnet'] : 1, isset($data['cent_im_ersten_jahr']) ? (int)(bool)$data['cent_im_ersten_jahr'] : 0, $data['notizen'] ?? null, $fyId, ] ); return (int)Database::lastInsertId(); } public static function update(int $id, array $data): void { $fyId = null; if (!empty($data['anschaffungsdatum'])) { $year = (int)date('Y', strtotime($data['anschaffungsdatum'])); $fy = FiscalYear::findOrCreateByYear($year); $fyId = $fy['id']; } Database::execute( 'UPDATE assets SET bezeichnung = ?, account_id = ?, anschaffungsdatum = ?, anschaffungskosten = ?, zugaenge = ?, abgaenge = ?, abschreibung_jahr = ?, nutzungsdauer = ?, automatisch_berechnet = ?, cent_im_ersten_jahr = ?, notizen = ?, fiscal_year_id = COALESCE(?, fiscal_year_id), updated_at = NOW() WHERE id = ?', [ $data['bezeichnung'], isset($data['account_id']) && $data['account_id'] !== '' ? (int)$data['account_id'] : null, $data['anschaffungsdatum'], $data['anschaffungskosten'] ?? 0, $data['zugaenge'] ?? 0, $data['abgaenge'] ?? 0, $data['abschreibung_jahr'] ?? 0, isset($data['nutzungsdauer']) && $data['nutzungsdauer'] !== '' ? (int)$data['nutzungsdauer'] : null, isset($data['automatisch_berechnet']) ? (int)(bool)$data['automatisch_berechnet'] : 1, isset($data['cent_im_ersten_jahr']) ? (int)(bool)$data['cent_im_ersten_jahr'] : 0, $data['notizen'] ?? null, $fyId, $id, ] ); } 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; } }