From b0bb865a875871b3f72653a381d39f173646fb8b Mon Sep 17 00:00:00 2001 From: younes elhaddoury <167001847+elhy17@users.noreply.github.com> Date: Sun, 31 Aug 2025 17:11:58 +0200 Subject: [PATCH] =?UTF-8?q?=C3=9Cberarbeite=20Fahrzeugverwaltung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 150 ++------------ WpfApp4/App.xaml.cs | 5 +- WpfApp4/DatabaseService.cs | 360 +++++++++++----------------------- WpfApp4/Fahrzeug.cs | 194 +++--------------- WpfApp4/FahrzeugVerwaltung.cs | 193 ------------------ WpfApp4/MainWindow.xaml | 27 ++- WpfApp4/MainWindow.xaml.cs | 349 ++++++++++++++------------------ WpfApp4/PdfService.cs | 290 ++++----------------------- 8 files changed, 364 insertions(+), 1204 deletions(-) delete mode 100644 WpfApp4/FahrzeugVerwaltung.cs diff --git a/README.md b/README.md index fc5e281..1e1f9c2 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,24 @@ -# WpfApp4AutoHandlung -# 🚗 Fahrzeugverwaltung +# Fahrzeugverwaltung -Ein modernes C# WPF-Anwendungssystem zur effizienten Verwaltung von Fahrzeugen mit automatischer Wertermittlung und PDF-Berichtserstellung. +Ein einfaches WPF-Projekt zur Verwaltung von Fahrzeugen. Daten werden in einer lokalen SQLite-Datenbank gespeichert. -## 📋 Projektübersicht +## Funktionen +- Fahrzeuge anlegen, bearbeiten und löschen +- Suche und Übersicht mit DataGrid +- Export eines Fahrzeugs als PDF +- Berechnung eines ungefähren Fahrzeugwerts -Die Fahrzeugverwaltung ist eine Desktop-Anwendung, die es Autohändlern, Fuhrparkmanagern und Privatpersonen ermöglicht, ihre Fahrzeuge strukturiert zu verwalten. Das System bietet eine intuitive Benutzeroberfläche zur Erfassung von Fahrzeugdaten, automatische Wertberechnung basierend auf Alter und Kilometerstand sowie professionelle PDF-Berichte. +## Bedienung +1. Marke und Modell wählen, restliche Felder ausfüllen. +2. **Hinzufügen** speichert ein neues Fahrzeug. +3. Ein Fahrzeug in der Liste auswählen und mit **Bearbeiten** ändern oder mit **Löschen** entfernen. +4. **Als PDF speichern** erzeugt ein Informationsblatt. -## ✨ Features +## Entwicklung +Dieses Projekt wurde im Rahmen einer Übung von **Younes**, **Saad** und **Ayman** erstellt. -### 🔧 Fahrzeugverwaltung -- **Vollständige Datenverwaltung**: Marke, Modell, Baujahr, Leistung, Kilometerstand, Farbe und Kaufpreis -- **Automatische Wertberechnung**: Intelligente Ermittlung des aktuellen Fahrzeugwerts -- **Oldtimer-Erkennung**: Automatische Klassifizierung von Fahrzeugen über 30 Jahren -- **Formatierte Anzeige**: Benutzerfreundliche Darstellung von Preisen und Kilometerständen - -### 📊 Berichte & Export -- **Einzelfahrzeug-PDF**: Detaillierte Infoblätter mit allen Fahrzeugdaten -- **Fahrzeugliste-PDF**: Übersichtliche Tabelle aller verwalteten Fahrzeuge -- **Zusammenfassungen**: Gesamtwerte, Wertverluste und statistische Auswertungen -- **Professionelles Design**: Moderne PDF-Layouts mit strukturierten Tabellen - -### 🧮 Wertermittlung -- **Altersbasierte Bewertung**: 15% Wertverlust in den ersten 3 Jahren, dann 10% jährlich -- **Kilometerstand-Faktor**: 2% Wertverlust pro 10.000 km -- **Mindestwert-Schutz**: Automatische Begrenzung auf mindestens 5% des Kaufpreises -- **Transparente Berechnung**: Nachvollziehbare Bewertungslogik - -## 🛠️ Technologie-Stack - -- **Framework**: .NET Framework / .NET Core -- **UI-Technologie**: WPF (Windows Presentation Foundation) -- **PDF-Generierung**: iTextSharp -- **Datenbank** : SQLite -- **Programmiersprache**: C# -- **Architektur**: MVVM Pattern - -## 📦 Installation - -### Voraussetzungen -- Windows 10 oder höher -- .NET Framework 4.8 oder .NET 6.0+ -- Visual Studio 2019+ (für Entwicklung) - -## 🚀 Verwendung - -### Neues Fahrzeug hinzufügen -1. Anwendung starten -2. "Neues Fahrzeug" Button klicken -3. Fahrzeugdaten eingeben -4. Speichern - automatische Wertberechnung erfolgt - -## 🎯 Kernkomponenten - -### Fahrzeug-Klasse -- Eigenschaften für alle Fahrzeugdaten -- Automatische Formatierung von Preisen und Kilometerständen -- Berechnungsmethoden für Alter und aktuellen Wert -- Oldtimer-Statusprüfung - -### PdfService -- Erstellung detaillierter Fahrzeug-Infoblätter -- Generierung von Fahrzeuglisten im Tabellenformat -- Professionelle Formatierung mit iTextSharp -- Automatische Zusammenfassungen und Statistiken - -## 🔄 Wertberechnungslogik - -```csharp -// Vereinfachtes Beispiel der Wertberechnung -public decimal BerechneAktuellenWert() -{ - decimal wert = Kaufpreis; - - // Altersbasierte Abschreibung - int alter = GetAlter(); - for (int i = 0; i < alter; i++) - { - decimal abschreibung = (i < 3) ? 0.15m : 0.10m; - wert *= (1 - abschreibung); - } - - // Kilometerstand-Abschreibung - decimal kmAbschreibung = (Kilometerstand / 10000) * 0.02m; - wert *= (1 - kmAbschreibung); - - // Mindestwert sicherstellen - decimal mindestwert = Kaufpreis * 0.05m; - return Math.Max(wert, mindestwert); -} +## Start ``` - -## 🤝 Beitragen - -Beiträge sind willkommen! Bitte beachten Sie: - -1. Fork des Repositories -2. Feature-Branch erstellen (`git checkout -b feature/AmazingFeature`) -3. Änderungen committen (`git commit -m 'Add some AmazingFeature'`) -4. Branch pushen (`git push origin feature/AmazingFeature`) -5. Pull Request erstellen - -## 📋 Roadmap - -- [ ] Datenbankintegration (SQLite/SQL Server) -- [ ] Erweiterte Suchfunktionen -- [ ] Fahrzeugbilder-Verwaltung -- [ ] Export nach Excel -- [ ] Wartungshistorie -- [ ] Benachrichtigungen für TÜV/Wartung -- [ ] Multi-User-Unterstützung -- [ ] Web-API für externe Systeme - -## 🐛 Bekannte Probleme - -- PDF-Generierung kann bei sehr großen Listen langsam sein -- PDF-Öffnung direkt nach dem Saving funktioniert nicht -- Währungsformatierung ist derzeit nur für EUR optimiert -- Keine Unterstützung für Fahrzeuge vor 1900 - -## 📜 Lizenz - -Dieses Projekt ist unter der YSA Lizenz lizenziert - siehe [LICENSE](LICENSE) Datei für Details. - -## 👥 Autor - -**El Haddoury Younes Ayman Alshian Saad Akki ** - *Initial work* - -## 🙏 Danksagungen - -- iTextSharp Team für die ausgezeichnete PDF-Bibliothek -- Microsoft für das WPF Framework -- Allen Testern und Contributoren - ---- - -⭐ **Gefällt Ihnen das Projekt? Geben Sie uns einen Stern!** ⭐ \ No newline at end of file +dotnet build +``` +Die Anwendung kann anschließend mit Visual Studio oder `dotnet run` gestartet werden. diff --git a/WpfApp4/App.xaml.cs b/WpfApp4/App.xaml.cs index 574fb08..81b3d11 100644 --- a/WpfApp4/App.xaml.cs +++ b/WpfApp4/App.xaml.cs @@ -6,15 +6,15 @@ namespace FahrzeugVerwaltung public partial class App : Application { + // startet die Anwendung und richtet Fehlerbehandlung ein protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); - - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; DispatcherUnhandledException += App_DispatcherUnhandledException; } + // behandelt UI-Ausnahmen private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show($"Ein unerwarteter Fehler ist aufgetreten:\n{e.Exception.Message}", @@ -22,6 +22,7 @@ namespace FahrzeugVerwaltung e.Handled = true; } + // behandelt kritische Ausnahmen private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show($"Ein kritischer Fehler ist aufgetreten:\n{((Exception)e.ExceptionObject).Message}", diff --git a/WpfApp4/DatabaseService.cs b/WpfApp4/DatabaseService.cs index 3cfa15e..227b136 100644 --- a/WpfApp4/DatabaseService.cs +++ b/WpfApp4/DatabaseService.cs @@ -1,8 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Data.SQLite; using System.IO; -using System.Linq; namespace FahrzeugVerwaltung { @@ -18,288 +17,155 @@ namespace FahrzeugVerwaltung InitializeDatabase(); } - /// - /// Initialisiert die Datenbank und erstellt die Tabelle falls sie nicht existiert - /// + // erstellt die Datenbank und Tabelle private void InitializeDatabase() { - try - { - using (var connection = new SQLiteConnection(_connectionString)) - { - connection.Open(); - - string createTableQuery = @" - CREATE TABLE IF NOT EXISTS Fahrzeuge ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - Marke TEXT NOT NULL, - Modell TEXT NOT NULL, - Baujahr INTEGER NOT NULL, - Leistung INTEGER NOT NULL, - Kilometerstand INTEGER NOT NULL, - Kaufpreis DECIMAL(10,2) NOT NULL, - Farbe TEXT NOT NULL, - ErstelltAm DATETIME DEFAULT CURRENT_TIMESTAMP - )"; - - using (var command = new SQLiteCommand(createTableQuery, connection)) - { - command.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - throw new Exception($"Fehler beim Initialisieren der Datenbank: {ex.Message}"); - } + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = @" + CREATE TABLE IF NOT EXISTS Fahrzeuge ( + Id INTEGER PRIMARY KEY AUTOINCREMENT, + Marke TEXT NOT NULL, + Modell TEXT NOT NULL, + Baujahr INTEGER NOT NULL, + Leistung INTEGER NOT NULL, + Kilometerstand INTEGER NOT NULL, + Kaufpreis DECIMAL(10,2) NOT NULL, + Farbe TEXT NOT NULL, + ErstelltAm DATETIME DEFAULT CURRENT_TIMESTAMP + )"; + using var command = new SQLiteCommand(query, connection); + command.ExecuteNonQuery(); } - /// - /// Speichert ein neues Fahrzeug in der Datenbank - /// - /// Das zu speichernde Fahrzeug - /// Die ID des gespeicherten Fahrzeugs + // speichert ein Fahrzeug und gibt die neue Id zurück public int SpeichereFahrzeug(Fahrzeug fahrzeug) { - try - { - using (var connection = new SQLiteConnection(_connectionString)) - { - connection.Open(); - - string insertQuery = @" - INSERT INTO Fahrzeuge (Marke, Modell, Baujahr, Leistung, Kilometerstand, Kaufpreis, Farbe) - VALUES (@Marke, @Modell, @Baujahr, @Leistung, @Kilometerstand, @Kaufpreis, @Farbe); - SELECT last_insert_rowid();"; - - using (var command = new SQLiteCommand(insertQuery, connection)) - { - command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); - command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); - command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); - command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); - command.Parameters.AddWithValue("@Kilometerstand", fahrzeug.Kilometerstand); - command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); - command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); - - var result = command.ExecuteScalar(); - return Convert.ToInt32(result); - } - } - } - catch (Exception ex) - { - throw new Exception($"Fehler beim Speichern des Fahrzeugs: {ex.Message}"); - } + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = @" + INSERT INTO Fahrzeuge (Marke, Modell, Baujahr, Leistung, Kilometerstand, Kaufpreis, Farbe) + VALUES (@Marke, @Modell, @Baujahr, @Leistung, @Kilometer, @Kaufpreis, @Farbe); + SELECT last_insert_rowid();"; + using var command = new SQLiteCommand(query, connection); + command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); + command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); + command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); + command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); + command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); + command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); + command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); + return Convert.ToInt32(command.ExecuteScalar()); } - /// - /// Lädt alle Fahrzeuge aus der Datenbank - /// - /// Liste aller Fahrzeuge + // lädt alle Fahrzeuge public List LadeAlleFahrzeuge() { var fahrzeuge = new List(); - - try + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = "SELECT * FROM Fahrzeuge ORDER BY Marke, Modell"; + using var command = new SQLiteCommand(query, connection); + using var reader = command.ExecuteReader(); + while (reader.Read()) { - using (var connection = new SQLiteConnection(_connectionString)) + fahrzeuge.Add(new Fahrzeug { - connection.Open(); - - string selectQuery = "SELECT * FROM Fahrzeuge ORDER BY Marke, Modell"; - - using (var command = new SQLiteCommand(selectQuery, connection)) - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - var fahrzeug = new Fahrzeug - { - Id = Convert.ToInt32(reader["Id"]), - Marke = reader["Marke"].ToString(), - Modell = reader["Modell"].ToString(), - Baujahr = Convert.ToInt32(reader["Baujahr"]), - Leistung = Convert.ToInt32(reader["Leistung"]), - Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), - Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), - Farbe = reader["Farbe"].ToString() - }; - - fahrzeuge.Add(fahrzeug); - } - } - } + Id = Convert.ToInt32(reader["Id"]), + Marke = reader["Marke"].ToString(), + Modell = reader["Modell"].ToString(), + Baujahr = Convert.ToInt32(reader["Baujahr"]), + Leistung = Convert.ToInt32(reader["Leistung"]), + Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), + Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), + Farbe = reader["Farbe"].ToString() + }); } - catch (Exception ex) - { - throw new Exception($"Fehler beim Laden der Fahrzeuge: {ex.Message}"); - } - return fahrzeuge; } - /// - /// Sucht Fahrzeuge basierend auf einem Suchbegriff - /// - /// Der Suchbegriff - /// Liste der gefundenen Fahrzeuge + // sucht Fahrzeuge nach Begriff public List SucheFahrzeuge(string suchbegriff) { - var fahrzeuge = new List(); - if (string.IsNullOrWhiteSpace(suchbegriff)) return LadeAlleFahrzeuge(); - try + var fahrzeuge = new List(); + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = @" + SELECT * FROM Fahrzeuge + WHERE Marke LIKE @S + OR Modell LIKE @S + OR Farbe LIKE @S + OR CAST(Baujahr AS TEXT) LIKE @S + ORDER BY Marke, Modell"; + using var command = new SQLiteCommand(query, connection); + command.Parameters.AddWithValue("@S", $"%{suchbegriff}%"); + using var reader = command.ExecuteReader(); + while (reader.Read()) { - using (var connection = new SQLiteConnection(_connectionString)) + fahrzeuge.Add(new Fahrzeug { - connection.Open(); - - string searchQuery = @" - SELECT * FROM Fahrzeuge - WHERE Marke LIKE @Suchbegriff - OR Modell LIKE @Suchbegriff - OR Farbe LIKE @Suchbegriff - OR CAST(Baujahr AS TEXT) LIKE @Suchbegriff - ORDER BY Marke, Modell"; - - using (var command = new SQLiteCommand(searchQuery, connection)) - { - command.Parameters.AddWithValue("@Suchbegriff", $"%{suchbegriff}%"); - - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - var fahrzeug = new Fahrzeug - { - Id = Convert.ToInt32(reader["Id"]), - Marke = reader["Marke"].ToString(), - Modell = reader["Modell"].ToString(), - Baujahr = Convert.ToInt32(reader["Baujahr"]), - Leistung = Convert.ToInt32(reader["Leistung"]), - Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), - Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), - Farbe = reader["Farbe"].ToString() - }; - - fahrzeuge.Add(fahrzeug); - } - } - } - } + Id = Convert.ToInt32(reader["Id"]), + Marke = reader["Marke"].ToString(), + Modell = reader["Modell"].ToString(), + Baujahr = Convert.ToInt32(reader["Baujahr"]), + Leistung = Convert.ToInt32(reader["Leistung"]), + Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]), + Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]), + Farbe = reader["Farbe"].ToString() + }); } - catch (Exception ex) - { - throw new Exception($"Fehler beim Suchen der Fahrzeuge: {ex.Message}"); - } - return fahrzeuge; } - /// - /// Aktualisiert ein bestehendes Fahrzeug in der Datenbank - /// - /// Das zu aktualisierende Fahrzeug - /// True wenn erfolgreich, sonst False + // aktualisiert ein Fahrzeug public bool AktualisiereFahrzeug(Fahrzeug fahrzeug) { - try - { - using (var connection = new SQLiteConnection(_connectionString)) - { - connection.Open(); - - string updateQuery = @" - UPDATE Fahrzeuge - SET Marke = @Marke, - Modell = @Modell, - Baujahr = @Baujahr, - Leistung = @Leistung, - Kilometerstand = @Kilometerstand, - Kaufpreis = @Kaufpreis, - Farbe = @Farbe - WHERE Id = @Id"; - - using (var command = new SQLiteCommand(updateQuery, connection)) - { - command.Parameters.AddWithValue("@Id", fahrzeug.Id); - command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); - command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); - command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); - command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); - command.Parameters.AddWithValue("@Kilometerstand", fahrzeug.Kilometerstand); - command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); - command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); - - int rowsAffected = command.ExecuteNonQuery(); - return rowsAffected > 0; - } - } - } - catch (Exception ex) - { - throw new Exception($"Fehler beim Aktualisieren des Fahrzeugs: {ex.Message}"); - } + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = @" + UPDATE Fahrzeuge + SET Marke=@Marke, + Modell=@Modell, + Baujahr=@Baujahr, + Leistung=@Leistung, + Kilometerstand=@Kilometer, + Kaufpreis=@Kaufpreis, + Farbe=@Farbe + WHERE Id=@Id"; + using var command = new SQLiteCommand(query, connection); + command.Parameters.AddWithValue("@Id", fahrzeug.Id); + command.Parameters.AddWithValue("@Marke", fahrzeug.Marke); + command.Parameters.AddWithValue("@Modell", fahrzeug.Modell); + command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr); + command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung); + command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand); + command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis); + command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe); + return command.ExecuteNonQuery() > 0; } - /// - /// Löscht ein Fahrzeug aus der Datenbank - /// - /// Die ID des zu löschenden Fahrzeugs - /// True wenn erfolgreich, sonst False + // löscht ein Fahrzeug public bool LoescheFahrzeug(int id) { - try - { - using (var connection = new SQLiteConnection(_connectionString)) - { - connection.Open(); - - string deleteQuery = "DELETE FROM Fahrzeuge WHERE Id = @Id"; - - using (var command = new SQLiteCommand(deleteQuery, connection)) - { - command.Parameters.AddWithValue("@Id", id); - - int rowsAffected = command.ExecuteNonQuery(); - return rowsAffected > 0; - } - } - } - catch (Exception ex) - { - throw new Exception($"Fehler beim Löschen des Fahrzeugs: {ex.Message}"); - } + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = "DELETE FROM Fahrzeuge WHERE Id=@Id"; + using var command = new SQLiteCommand(query, connection); + command.Parameters.AddWithValue("@Id", id); + return command.ExecuteNonQuery() > 0; } - /// - /// Gibt die Anzahl der Fahrzeuge in der Datenbank zurück - /// - /// Anzahl der Fahrzeuge + // gibt die Anzahl der Fahrzeuge zurück public int GetAnzahlFahrzeuge() { - try - { - using (var connection = new SQLiteConnection(_connectionString)) - { - connection.Open(); - - string countQuery = "SELECT COUNT(*) FROM Fahrzeuge"; - - using (var command = new SQLiteCommand(countQuery, connection)) - { - var result = command.ExecuteScalar(); - return Convert.ToInt32(result); - } - } - } - catch (Exception ex) - { - throw new Exception($"Fehler beim Ermitteln der Fahrzeuganzahl: {ex.Message}"); - } + using var connection = new SQLiteConnection(_connectionString); + connection.Open(); + string query = "SELECT COUNT(*) FROM Fahrzeuge"; + using var command = new SQLiteCommand(query, connection); + return Convert.ToInt32(command.ExecuteScalar()); } } -} \ No newline at end of file +} diff --git a/WpfApp4/Fahrzeug.cs b/WpfApp4/Fahrzeug.cs index cadf7e0..e8db68a 100644 --- a/WpfApp4/Fahrzeug.cs +++ b/WpfApp4/Fahrzeug.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; namespace FahrzeugVerwaltung @@ -14,189 +14,57 @@ namespace FahrzeugVerwaltung private decimal _kaufpreis; private string _farbe; - public int Id - { - get => _id; - set - { - _id = value; - OnPropertyChanged(nameof(Id)); - } - } + public int Id { get => _id; set { _id = value; OnPropertyChanged(nameof(Id)); } } + public string Marke { get => _marke; set { _marke = value; OnPropertyChanged(nameof(Marke)); } } + public string Modell { get => _modell; set { _modell = value; OnPropertyChanged(nameof(Modell)); } } + public int Baujahr { get => _baujahr; set { _baujahr = value; OnPropertyChanged(nameof(Baujahr)); OnPropertyChanged(nameof(AktuellerWert)); OnPropertyChanged(nameof(AktuellerWertFormatiert)); } } + public int Leistung { get => _leistung; set { _leistung = value; OnPropertyChanged(nameof(Leistung)); } } + public int Kilometerstand { get => _kilometerstand; set { _kilometerstand = value; OnPropertyChanged(nameof(Kilometerstand)); OnPropertyChanged(nameof(KilometerstandFormatiert)); OnPropertyChanged(nameof(AktuellerWert)); OnPropertyChanged(nameof(AktuellerWertFormatiert)); } } + public decimal Kaufpreis { get => _kaufpreis; set { _kaufpreis = value; OnPropertyChanged(nameof(Kaufpreis)); OnPropertyChanged(nameof(KaufpreisFormatiert)); OnPropertyChanged(nameof(AktuellerWert)); OnPropertyChanged(nameof(AktuellerWertFormatiert)); } } + public string Farbe { get => _farbe; set { _farbe = value; OnPropertyChanged(nameof(Farbe)); } } - public string Marke - { - get => _marke; - set - { - _marke = value; - OnPropertyChanged(nameof(Marke)); - } - } - - public string Modell - { - get => _modell; - set - { - _modell = value; - OnPropertyChanged(nameof(Modell)); - } - } - - public int Baujahr - { - get => _baujahr; - set - { - _baujahr = value; - OnPropertyChanged(nameof(Baujahr)); - OnPropertyChanged(nameof(AktuellerWert)); - OnPropertyChanged(nameof(AktuellerWertFormatiert)); - } - } - - public int Leistung - { - get => _leistung; - set - { - _leistung = value; - OnPropertyChanged(nameof(Leistung)); - } - } - - public int Kilometerstand - { - get => _kilometerstand; - set - { - _kilometerstand = value; - OnPropertyChanged(nameof(Kilometerstand)); - OnPropertyChanged(nameof(KilometerstandFormatiert)); - OnPropertyChanged(nameof(AktuellerWert)); - OnPropertyChanged(nameof(AktuellerWertFormatiert)); - } - } - - public decimal Kaufpreis - { - get => _kaufpreis; - set - { - _kaufpreis = value; - OnPropertyChanged(nameof(Kaufpreis)); - OnPropertyChanged(nameof(KaufpreisFormatiert)); - OnPropertyChanged(nameof(AktuellerWert)); - OnPropertyChanged(nameof(AktuellerWertFormatiert)); - } - } - - public string Farbe - { - get => _farbe; - set - { - _farbe = value; - OnPropertyChanged(nameof(Farbe)); - } - } - - // Formatierte Eigenschaften für die Anzeige public string KilometerstandFormatiert => $"{Kilometerstand:N0} km"; public string KaufpreisFormatiert => $"{Kaufpreis:C}"; public string AktuellerWertFormatiert => $"{AktuellerWert:C}"; - // Berechnet den aktuellen Wert basierend auf Alter und Kilometerstand - public decimal AktuellerWert - { - get - { - return BerechneAktuellenWert(); - } - } + // berechnet den geschätzten aktuellen Wert + public decimal AktuellerWert => BerechneAktuellenWert(); - /// - /// Berechnet den aktuellen Wert des Fahrzeugs - /// Formel: Wertverlust basierend auf Alter und Kilometerstand - /// - /// Aktueller Wert des Fahrzeugs + // ermittelt den aktuellen Wert basierend auf Alter und Laufleistung public decimal BerechneAktuellenWert() { - if (Kaufpreis <= 0 || Baujahr <= 0) - return 0; + if (Kaufpreis <= 0 || Baujahr <= 0) return 0; - int aktuellesJahr = DateTime.Now.Year; - int alter = aktuellesJahr - Baujahr; - - // Wertverlust pro Jahr: 15% in den ersten 3 Jahren, dann 10% pro Jahr - decimal wertverlustProzent = 0; + int alter = DateTime.Now.Year - Baujahr; + decimal wertverlust = 0; for (int i = 0; i < alter; i++) - { - if (i < 3) - wertverlustProzent += 0.15m; // 15% pro Jahr in den ersten 3 Jahren - else - wertverlustProzent += 0.10m; // 10% pro Jahr danach - } + wertverlust += (i < 3) ? 0.15m : 0.10m; - // Zusätzlicher Wertverlust basierend auf Kilometerstand - // Pro 10.000 km: 2% Wertverlust - decimal kmWertverlust = (Kilometerstand / 10000m) * 0.02m; + wertverlust += (Kilometerstand / 10000m) * 0.02m; + if (wertverlust > 0.90m) wertverlust = 0.90m; - wertverlustProzent += kmWertverlust; - - // Maximal 90% Wertverlust - if (wertverlustProzent > 0.90m) - wertverlustProzent = 0.90m; - - decimal aktuellerWert = Kaufpreis * (1 - wertverlustProzent); - - // Mindestwert: 5% des Kaufpreises + decimal wert = Kaufpreis * (1 - wertverlust); decimal mindestwert = Kaufpreis * 0.05m; - if (aktuellerWert < mindestwert) - aktuellerWert = mindestwert; + if (wert < mindestwert) wert = mindestwert; - return Math.Round(aktuellerWert, 2); + return Math.Round(wert, 2); } - /// - /// Gibt eine detaillierte Beschreibung des Fahrzeugs zurück - /// - /// Formatierte Fahrzeugbeschreibung - public string GetDetailedDescription() - { - return $"{Marke} {Modell} ({Baujahr}) - {Leistung} PS - {KilometerstandFormatiert} - {Farbe}"; - } + // liefert eine kurze Beschreibung + public string GetDetailedDescription() => + $"{Marke} {Modell} ({Baujahr}) - {Leistung} PS - {KilometerstandFormatiert} - {Farbe}"; - /// - /// Berechnet das Alter des Fahrzeugs in Jahren - /// - /// Alter in Jahren - public int GetAlter() - { - return DateTime.Now.Year - Baujahr; - } + // gibt das Alter des Fahrzeugs zurück + public int GetAlter() => DateTime.Now.Year - Baujahr; - /// - /// Prüft, ob das Fahrzeug als Oldtimer gilt (älter als 30 Jahre) - /// - /// True wenn Oldtimer, sonst False - public bool IsOldtimer() - { - return GetAlter() >= 30; - } + // prüft, ob das Fahrzeug ein Oldtimer ist + public bool IsOldtimer() => GetAlter() >= 30; public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged(string propertyName) - { + private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - public override string ToString() - { - return $"{Marke} {Modell} ({Baujahr})"; - } + public override string ToString() => $"{Marke} {Modell} ({Baujahr})"; } -} \ No newline at end of file +} diff --git a/WpfApp4/FahrzeugVerwaltung.cs b/WpfApp4/FahrzeugVerwaltung.cs deleted file mode 100644 index 8d530dc..0000000 --- a/WpfApp4/FahrzeugVerwaltung.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Globalization; -using System.Text.RegularExpressions; -using System.Windows; -using System.Windows.Controls; - -namespace FahrzeugVerwaltung -{ - public static class Utilities - { - /// - /// Validiert eine Eingabe für numerische Werte - /// - public static bool IsValidNumber(string input, out double result, double min = double.MinValue, double max = double.MaxValue) - { - result = 0; - - if (string.IsNullOrWhiteSpace(input)) - return false; - - if (double.TryParse(input, NumberStyles.Any, CultureInfo.CurrentCulture, out result)) - { - return result >= min && result <= max; - } - - return false; - } - - /// - /// Validiert eine Eingabe für Ganzzahlen - /// - public static bool IsValidInteger(string input, out int result, int min = int.MinValue, int max = int.MaxValue) - { - result = 0; - - if (string.IsNullOrWhiteSpace(input)) - return false; - - if (int.TryParse(input, out result)) - { - return result >= min && result <= max; - } - - return false; - } - - /// - /// Validiert eine Eingabe für Dezimalzahlen - /// - public static bool IsValidDecimal(string input, out decimal result, decimal min = decimal.MinValue, decimal max = decimal.MaxValue) - { - result = 0; - - if (string.IsNullOrWhiteSpace(input)) - return false; - - if (decimal.TryParse(input, NumberStyles.Any, CultureInfo.CurrentCulture, out result)) - { - return result >= min && result <= max; - } - - return false; - } - - /// - /// Bereinigt Eingabetext von überflüssigen Zeichen - /// - public static string CleanInput(string input) - { - if (string.IsNullOrWhiteSpace(input)) - return string.Empty; - - // Mehrfache Leerzeichen durch einzelne ersetzen - return Regex.Replace(input.Trim(), @"\s+", " "); - } - - /// - /// Zeigt eine Fehlermeldung an - /// - public static void ShowError(string message, string title = "Fehler") - { - MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Error); - } - - /// - /// Zeigt eine Warnmeldung an - /// - public static void ShowWarning(string message, string title = "Warnung") - { - MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Warning); - } - - /// - /// Zeigt eine Informationsmeldung an - /// - public static void ShowInfo(string message, string title = "Information") - { - MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Information); - } - - /// - /// Zeigt eine Bestätigungsdialog an - /// - public static bool ShowConfirmation(string message, string title = "Bestätigung") - { - return MessageBox.Show(message, title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes; - } - - /// - /// Formatiert einen Preis für die Anzeige - /// - public static string FormatPrice(decimal price) - { - return price.ToString("C", CultureInfo.CurrentCulture); - } - - /// - /// Formatiert einen Kilometerstand für die Anzeige - /// - public static string FormatKilometers(int kilometers) - { - return $"{kilometers:N0} km"; - } - - /// - /// Berechnet die Differenz zwischen zwei Jahren - /// - public static int CalculateYearsDifference(int fromYear, int toYear) - { - return Math.Abs(toYear - fromYear); - } - - /// - /// Prüft, ob ein Baujahr realistisch ist - /// - public static bool IsValidBuildYear(int year) - { - int currentYear = DateTime.Now.Year; - return year >= 1900 && year <= currentYear + 1; - } - - /// - /// Generiert einen Dateinamen basierend auf Fahrzeugdaten - /// - public static string GenerateFileName(Fahrzeug fahrzeug, string extension = "html") - { - string marke = CleanInput(fahrzeug.Marke).Replace(" ", "_"); - string modell = CleanInput(fahrzeug.Modell).Replace(" ", "_"); - string datum = DateTime.Now.ToString("yyyyMMdd_HHmmss"); - - return $"Fahrzeug_{marke}_{modell}_{datum}.{extension}"; - } - - /// - /// Prüft, ob eine Textbox nur numerische Eingaben enthält - /// - public static void SetNumericOnly(TextBox textBox) - { - textBox.PreviewTextInput += (sender, e) => - { - e.Handled = !IsNumeric(e.Text); - }; - } - - /// - /// Prüft, ob ein String nur Zahlen enthält - /// - private static bool IsNumeric(string text) - { - return Regex.IsMatch(text, @"^[0-9]+$"); - } - - /// - /// Konvertiert einen String sicher zu einem Integer - /// - public static int SafeParseInt(string value, int defaultValue = 0) - { - if (int.TryParse(value, out int result)) - return result; - return defaultValue; - } - - /// - /// Konvertiert einen String sicher zu einem Decimal - /// - public static decimal SafeParseDecimal(string value, decimal defaultValue = 0) - { - if (decimal.TryParse(value, out decimal result)) - return result; - return defaultValue; - } - } -} \ No newline at end of file diff --git a/WpfApp4/MainWindow.xaml b/WpfApp4/MainWindow.xaml index 3f27810..8a76d0d 100644 --- a/WpfApp4/MainWindow.xaml +++ b/WpfApp4/MainWindow.xaml @@ -6,15 +6,16 @@ @@ -32,7 +33,7 @@ - + @@ -51,7 +52,6 @@ - @@ -59,10 +59,10 @@