Überarbeite Fahrzeugverwaltung
This commit is contained in:
parent
127a53f003
commit
b0bb865a87
150
README.md
150
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
|
## Start
|
||||||
- **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);
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
dotnet build
|
||||||
## 🤝 Beitragen
|
```
|
||||||
|
Die Anwendung kann anschließend mit Visual Studio oder `dotnet run` gestartet werden.
|
||||||
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!** ⭐
|
|
||||||
|
@ -6,15 +6,15 @@ namespace FahrzeugVerwaltung
|
|||||||
|
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
// startet die Anwendung und richtet Fehlerbehandlung ein
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
DispatcherUnhandledException += App_DispatcherUnhandledException;
|
DispatcherUnhandledException += App_DispatcherUnhandledException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// behandelt UI-Ausnahmen
|
||||||
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Ein unerwarteter Fehler ist aufgetreten:\n{e.Exception.Message}",
|
MessageBox.Show($"Ein unerwarteter Fehler ist aufgetreten:\n{e.Exception.Message}",
|
||||||
@ -22,6 +22,7 @@ namespace FahrzeugVerwaltung
|
|||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// behandelt kritische Ausnahmen
|
||||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Ein kritischer Fehler ist aufgetreten:\n{((Exception)e.ExceptionObject).Message}",
|
MessageBox.Show($"Ein kritischer Fehler ist aufgetreten:\n{((Exception)e.ExceptionObject).Message}",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.SQLite;
|
using System.Data.SQLite;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace FahrzeugVerwaltung
|
namespace FahrzeugVerwaltung
|
||||||
{
|
{
|
||||||
@ -18,288 +17,155 @@ namespace FahrzeugVerwaltung
|
|||||||
InitializeDatabase();
|
InitializeDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// erstellt die Datenbank und Tabelle
|
||||||
/// Initialisiert die Datenbank und erstellt die Tabelle falls sie nicht existiert
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeDatabase()
|
private void InitializeDatabase()
|
||||||
{
|
{
|
||||||
try
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
{
|
connection.Open();
|
||||||
using (var connection = new SQLiteConnection(_connectionString))
|
string query = @"
|
||||||
{
|
CREATE TABLE IF NOT EXISTS Fahrzeuge (
|
||||||
connection.Open();
|
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
Marke TEXT NOT NULL,
|
||||||
string createTableQuery = @"
|
Modell TEXT NOT NULL,
|
||||||
CREATE TABLE IF NOT EXISTS Fahrzeuge (
|
Baujahr INTEGER NOT NULL,
|
||||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
Leistung INTEGER NOT NULL,
|
||||||
Marke TEXT NOT NULL,
|
Kilometerstand INTEGER NOT NULL,
|
||||||
Modell TEXT NOT NULL,
|
Kaufpreis DECIMAL(10,2) NOT NULL,
|
||||||
Baujahr INTEGER NOT NULL,
|
Farbe TEXT NOT NULL,
|
||||||
Leistung INTEGER NOT NULL,
|
ErstelltAm DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
Kilometerstand INTEGER NOT NULL,
|
)";
|
||||||
Kaufpreis DECIMAL(10,2) NOT NULL,
|
using var command = new SQLiteCommand(query, connection);
|
||||||
Farbe TEXT NOT NULL,
|
command.ExecuteNonQuery();
|
||||||
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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// speichert ein Fahrzeug und gibt die neue Id zurück
|
||||||
/// Speichert ein neues Fahrzeug in der Datenbank
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fahrzeug">Das zu speichernde Fahrzeug</param>
|
|
||||||
/// <returns>Die ID des gespeicherten Fahrzeugs</returns>
|
|
||||||
public int SpeichereFahrzeug(Fahrzeug fahrzeug)
|
public int SpeichereFahrzeug(Fahrzeug fahrzeug)
|
||||||
{
|
{
|
||||||
try
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
{
|
connection.Open();
|
||||||
using (var connection = new SQLiteConnection(_connectionString))
|
string query = @"
|
||||||
{
|
INSERT INTO Fahrzeuge (Marke, Modell, Baujahr, Leistung, Kilometerstand, Kaufpreis, Farbe)
|
||||||
connection.Open();
|
VALUES (@Marke, @Modell, @Baujahr, @Leistung, @Kilometer, @Kaufpreis, @Farbe);
|
||||||
|
SELECT last_insert_rowid();";
|
||||||
string insertQuery = @"
|
using var command = new SQLiteCommand(query, connection);
|
||||||
INSERT INTO Fahrzeuge (Marke, Modell, Baujahr, Leistung, Kilometerstand, Kaufpreis, Farbe)
|
command.Parameters.AddWithValue("@Marke", fahrzeug.Marke);
|
||||||
VALUES (@Marke, @Modell, @Baujahr, @Leistung, @Kilometerstand, @Kaufpreis, @Farbe);
|
command.Parameters.AddWithValue("@Modell", fahrzeug.Modell);
|
||||||
SELECT last_insert_rowid();";
|
command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr);
|
||||||
|
command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung);
|
||||||
using (var command = new SQLiteCommand(insertQuery, connection))
|
command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand);
|
||||||
{
|
command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis);
|
||||||
command.Parameters.AddWithValue("@Marke", fahrzeug.Marke);
|
command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe);
|
||||||
command.Parameters.AddWithValue("@Modell", fahrzeug.Modell);
|
return Convert.ToInt32(command.ExecuteScalar());
|
||||||
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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// lädt alle Fahrzeuge
|
||||||
/// Lädt alle Fahrzeuge aus der Datenbank
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Liste aller Fahrzeuge</returns>
|
|
||||||
public List<Fahrzeug> LadeAlleFahrzeuge()
|
public List<Fahrzeug> LadeAlleFahrzeuge()
|
||||||
{
|
{
|
||||||
var fahrzeuge = new List<Fahrzeug>();
|
var fahrzeuge = new List<Fahrzeug>();
|
||||||
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
try
|
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();
|
Id = Convert.ToInt32(reader["Id"]),
|
||||||
|
Marke = reader["Marke"].ToString(),
|
||||||
string selectQuery = "SELECT * FROM Fahrzeuge ORDER BY Marke, Modell";
|
Modell = reader["Modell"].ToString(),
|
||||||
|
Baujahr = Convert.ToInt32(reader["Baujahr"]),
|
||||||
using (var command = new SQLiteCommand(selectQuery, connection))
|
Leistung = Convert.ToInt32(reader["Leistung"]),
|
||||||
using (var reader = command.ExecuteReader())
|
Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]),
|
||||||
{
|
Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]),
|
||||||
while (reader.Read())
|
Farbe = reader["Farbe"].ToString()
|
||||||
{
|
});
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"Fehler beim Laden der Fahrzeuge: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return fahrzeuge;
|
return fahrzeuge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// sucht Fahrzeuge nach Begriff
|
||||||
/// Sucht Fahrzeuge basierend auf einem Suchbegriff
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="suchbegriff">Der Suchbegriff</param>
|
|
||||||
/// <returns>Liste der gefundenen Fahrzeuge</returns>
|
|
||||||
public List<Fahrzeug> SucheFahrzeuge(string suchbegriff)
|
public List<Fahrzeug> SucheFahrzeuge(string suchbegriff)
|
||||||
{
|
{
|
||||||
var fahrzeuge = new List<Fahrzeug>();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(suchbegriff))
|
if (string.IsNullOrWhiteSpace(suchbegriff))
|
||||||
return LadeAlleFahrzeuge();
|
return LadeAlleFahrzeuge();
|
||||||
|
|
||||||
try
|
var fahrzeuge = new List<Fahrzeug>();
|
||||||
|
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();
|
Id = Convert.ToInt32(reader["Id"]),
|
||||||
|
Marke = reader["Marke"].ToString(),
|
||||||
string searchQuery = @"
|
Modell = reader["Modell"].ToString(),
|
||||||
SELECT * FROM Fahrzeuge
|
Baujahr = Convert.ToInt32(reader["Baujahr"]),
|
||||||
WHERE Marke LIKE @Suchbegriff
|
Leistung = Convert.ToInt32(reader["Leistung"]),
|
||||||
OR Modell LIKE @Suchbegriff
|
Kilometerstand = Convert.ToInt32(reader["Kilometerstand"]),
|
||||||
OR Farbe LIKE @Suchbegriff
|
Kaufpreis = Convert.ToDecimal(reader["Kaufpreis"]),
|
||||||
OR CAST(Baujahr AS TEXT) LIKE @Suchbegriff
|
Farbe = reader["Farbe"].ToString()
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"Fehler beim Suchen der Fahrzeuge: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return fahrzeuge;
|
return fahrzeuge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// aktualisiert ein Fahrzeug
|
||||||
/// Aktualisiert ein bestehendes Fahrzeug in der Datenbank
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fahrzeug">Das zu aktualisierende Fahrzeug</param>
|
|
||||||
/// <returns>True wenn erfolgreich, sonst False</returns>
|
|
||||||
public bool AktualisiereFahrzeug(Fahrzeug fahrzeug)
|
public bool AktualisiereFahrzeug(Fahrzeug fahrzeug)
|
||||||
{
|
{
|
||||||
try
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
{
|
connection.Open();
|
||||||
using (var connection = new SQLiteConnection(_connectionString))
|
string query = @"
|
||||||
{
|
UPDATE Fahrzeuge
|
||||||
connection.Open();
|
SET Marke=@Marke,
|
||||||
|
Modell=@Modell,
|
||||||
string updateQuery = @"
|
Baujahr=@Baujahr,
|
||||||
UPDATE Fahrzeuge
|
Leistung=@Leistung,
|
||||||
SET Marke = @Marke,
|
Kilometerstand=@Kilometer,
|
||||||
Modell = @Modell,
|
Kaufpreis=@Kaufpreis,
|
||||||
Baujahr = @Baujahr,
|
Farbe=@Farbe
|
||||||
Leistung = @Leistung,
|
WHERE Id=@Id";
|
||||||
Kilometerstand = @Kilometerstand,
|
using var command = new SQLiteCommand(query, connection);
|
||||||
Kaufpreis = @Kaufpreis,
|
command.Parameters.AddWithValue("@Id", fahrzeug.Id);
|
||||||
Farbe = @Farbe
|
command.Parameters.AddWithValue("@Marke", fahrzeug.Marke);
|
||||||
WHERE Id = @Id";
|
command.Parameters.AddWithValue("@Modell", fahrzeug.Modell);
|
||||||
|
command.Parameters.AddWithValue("@Baujahr", fahrzeug.Baujahr);
|
||||||
using (var command = new SQLiteCommand(updateQuery, connection))
|
command.Parameters.AddWithValue("@Leistung", fahrzeug.Leistung);
|
||||||
{
|
command.Parameters.AddWithValue("@Kilometer", fahrzeug.Kilometerstand);
|
||||||
command.Parameters.AddWithValue("@Id", fahrzeug.Id);
|
command.Parameters.AddWithValue("@Kaufpreis", fahrzeug.Kaufpreis);
|
||||||
command.Parameters.AddWithValue("@Marke", fahrzeug.Marke);
|
command.Parameters.AddWithValue("@Farbe", fahrzeug.Farbe);
|
||||||
command.Parameters.AddWithValue("@Modell", fahrzeug.Modell);
|
return command.ExecuteNonQuery() > 0;
|
||||||
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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// löscht ein Fahrzeug
|
||||||
/// Löscht ein Fahrzeug aus der Datenbank
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">Die ID des zu löschenden Fahrzeugs</param>
|
|
||||||
/// <returns>True wenn erfolgreich, sonst False</returns>
|
|
||||||
public bool LoescheFahrzeug(int id)
|
public bool LoescheFahrzeug(int id)
|
||||||
{
|
{
|
||||||
try
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
{
|
connection.Open();
|
||||||
using (var connection = new SQLiteConnection(_connectionString))
|
string query = "DELETE FROM Fahrzeuge WHERE Id=@Id";
|
||||||
{
|
using var command = new SQLiteCommand(query, connection);
|
||||||
connection.Open();
|
command.Parameters.AddWithValue("@Id", id);
|
||||||
|
return command.ExecuteNonQuery() > 0;
|
||||||
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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// gibt die Anzahl der Fahrzeuge zurück
|
||||||
/// Gibt die Anzahl der Fahrzeuge in der Datenbank zurück
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Anzahl der Fahrzeuge</returns>
|
|
||||||
public int GetAnzahlFahrzeuge()
|
public int GetAnzahlFahrzeuge()
|
||||||
{
|
{
|
||||||
try
|
using var connection = new SQLiteConnection(_connectionString);
|
||||||
{
|
connection.Open();
|
||||||
using (var connection = new SQLiteConnection(_connectionString))
|
string query = "SELECT COUNT(*) FROM Fahrzeuge";
|
||||||
{
|
using var command = new SQLiteCommand(query, connection);
|
||||||
connection.Open();
|
return Convert.ToInt32(command.ExecuteScalar());
|
||||||
|
|
||||||
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}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
namespace FahrzeugVerwaltung
|
namespace FahrzeugVerwaltung
|
||||||
@ -14,189 +14,57 @@ namespace FahrzeugVerwaltung
|
|||||||
private decimal _kaufpreis;
|
private decimal _kaufpreis;
|
||||||
private string _farbe;
|
private string _farbe;
|
||||||
|
|
||||||
public int Id
|
public int Id { get => _id; set { _id = value; OnPropertyChanged(nameof(Id)); } }
|
||||||
{
|
public string Marke { get => _marke; set { _marke = value; OnPropertyChanged(nameof(Marke)); } }
|
||||||
get => _id;
|
public string Modell { get => _modell; set { _modell = value; OnPropertyChanged(nameof(Modell)); } }
|
||||||
set
|
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)); } }
|
||||||
_id = value;
|
public int Kilometerstand { get => _kilometerstand; set { _kilometerstand = value; OnPropertyChanged(nameof(Kilometerstand)); OnPropertyChanged(nameof(KilometerstandFormatiert)); OnPropertyChanged(nameof(AktuellerWert)); OnPropertyChanged(nameof(AktuellerWertFormatiert)); } }
|
||||||
OnPropertyChanged(nameof(Id));
|
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 KilometerstandFormatiert => $"{Kilometerstand:N0} km";
|
||||||
public string KaufpreisFormatiert => $"{Kaufpreis:C}";
|
public string KaufpreisFormatiert => $"{Kaufpreis:C}";
|
||||||
public string AktuellerWertFormatiert => $"{AktuellerWert:C}";
|
public string AktuellerWertFormatiert => $"{AktuellerWert:C}";
|
||||||
|
|
||||||
// Berechnet den aktuellen Wert basierend auf Alter und Kilometerstand
|
// berechnet den geschätzten aktuellen Wert
|
||||||
public decimal AktuellerWert
|
public decimal AktuellerWert => BerechneAktuellenWert();
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return BerechneAktuellenWert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
// ermittelt den aktuellen Wert basierend auf Alter und Laufleistung
|
||||||
/// Berechnet den aktuellen Wert des Fahrzeugs
|
|
||||||
/// Formel: Wertverlust basierend auf Alter und Kilometerstand
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Aktueller Wert des Fahrzeugs</returns>
|
|
||||||
public decimal BerechneAktuellenWert()
|
public decimal BerechneAktuellenWert()
|
||||||
{
|
{
|
||||||
if (Kaufpreis <= 0 || Baujahr <= 0)
|
if (Kaufpreis <= 0 || Baujahr <= 0) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
int aktuellesJahr = DateTime.Now.Year;
|
int alter = DateTime.Now.Year - Baujahr;
|
||||||
int alter = aktuellesJahr - Baujahr;
|
decimal wertverlust = 0;
|
||||||
|
|
||||||
// Wertverlust pro Jahr: 15% in den ersten 3 Jahren, dann 10% pro Jahr
|
|
||||||
decimal wertverlustProzent = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < alter; i++)
|
for (int i = 0; i < alter; i++)
|
||||||
{
|
wertverlust += (i < 3) ? 0.15m : 0.10m;
|
||||||
if (i < 3)
|
|
||||||
wertverlustProzent += 0.15m; // 15% pro Jahr in den ersten 3 Jahren
|
|
||||||
else
|
|
||||||
wertverlustProzent += 0.10m; // 10% pro Jahr danach
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zusätzlicher Wertverlust basierend auf Kilometerstand
|
wertverlust += (Kilometerstand / 10000m) * 0.02m;
|
||||||
// Pro 10.000 km: 2% Wertverlust
|
if (wertverlust > 0.90m) wertverlust = 0.90m;
|
||||||
decimal kmWertverlust = (Kilometerstand / 10000m) * 0.02m;
|
|
||||||
|
|
||||||
wertverlustProzent += kmWertverlust;
|
decimal wert = Kaufpreis * (1 - wertverlust);
|
||||||
|
|
||||||
// Maximal 90% Wertverlust
|
|
||||||
if (wertverlustProzent > 0.90m)
|
|
||||||
wertverlustProzent = 0.90m;
|
|
||||||
|
|
||||||
decimal aktuellerWert = Kaufpreis * (1 - wertverlustProzent);
|
|
||||||
|
|
||||||
// Mindestwert: 5% des Kaufpreises
|
|
||||||
decimal mindestwert = Kaufpreis * 0.05m;
|
decimal mindestwert = Kaufpreis * 0.05m;
|
||||||
if (aktuellerWert < mindestwert)
|
if (wert < mindestwert) wert = mindestwert;
|
||||||
aktuellerWert = mindestwert;
|
|
||||||
|
|
||||||
return Math.Round(aktuellerWert, 2);
|
return Math.Round(wert, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// liefert eine kurze Beschreibung
|
||||||
/// Gibt eine detaillierte Beschreibung des Fahrzeugs zurück
|
public string GetDetailedDescription() =>
|
||||||
/// </summary>
|
$"{Marke} {Modell} ({Baujahr}) - {Leistung} PS - {KilometerstandFormatiert} - {Farbe}";
|
||||||
/// <returns>Formatierte Fahrzeugbeschreibung</returns>
|
|
||||||
public string GetDetailedDescription()
|
|
||||||
{
|
|
||||||
return $"{Marke} {Modell} ({Baujahr}) - {Leistung} PS - {KilometerstandFormatiert} - {Farbe}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
// gibt das Alter des Fahrzeugs zurück
|
||||||
/// Berechnet das Alter des Fahrzeugs in Jahren
|
public int GetAlter() => DateTime.Now.Year - Baujahr;
|
||||||
/// </summary>
|
|
||||||
/// <returns>Alter in Jahren</returns>
|
|
||||||
public int GetAlter()
|
|
||||||
{
|
|
||||||
return DateTime.Now.Year - Baujahr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
// prüft, ob das Fahrzeug ein Oldtimer ist
|
||||||
/// Prüft, ob das Fahrzeug als Oldtimer gilt (älter als 30 Jahre)
|
public bool IsOldtimer() => GetAlter() >= 30;
|
||||||
/// </summary>
|
|
||||||
/// <returns>True wenn Oldtimer, sonst False</returns>
|
|
||||||
public bool IsOldtimer()
|
|
||||||
{
|
|
||||||
return GetAlter() >= 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
private void OnPropertyChanged(string propertyName) =>
|
||||||
protected virtual void OnPropertyChanged(string propertyName)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString() => $"{Marke} {Modell} ({Baujahr})";
|
||||||
{
|
|
||||||
return $"{Marke} {Modell} ({Baujahr})";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Validiert eine Eingabe für numerische Werte
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validiert eine Eingabe für Ganzzahlen
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validiert eine Eingabe für Dezimalzahlen
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Bereinigt Eingabetext von überflüssigen Zeichen
|
|
||||||
/// </summary>
|
|
||||||
public static string CleanInput(string input)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(input))
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
// Mehrfache Leerzeichen durch einzelne ersetzen
|
|
||||||
return Regex.Replace(input.Trim(), @"\s+", " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Zeigt eine Fehlermeldung an
|
|
||||||
/// </summary>
|
|
||||||
public static void ShowError(string message, string title = "Fehler")
|
|
||||||
{
|
|
||||||
MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Zeigt eine Warnmeldung an
|
|
||||||
/// </summary>
|
|
||||||
public static void ShowWarning(string message, string title = "Warnung")
|
|
||||||
{
|
|
||||||
MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Zeigt eine Informationsmeldung an
|
|
||||||
/// </summary>
|
|
||||||
public static void ShowInfo(string message, string title = "Information")
|
|
||||||
{
|
|
||||||
MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Zeigt eine Bestätigungsdialog an
|
|
||||||
/// </summary>
|
|
||||||
public static bool ShowConfirmation(string message, string title = "Bestätigung")
|
|
||||||
{
|
|
||||||
return MessageBox.Show(message, title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Formatiert einen Preis für die Anzeige
|
|
||||||
/// </summary>
|
|
||||||
public static string FormatPrice(decimal price)
|
|
||||||
{
|
|
||||||
return price.ToString("C", CultureInfo.CurrentCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Formatiert einen Kilometerstand für die Anzeige
|
|
||||||
/// </summary>
|
|
||||||
public static string FormatKilometers(int kilometers)
|
|
||||||
{
|
|
||||||
return $"{kilometers:N0} km";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Berechnet die Differenz zwischen zwei Jahren
|
|
||||||
/// </summary>
|
|
||||||
public static int CalculateYearsDifference(int fromYear, int toYear)
|
|
||||||
{
|
|
||||||
return Math.Abs(toYear - fromYear);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prüft, ob ein Baujahr realistisch ist
|
|
||||||
/// </summary>
|
|
||||||
public static bool IsValidBuildYear(int year)
|
|
||||||
{
|
|
||||||
int currentYear = DateTime.Now.Year;
|
|
||||||
return year >= 1900 && year <= currentYear + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generiert einen Dateinamen basierend auf Fahrzeugdaten
|
|
||||||
/// </summary>
|
|
||||||
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}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prüft, ob eine Textbox nur numerische Eingaben enthält
|
|
||||||
/// </summary>
|
|
||||||
public static void SetNumericOnly(TextBox textBox)
|
|
||||||
{
|
|
||||||
textBox.PreviewTextInput += (sender, e) =>
|
|
||||||
{
|
|
||||||
e.Handled = !IsNumeric(e.Text);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prüft, ob ein String nur Zahlen enthält
|
|
||||||
/// </summary>
|
|
||||||
private static bool IsNumeric(string text)
|
|
||||||
{
|
|
||||||
return Regex.IsMatch(text, @"^[0-9]+$");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Konvertiert einen String sicher zu einem Integer
|
|
||||||
/// </summary>
|
|
||||||
public static int SafeParseInt(string value, int defaultValue = 0)
|
|
||||||
{
|
|
||||||
if (int.TryParse(value, out int result))
|
|
||||||
return result;
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Konvertiert einen String sicher zu einem Decimal
|
|
||||||
/// </summary>
|
|
||||||
public static decimal SafeParseDecimal(string value, decimal defaultValue = 0)
|
|
||||||
{
|
|
||||||
if (decimal.TryParse(value, out decimal result))
|
|
||||||
return result;
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,15 +6,16 @@
|
|||||||
|
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style TargetType="Button">
|
<Style TargetType="Button">
|
||||||
<Setter Property="Background" Value="#FF007ACC"/>
|
<Setter Property="Background" Value="#FF2196F3"/>
|
||||||
<Setter Property="Foreground" Value="White"/>
|
<Setter Property="Foreground" Value="White"/>
|
||||||
<Setter Property="FontWeight" Value="Bold"/>
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
<Setter Property="BorderBrush" Value="#FF005A9B"/>
|
<Setter Property="BorderBrush" Value="#FF1976D2"/>
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
<Setter Property="Padding" Value="10,5"/>
|
<Setter Property="Padding" Value="10,5"/>
|
||||||
|
<Setter Property="Margin" Value="5"/>
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
<Setter Property="Background" Value="#FF005A9B"/>
|
<Setter Property="Background" Value="#FF1976D2"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
@ -32,7 +33,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
|
|
||||||
<Grid Margin="10">
|
<Grid Margin="10" Background="#F5F5F5">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="400"/>
|
<ColumnDefinition Width="400"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
@ -51,7 +52,6 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="120"/>
|
||||||
@ -59,10 +59,10 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="Marke:" VerticalAlignment="Center"/>
|
<Label Grid.Row="0" Grid.Column="0" Content="Marke:" VerticalAlignment="Center"/>
|
||||||
<TextBox Grid.Row="0" Grid.Column="1" Name="txtMarke" Margin="5"/>
|
<ComboBox Grid.Row="0" Grid.Column="1" Name="cmbMarke" Margin="5" SelectionChanged="CmbMarke_SelectionChanged"/>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="Modell:" VerticalAlignment="Center"/>
|
<Label Grid.Row="1" Grid.Column="0" Content="Modell:" VerticalAlignment="Center"/>
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Name="txtModell" Margin="5"/>
|
<ComboBox Grid.Row="1" Grid.Column="1" Name="cmbModell" Margin="5"/>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="Baujahr:" VerticalAlignment="Center"/>
|
<Label Grid.Row="2" Grid.Column="0" Content="Baujahr:" VerticalAlignment="Center"/>
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" Name="txtBaujahr" Margin="5"/>
|
<TextBox Grid.Row="2" Grid.Column="1" Name="txtBaujahr" Margin="5"/>
|
||||||
@ -78,10 +78,6 @@
|
|||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="Farbe:" VerticalAlignment="Center"/>
|
<Label Grid.Row="6" Grid.Column="0" Content="Farbe:" VerticalAlignment="Center"/>
|
||||||
<TextBox Grid.Row="6" Grid.Column="1" Name="txtFarbe" Margin="5"/>
|
<TextBox Grid.Row="6" Grid.Column="1" Name="txtFarbe" Margin="5"/>
|
||||||
|
|
||||||
<Button Grid.Row="7" Grid.Column="1" Name="btnSpeichern" Content="Speichern"
|
|
||||||
Margin="5" HorizontalAlignment="Right" Width="120" Height="35"
|
|
||||||
Click="BtnSpeichern_Click"/>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<GroupBox Grid.Column="1" Grid.Row="0" Header="Fahrzeuge suchen" Margin="5">
|
<GroupBox Grid.Column="1" Grid.Row="0" Header="Fahrzeuge suchen" Margin="5">
|
||||||
@ -121,10 +117,11 @@
|
|||||||
Text="Kein Fahrzeug ausgewählt" HorizontalAlignment="Center"/>
|
Text="Kein Fahrzeug ausgewählt" HorizontalAlignment="Center"/>
|
||||||
|
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10">
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="10">
|
||||||
<Button Name="btnPdf" Content="Als PDF speichern" Width="150" Height="35"
|
<Button Name="btnHinzufuegen" Content="Hinzufügen" Width="120" Height="35" Click="BtnHinzufuegen_Click"/>
|
||||||
Margin="5" IsEnabled="False" Click="BtnPdf_Click"/>
|
<Button Name="btnBearbeiten" Content="Bearbeiten" Width="120" Height="35" Click="BtnBearbeiten_Click"/>
|
||||||
<Button Name="btnAktualisieren" Content="Aktualisieren" Width="120" Height="35"
|
<Button Name="btnLoeschen" Content="Löschen" Width="120" Height="35" Click="BtnLoeschen_Click"/>
|
||||||
Margin="5" Click="BtnAktualisieren_Click"/>
|
<Button Name="btnPdf" Content="Als PDF speichern" Width="150" Height="35" IsEnabled="False" Click="BtnPdf_Click"/>
|
||||||
|
<Button Name="btnAktualisieren" Content="Aktualisieren" Width="120" Height="35" Click="BtnAktualisieren_Click"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FahrzeugVerwaltung
|
namespace FahrzeugVerwaltung
|
||||||
{
|
{
|
||||||
@ -15,211 +13,198 @@ namespace FahrzeugVerwaltung
|
|||||||
private PdfService _pdfService;
|
private PdfService _pdfService;
|
||||||
private List<Fahrzeug> _aktuelleFahrzeuge;
|
private List<Fahrzeug> _aktuelleFahrzeuge;
|
||||||
private Fahrzeug _ausgewaehltesFahrzeug;
|
private Fahrzeug _ausgewaehltesFahrzeug;
|
||||||
|
private Dictionary<string, List<string>> _markenModelle;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
InitializeServices();
|
InitializeServices();
|
||||||
|
InitializeMarken();
|
||||||
LadeFahrzeuge();
|
LadeFahrzeuge();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// legt die Dienste an
|
||||||
/// Initialisiert die Services
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeServices()
|
private void InitializeServices()
|
||||||
{
|
{
|
||||||
try
|
_databaseService = new DatabaseService();
|
||||||
{
|
_pdfService = new PdfService();
|
||||||
_databaseService = new DatabaseService();
|
_aktuelleFahrzeuge = new List<Fahrzeug>();
|
||||||
_pdfService = new PdfService();
|
|
||||||
_aktuelleFahrzeuge = new List<Fahrzeug>();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Fehler beim Initialisieren der Anwendung: {ex.Message}",
|
|
||||||
"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// füllt die Listen für Marken und Modelle
|
||||||
/// Lädt alle Fahrzeuge aus der Datenbank
|
private void InitializeMarken()
|
||||||
/// </summary>
|
{
|
||||||
|
_markenModelle = new Dictionary<string, List<string>>
|
||||||
|
{
|
||||||
|
{"Audi", new List<string>{"A3","A4","A6","Q3","Q5","Q7"}},
|
||||||
|
{"BMW", new List<string>{"1er","3er","5er","X1","X3","X5"}},
|
||||||
|
{"Mercedes", new List<string>{"A-Klasse","C-Klasse","E-Klasse","GLA","GLC","GLE"}},
|
||||||
|
{"Volkswagen", new List<string>{"Golf","Passat","Polo","Tiguan","T-Roc","Arteon"}},
|
||||||
|
{"Opel", new List<string>{"Corsa","Astra","Insignia","Mokka","Crossland","Grandland"}},
|
||||||
|
{"Ford", new List<string>{"Fiesta","Focus","Mondeo","Kuga","Puma","S-MAX"}},
|
||||||
|
{"Toyota", new List<string>{"Yaris","Corolla","Camry","RAV4","C-HR","Auris"}},
|
||||||
|
{"Honda", new List<string>{"Civic","Accord","Jazz","CR-V","HR-V","NSX"}},
|
||||||
|
{"Hyundai", new List<string>{"i20","i30","i40","Tucson","Santa Fe","Kona"}},
|
||||||
|
{"Nissan", new List<string>{"Micra","Juke","Qashqai","X-Trail","Leaf","Navara"}}
|
||||||
|
};
|
||||||
|
|
||||||
|
cmbMarke.ItemsSource = _markenModelle.Keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lädt alle Fahrzeuge
|
||||||
private void LadeFahrzeuge()
|
private void LadeFahrzeuge()
|
||||||
{
|
{
|
||||||
try
|
_aktuelleFahrzeuge = _databaseService.LadeAlleFahrzeuge();
|
||||||
{
|
dgFahrzeuge.ItemsSource = _aktuelleFahrzeuge;
|
||||||
_aktuelleFahrzeuge = _databaseService.LadeAlleFahrzeuge();
|
UpdateStatusText();
|
||||||
dgFahrzeuge.ItemsSource = _aktuelleFahrzeuge;
|
|
||||||
UpdateStatusText();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Fehler beim Laden der Fahrzeuge: {ex.Message}",
|
|
||||||
"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// zeigt Anzahl der Fahrzeuge an
|
||||||
/// Aktualisiert den Status-Text
|
|
||||||
/// </summary>
|
|
||||||
private void UpdateStatusText()
|
private void UpdateStatusText()
|
||||||
{
|
{
|
||||||
if (_aktuelleFahrzeuge.Count == 0)
|
if (_aktuelleFahrzeuge.Count == 0)
|
||||||
{
|
|
||||||
txtDetails.Text = "Keine Fahrzeuge vorhanden";
|
txtDetails.Text = "Keine Fahrzeuge vorhanden";
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
txtDetails.Text = $"{_aktuelleFahrzeuge.Count} Fahrzeug(e) gefunden";
|
txtDetails.Text = $"{_aktuelleFahrzeuge.Count} Fahrzeug(e) gefunden";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// fügt ein neues Fahrzeug hinzu
|
||||||
/// Speichert ein neues Fahrzeug
|
private void BtnHinzufuegen_Click(object sender, RoutedEventArgs e)
|
||||||
/// </summary>
|
|
||||||
private void BtnSpeichern_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
try
|
if (!PruefeEingaben())
|
||||||
{
|
return;
|
||||||
if (!ValidateInput())
|
|
||||||
return;
|
|
||||||
|
|
||||||
var fahrzeug = new Fahrzeug
|
var fahrzeug = new Fahrzeug
|
||||||
|
{
|
||||||
|
Marke = cmbMarke.SelectedItem.ToString(),
|
||||||
|
Modell = cmbModell.SelectedItem.ToString(),
|
||||||
|
Baujahr = int.Parse(txtBaujahr.Text.Trim()),
|
||||||
|
Leistung = int.Parse(txtLeistung.Text.Trim()),
|
||||||
|
Kilometerstand = int.Parse(txtKilometer.Text.Trim()),
|
||||||
|
Kaufpreis = decimal.Parse(txtKaufpreis.Text.Trim()),
|
||||||
|
Farbe = txtFarbe.Text.Trim()
|
||||||
|
};
|
||||||
|
|
||||||
|
fahrzeug.Id = _databaseService.SpeichereFahrzeug(fahrzeug);
|
||||||
|
MessageBox.Show("Fahrzeug gespeichert.", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
ClearInputFields();
|
||||||
|
LadeFahrzeuge();
|
||||||
|
}
|
||||||
|
|
||||||
|
// bearbeitet das ausgewählte Fahrzeug
|
||||||
|
private void BtnBearbeiten_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_ausgewaehltesFahrzeug == null || !PruefeEingaben())
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ausgewaehltesFahrzeug.Marke = cmbMarke.SelectedItem.ToString();
|
||||||
|
_ausgewaehltesFahrzeug.Modell = cmbModell.SelectedItem.ToString();
|
||||||
|
_ausgewaehltesFahrzeug.Baujahr = int.Parse(txtBaujahr.Text.Trim());
|
||||||
|
_ausgewaehltesFahrzeug.Leistung = int.Parse(txtLeistung.Text.Trim());
|
||||||
|
_ausgewaehltesFahrzeug.Kilometerstand = int.Parse(txtKilometer.Text.Trim());
|
||||||
|
_ausgewaehltesFahrzeug.Kaufpreis = decimal.Parse(txtKaufpreis.Text.Trim());
|
||||||
|
_ausgewaehltesFahrzeug.Farbe = txtFarbe.Text.Trim();
|
||||||
|
|
||||||
|
if (_databaseService.AktualisiereFahrzeug(_ausgewaehltesFahrzeug))
|
||||||
|
MessageBox.Show("Fahrzeug aktualisiert.", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
|
||||||
|
LadeFahrzeuge();
|
||||||
|
}
|
||||||
|
|
||||||
|
// löscht das ausgewählte Fahrzeug
|
||||||
|
private void BtnLoeschen_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (_ausgewaehltesFahrzeug == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (MessageBox.Show("Fahrzeug wirklich löschen?", "Bestätigung", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||||
|
{
|
||||||
|
if (_databaseService.LoescheFahrzeug(_ausgewaehltesFahrzeug.Id))
|
||||||
{
|
{
|
||||||
Marke = txtMarke.Text.Trim(),
|
MessageBox.Show("Fahrzeug gelöscht.", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
Modell = txtModell.Text.Trim(),
|
ClearInputFields();
|
||||||
Baujahr = int.Parse(txtBaujahr.Text.Trim()),
|
LadeFahrzeuge();
|
||||||
Leistung = int.Parse(txtLeistung.Text.Trim()),
|
}
|
||||||
Kilometerstand = int.Parse(txtKilometer.Text.Trim()),
|
|
||||||
Kaufpreis = decimal.Parse(txtKaufpreis.Text.Trim()),
|
|
||||||
Farbe = txtFarbe.Text.Trim()
|
|
||||||
};
|
|
||||||
|
|
||||||
int neueId = _databaseService.SpeichereFahrzeug(fahrzeug);
|
|
||||||
fahrzeug.Id = neueId;
|
|
||||||
|
|
||||||
MessageBox.Show($"Fahrzeug '{fahrzeug.Marke} {fahrzeug.Modell}' wurde erfolgreich gespeichert!",
|
|
||||||
"Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
|
|
||||||
// Eingabefelder leeren
|
|
||||||
ClearInputFields();
|
|
||||||
|
|
||||||
// Fahrzeugliste aktualisieren
|
|
||||||
LadeFahrzeuge();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Fehler beim Speichern des Fahrzeugs: {ex.Message}",
|
|
||||||
"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// prüft die Eingaben
|
||||||
/// Validiert die Eingaben
|
private bool PruefeEingaben()
|
||||||
/// </summary>
|
|
||||||
private bool ValidateInput()
|
|
||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var fehler = new List<string>();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(txtMarke.Text))
|
|
||||||
errors.Add("Marke ist erforderlich");
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(txtModell.Text))
|
|
||||||
errors.Add("Modell ist erforderlich");
|
|
||||||
|
|
||||||
|
if (cmbMarke.SelectedItem == null)
|
||||||
|
fehler.Add("Marke wählen");
|
||||||
|
if (cmbModell.SelectedItem == null)
|
||||||
|
fehler.Add("Modell wählen");
|
||||||
if (!int.TryParse(txtBaujahr.Text, out int baujahr) || baujahr < 1900 || baujahr > DateTime.Now.Year)
|
if (!int.TryParse(txtBaujahr.Text, out int baujahr) || baujahr < 1900 || baujahr > DateTime.Now.Year)
|
||||||
errors.Add($"Baujahr muss zwischen 1900 und {DateTime.Now.Year} liegen");
|
fehler.Add($"Baujahr zwischen 1900 und {DateTime.Now.Year}");
|
||||||
|
|
||||||
if (!int.TryParse(txtLeistung.Text, out int leistung) || leistung <= 0)
|
if (!int.TryParse(txtLeistung.Text, out int leistung) || leistung <= 0)
|
||||||
errors.Add("Leistung muss eine positive Zahl sein");
|
fehler.Add("Leistung muss positiv sein");
|
||||||
|
|
||||||
if (!int.TryParse(txtKilometer.Text, out int kilometer) || kilometer < 0)
|
if (!int.TryParse(txtKilometer.Text, out int kilometer) || kilometer < 0)
|
||||||
errors.Add("Kilometerstand muss 0 oder größer sein");
|
fehler.Add("Kilometerstand muss 0 oder größer sein");
|
||||||
|
|
||||||
if (!decimal.TryParse(txtKaufpreis.Text, out decimal kaufpreis) || kaufpreis <= 0)
|
if (!decimal.TryParse(txtKaufpreis.Text, out decimal kaufpreis) || kaufpreis <= 0)
|
||||||
errors.Add("Kaufpreis muss eine positive Zahl sein");
|
fehler.Add("Kaufpreis muss positiv sein");
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(txtFarbe.Text))
|
if (string.IsNullOrWhiteSpace(txtFarbe.Text))
|
||||||
errors.Add("Farbe ist erforderlich");
|
fehler.Add("Farbe angeben");
|
||||||
|
|
||||||
if (errors.Any())
|
if (fehler.Any())
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Bitte korrigieren Sie folgende Fehler:\n\n{string.Join("\n", errors)}",
|
MessageBox.Show(string.Join("\n", fehler), "Eingabefehler", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
"Eingabefehler", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// leert alle Eingabefelder
|
||||||
/// Leert alle Eingabefelder
|
|
||||||
/// </summary>
|
|
||||||
private void ClearInputFields()
|
private void ClearInputFields()
|
||||||
{
|
{
|
||||||
txtMarke.Clear();
|
cmbMarke.SelectedIndex = -1;
|
||||||
txtModell.Clear();
|
cmbModell.ItemsSource = null;
|
||||||
txtBaujahr.Clear();
|
txtBaujahr.Clear();
|
||||||
txtLeistung.Clear();
|
txtLeistung.Clear();
|
||||||
txtKilometer.Clear();
|
txtKilometer.Clear();
|
||||||
txtKaufpreis.Clear();
|
txtKaufpreis.Clear();
|
||||||
txtFarbe.Clear();
|
txtFarbe.Clear();
|
||||||
txtMarke.Focus();
|
cmbMarke.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// sucht Fahrzeuge nach Begriff
|
||||||
/// Sucht nach Fahrzeugen
|
|
||||||
/// </summary>
|
|
||||||
private void BtnSuchen_Click(object sender, RoutedEventArgs e)
|
private void BtnSuchen_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
var suchbegriff = txtSuche.Text.Trim();
|
||||||
{
|
if (string.IsNullOrWhiteSpace(suchbegriff))
|
||||||
string suchbegriff = txtSuche.Text.Trim();
|
return;
|
||||||
if (string.IsNullOrWhiteSpace(suchbegriff))
|
|
||||||
{
|
|
||||||
MessageBox.Show("Bitte geben Sie einen Suchbegriff ein.",
|
|
||||||
"Hinweis", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_aktuelleFahrzeuge = _databaseService.SucheFahrzeuge(suchbegriff);
|
_aktuelleFahrzeuge = _databaseService.SucheFahrzeuge(suchbegriff);
|
||||||
dgFahrzeuge.ItemsSource = _aktuelleFahrzeuge;
|
dgFahrzeuge.ItemsSource = _aktuelleFahrzeuge;
|
||||||
UpdateStatusText();
|
UpdateStatusText();
|
||||||
|
|
||||||
if (_aktuelleFahrzeuge.Count == 0)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Keine Fahrzeuge mit dem Suchbegriff '{suchbegriff}' gefunden.",
|
|
||||||
"Suchergebnis", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Fehler bei der Suche: {ex.Message}",
|
|
||||||
"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// zeigt alle Fahrzeuge
|
||||||
/// Zeigt alle Fahrzeuge an
|
|
||||||
/// </summary>
|
|
||||||
private void BtnAlle_Click(object sender, RoutedEventArgs e)
|
private void BtnAlle_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
txtSuche.Clear();
|
txtSuche.Clear();
|
||||||
LadeFahrzeuge();
|
LadeFahrzeuge();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// reagiert auf Auswahl in der Liste
|
||||||
/// Wird aufgerufen wenn ein Fahrzeug ausgewählt wird
|
|
||||||
/// </summary>
|
|
||||||
private void DgFahrzeuge_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void DgFahrzeuge_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
_ausgewaehltesFahrzeug = dgFahrzeuge.SelectedItem as Fahrzeug;
|
_ausgewaehltesFahrzeug = dgFahrzeuge.SelectedItem as Fahrzeug;
|
||||||
|
|
||||||
if (_ausgewaehltesFahrzeug != null)
|
if (_ausgewaehltesFahrzeug != null)
|
||||||
{
|
{
|
||||||
txtDetails.Text = $"Ausgewählt: {_ausgewaehltesFahrzeug.GetDetailedDescription()} | " +
|
txtDetails.Text = $"Ausgewählt: {_ausgewaehltesFahrzeug.GetDetailedDescription()}";
|
||||||
$"Aktueller Wert: {_ausgewaehltesFahrzeug.AktuellerWertFormatiert} | " +
|
cmbMarke.SelectedItem = _ausgewaehltesFahrzeug.Marke;
|
||||||
$"Wertverlust: {((_ausgewaehltesFahrzeug.Kaufpreis - _ausgewaehltesFahrzeug.AktuellerWert) / _ausgewaehltesFahrzeug.Kaufpreis * 100):F1}%";
|
CmbMarke_SelectionChanged(null, null);
|
||||||
|
cmbModell.SelectedItem = _ausgewaehltesFahrzeug.Modell;
|
||||||
|
txtBaujahr.Text = _ausgewaehltesFahrzeug.Baujahr.ToString();
|
||||||
|
txtLeistung.Text = _ausgewaehltesFahrzeug.Leistung.ToString();
|
||||||
|
txtKilometer.Text = _ausgewaehltesFahrzeug.Kilometerstand.ToString();
|
||||||
|
txtKaufpreis.Text = _ausgewaehltesFahrzeug.Kaufpreis.ToString();
|
||||||
|
txtFarbe.Text = _ausgewaehltesFahrzeug.Farbe;
|
||||||
btnPdf.IsEnabled = true;
|
btnPdf.IsEnabled = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -229,98 +214,49 @@ namespace FahrzeugVerwaltung
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// erstellt ein PDF zum Fahrzeug
|
||||||
/// Erstellt ein PDF für das ausgewählte Fahrzeug
|
|
||||||
/// </summary>
|
|
||||||
private void BtnPdf_Click(object sender, RoutedEventArgs e)
|
private void BtnPdf_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_ausgewaehltesFahrzeug == null)
|
if (_ausgewaehltesFahrzeug == null)
|
||||||
{
|
|
||||||
MessageBox.Show("Bitte wählen Sie erst ein Fahrzeug aus.",
|
|
||||||
"Hinweis", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
try
|
var dialog = new SaveFileDialog
|
||||||
{
|
{
|
||||||
var saveFileDialog = new SaveFileDialog
|
Filter = "PDF-Dateien (*.pdf)|*.pdf",
|
||||||
{
|
FileName = $"Fahrzeug_{_ausgewaehltesFahrzeug.Marke}_{_ausgewaehltesFahrzeug.Modell}_{DateTime.Now:yyyyMMdd_HHmmss}.pdf"
|
||||||
Filter = "PDF-Dateien (*.pdf)|*.pdf",
|
};
|
||||||
FileName = $"Fahrzeug_{_ausgewaehltesFahrzeug.Marke}_{_ausgewaehltesFahrzeug.Modell}_{DateTime.Now:yyyyMMdd_HHmmss}.pdf",
|
|
||||||
Title = "PDF speichern"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (saveFileDialog.ShowDialog() == true)
|
if (dialog.ShowDialog() == true)
|
||||||
{
|
|
||||||
bool erfolg = _pdfService.ErstelleFahrzeugPdf(_ausgewaehltesFahrzeug, saveFileDialog.FileName);
|
|
||||||
|
|
||||||
if (erfolg)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"PDF wurde erfolgreich erstellt:\n{saveFileDialog.FileName}",
|
|
||||||
"Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
|
|
||||||
// Fragen ob PDF geöffnet werden soll
|
|
||||||
var result = MessageBox.Show("Möchten Sie das PDF jetzt öffnen?",
|
|
||||||
"PDF öffnen", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Process.Start(saveFileDialog.FileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Fehler beim Erstellen des PDFs: {ex.Message}",
|
if (_pdfService.ErstelleFahrzeugPdf(_ausgewaehltesFahrzeug, dialog.FileName))
|
||||||
"Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show("PDF erstellt.", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// lädt die Liste neu
|
||||||
/// Aktualisiert die Fahrzeugliste
|
|
||||||
/// </summary>
|
|
||||||
private void BtnAktualisieren_Click(object sender, RoutedEventArgs e)
|
private void BtnAktualisieren_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
LadeFahrzeuge();
|
LadeFahrzeuge();
|
||||||
MessageBox.Show("Fahrzeugliste wurde aktualisiert.",
|
|
||||||
"Information", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// Tastenkürzel
|
||||||
/// Behandelt das Schließen des Fensters
|
|
||||||
/// </summary>
|
|
||||||
protected override void OnClosed(EventArgs e)
|
|
||||||
{
|
|
||||||
base.OnClosed(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Behandelt Tastatureingaben für Shortcuts
|
|
||||||
/// </summary>
|
|
||||||
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
|
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
|
||||||
{
|
{
|
||||||
// Strg+S zum Speichern
|
if (e.Key == System.Windows.Input.Key.S && System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Control)
|
||||||
if (e.Key == System.Windows.Input.Key.S &&
|
|
||||||
System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Control)
|
|
||||||
{
|
{
|
||||||
BtnSpeichern_Click(null, null);
|
BtnHinzufuegen_Click(null, null);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
// Strg+F zum Suchen
|
else if (e.Key == System.Windows.Input.Key.F && System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Control)
|
||||||
else if (e.Key == System.Windows.Input.Key.F &&
|
|
||||||
System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Control)
|
|
||||||
{
|
{
|
||||||
txtSuche.Focus();
|
txtSuche.Focus();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
// F5 zum Aktualisieren
|
|
||||||
else if (e.Key == System.Windows.Input.Key.F5)
|
else if (e.Key == System.Windows.Input.Key.F5)
|
||||||
{
|
{
|
||||||
BtnAktualisieren_Click(null, null);
|
BtnAktualisieren_Click(null, null);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
// Escape zum Leeren der Eingabefelder
|
|
||||||
else if (e.Key == System.Windows.Input.Key.Escape)
|
else if (e.Key == System.Windows.Input.Key.Escape)
|
||||||
{
|
{
|
||||||
ClearInputFields();
|
ClearInputFields();
|
||||||
@ -329,5 +265,18 @@ namespace FahrzeugVerwaltung
|
|||||||
|
|
||||||
base.OnKeyDown(e);
|
base.OnKeyDown(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// passt Modellliste an
|
||||||
|
private void CmbMarke_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (cmbMarke.SelectedItem == null)
|
||||||
|
{
|
||||||
|
cmbModell.ItemsSource = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var marke = cmbMarke.SelectedItem.ToString();
|
||||||
|
cmbModell.ItemsSource = _markenModelle[marke];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using iTextSharp.text;
|
using iTextSharp.text;
|
||||||
using iTextSharp.text.pdf;
|
using iTextSharp.text.pdf;
|
||||||
|
|
||||||
@ -9,273 +7,61 @@ namespace FahrzeugVerwaltung
|
|||||||
{
|
{
|
||||||
public class PdfService
|
public class PdfService
|
||||||
{
|
{
|
||||||
/// <summary>
|
// erstellt ein einfaches PDF für ein Fahrzeug
|
||||||
/// Erstellt ein PDF-Infoblatt für ein Fahrzeug
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fahrzeug">Das Fahrzeug für das PDF</param>
|
|
||||||
/// <param name="dateiPfad">Der Pfad wo das PDF gespeichert werden soll</param>
|
|
||||||
/// <returns>True wenn erfolgreich, sonst False</returns>
|
|
||||||
public bool ErstelleFahrzeugPdf(Fahrzeug fahrzeug, string dateiPfad)
|
public bool ErstelleFahrzeugPdf(Fahrzeug fahrzeug, string dateiPfad)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// PDF-Dokument erstellen
|
using var document = new Document(PageSize.A4);
|
||||||
using (var document = new iTextSharp.text.Document(PageSize.A4, 50, 50, 50, 50))
|
PdfWriter.GetInstance(document, new FileStream(dateiPfad, FileMode.Create));
|
||||||
{
|
document.Open();
|
||||||
using (var writer = PdfWriter.GetInstance(document, new FileStream(dateiPfad, FileMode.Create)))
|
document.Add(new Paragraph($"Fahrzeug: {fahrzeug.Marke} {fahrzeug.Modell}"));
|
||||||
{
|
document.Add(new Paragraph($"Baujahr: {fahrzeug.Baujahr}"));
|
||||||
document.Open();
|
document.Add(new Paragraph($"Leistung: {fahrzeug.Leistung} PS"));
|
||||||
|
document.Add(new Paragraph($"Kilometerstand: {fahrzeug.KilometerstandFormatiert}"));
|
||||||
// Titel
|
document.Add(new Paragraph($"Farbe: {fahrzeug.Farbe}"));
|
||||||
var titelFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 18, BaseColor.DARK_GRAY);
|
document.Add(new Paragraph($"Kaufpreis: {fahrzeug.KaufpreisFormatiert}"));
|
||||||
var titel = new iTextSharp.text.Paragraph("FAHRZEUG-INFOBLATT", titelFont)
|
document.Add(new Paragraph($"Aktueller Wert: {fahrzeug.AktuellerWertFormatiert}"));
|
||||||
{
|
document.Close();
|
||||||
Alignment = Element.ALIGN_CENTER,
|
|
||||||
SpacingAfter = 20
|
|
||||||
};
|
|
||||||
document.Add(titel);
|
|
||||||
|
|
||||||
// Datum
|
|
||||||
var datumFont = FontFactory.GetFont(FontFactory.HELVETICA, 10, BaseColor.GRAY);
|
|
||||||
var datum = new iTextSharp.text.Paragraph($"Erstellt am: {DateTime.Now:dd.MM.yyyy HH:mm}", datumFont)
|
|
||||||
{
|
|
||||||
Alignment = Element.ALIGN_RIGHT,
|
|
||||||
SpacingAfter = 30
|
|
||||||
};
|
|
||||||
document.Add(datum);
|
|
||||||
|
|
||||||
// Fahrzeugdaten als Tabelle
|
|
||||||
var table = new PdfPTable(2)
|
|
||||||
{
|
|
||||||
WidthPercentage = 100,
|
|
||||||
SpacingAfter = 20
|
|
||||||
};
|
|
||||||
table.SetWidths(new float[] { 1f, 2f });
|
|
||||||
|
|
||||||
// Tabellen-Style
|
|
||||||
var headerFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 12, BaseColor.WHITE);
|
|
||||||
var contentFont = FontFactory.GetFont(FontFactory.HELVETICA, 11, BaseColor.BLACK);
|
|
||||||
var labelFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11, BaseColor.DARK_GRAY);
|
|
||||||
|
|
||||||
// Header
|
|
||||||
var headerCell1 = new PdfPCell(new Phrase("Eigenschaft", headerFont))
|
|
||||||
{
|
|
||||||
BackgroundColor = BaseColor.DARK_GRAY,
|
|
||||||
Padding = 10,
|
|
||||||
HorizontalAlignment = Element.ALIGN_CENTER
|
|
||||||
};
|
|
||||||
var headerCell2 = new PdfPCell(new Phrase("Wert", headerFont))
|
|
||||||
{
|
|
||||||
BackgroundColor = BaseColor.DARK_GRAY,
|
|
||||||
Padding = 10,
|
|
||||||
HorizontalAlignment = Element.ALIGN_CENTER
|
|
||||||
};
|
|
||||||
table.AddCell(headerCell1);
|
|
||||||
table.AddCell(headerCell2);
|
|
||||||
|
|
||||||
// Fahrzeugdaten hinzufügen
|
|
||||||
AddTableRow(table, "Marke", fahrzeug.Marke, labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Modell", fahrzeug.Modell, labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Baujahr", fahrzeug.Baujahr.ToString(), labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Leistung", $"{fahrzeug.Leistung} PS", labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Kilometerstand", fahrzeug.KilometerstandFormatiert, labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Farbe", fahrzeug.Farbe, labelFont, contentFont);
|
|
||||||
AddTableRow(table, "Kaufpreis", fahrzeug.KaufpreisFormatiert, labelFont, contentFont);
|
|
||||||
|
|
||||||
// Berechnete Werte
|
|
||||||
var calculatedFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11, BaseColor.BLUE);
|
|
||||||
AddTableRow(table, "Aktueller Wert", fahrzeug.AktuellerWertFormatiert, labelFont, calculatedFont);
|
|
||||||
AddTableRow(table, "Alter", $"{fahrzeug.GetAlter()} Jahre", labelFont, calculatedFont);
|
|
||||||
AddTableRow(table, "Wertverlust", $"{((fahrzeug.Kaufpreis - fahrzeug.AktuellerWert) / fahrzeug.Kaufpreis * 100):F1}%", labelFont, calculatedFont);
|
|
||||||
|
|
||||||
document.Add(table);
|
|
||||||
|
|
||||||
// Zusätzliche Informationen
|
|
||||||
var infoTitel = new iTextSharp.text.Paragraph("ZUSÄTZLICHE INFORMATIONEN",
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 14, BaseColor.DARK_GRAY))
|
|
||||||
{
|
|
||||||
SpacingBefore = 20,
|
|
||||||
SpacingAfter = 10
|
|
||||||
};
|
|
||||||
document.Add(infoTitel);
|
|
||||||
|
|
||||||
var infoText = new StringBuilder();
|
|
||||||
infoText.AppendLine($"• Fahrzeugtyp: {(fahrzeug.IsOldtimer() ? "Oldtimer" : "Gebrauchtwagen")}");
|
|
||||||
infoText.AppendLine($"• Vollständige Bezeichnung: {fahrzeug.GetDetailedDescription()}");
|
|
||||||
infoText.AppendLine($"• Durchschnittliche Laufleistung pro Jahr: {(fahrzeug.Kilometerstand / Math.Max(fahrzeug.GetAlter(), 1)):N0} km");
|
|
||||||
|
|
||||||
if (fahrzeug.IsOldtimer())
|
|
||||||
{
|
|
||||||
infoText.AppendLine("• Oldtimer-Status: Dieses Fahrzeug ist über 30 Jahre alt und gilt als Oldtimer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var info = new iTextSharp.text.Paragraph(infoText.ToString(),
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA, 10, BaseColor.BLACK))
|
|
||||||
{
|
|
||||||
SpacingAfter = 20
|
|
||||||
};
|
|
||||||
document.Add(info);
|
|
||||||
|
|
||||||
// Bewertungshinweise
|
|
||||||
var bewertungTitel = new iTextSharp.text.Paragraph("BEWERTUNGSHINWEISE",
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 14, BaseColor.DARK_GRAY))
|
|
||||||
{
|
|
||||||
SpacingBefore = 20,
|
|
||||||
SpacingAfter = 10
|
|
||||||
};
|
|
||||||
document.Add(bewertungTitel);
|
|
||||||
|
|
||||||
var bewertungText = @"Der angegebene aktuelle Wert ist eine automatische Schätzung basierend auf:
|
|
||||||
• Alter des Fahrzeugs (15% Wertverlust pro Jahr in den ersten 3 Jahren, dann 10% pro Jahr)
|
|
||||||
• Kilometerstand (2% Wertverlust pro 10.000 km)
|
|
||||||
• Mindestwert von 5% des ursprünglichen Kaufpreises
|
|
||||||
|
|
||||||
Diese Bewertung ersetzt keine professionelle Fahrzeugbewertung und dient nur als Richtwert.
|
|
||||||
Faktoren wie Zustand, Wartungshistorie, Unfallschäden und Marktlage werden nicht berücksichtigt.";
|
|
||||||
|
|
||||||
var bewertung = new iTextSharp.text.Paragraph(bewertungText,
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA, 9, BaseColor.GRAY))
|
|
||||||
{
|
|
||||||
SpacingAfter = 30
|
|
||||||
};
|
|
||||||
document.Add(bewertung);
|
|
||||||
|
|
||||||
// Fußzeile
|
|
||||||
var fusszeile = new iTextSharp.text.Paragraph("Erstellt mit Fahrzeugverwaltung - Alle Angaben ohne Gewähr",
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA, 8, BaseColor.LIGHT_GRAY))
|
|
||||||
{
|
|
||||||
Alignment = Element.ALIGN_CENTER
|
|
||||||
};
|
|
||||||
document.Add(fusszeile);
|
|
||||||
|
|
||||||
document.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
throw new Exception($"Fehler beim Erstellen des PDFs: {ex.Message}");
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
// erstellt ein einfaches PDF mit einer Fahrzeugliste
|
||||||
/// Hilfsmethode zum Hinzufügen einer Tabellenzeile
|
public bool ErstelleFahrzeuglistePdf(List<Fahrzeug> fahrzeuge, string dateiPfad)
|
||||||
/// </summary>
|
|
||||||
private void AddTableRow(PdfPTable table, string label, string value, Font labelFont, Font valueFont)
|
|
||||||
{
|
|
||||||
var labelCell = new PdfPCell(new Phrase(label, labelFont))
|
|
||||||
{
|
|
||||||
Padding = 8,
|
|
||||||
BackgroundColor = BaseColor.LIGHT_GRAY,
|
|
||||||
HorizontalAlignment = Element.ALIGN_LEFT
|
|
||||||
};
|
|
||||||
|
|
||||||
var valueCell = new PdfPCell(new Phrase(value, valueFont))
|
|
||||||
{
|
|
||||||
Padding = 8,
|
|
||||||
HorizontalAlignment = Element.ALIGN_LEFT
|
|
||||||
};
|
|
||||||
|
|
||||||
table.AddCell(labelCell);
|
|
||||||
table.AddCell(valueCell);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Erstellt ein PDF mit einer Fahrzeugliste
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fahrzeuge">Liste der Fahrzeuge</param>
|
|
||||||
/// <param name="dateiPfad">Pfad für das PDF</param>
|
|
||||||
/// <returns>True wenn erfolgreich</returns>
|
|
||||||
public bool ErstelleFahrzeuglistePdf(System.Collections.Generic.List<Fahrzeug> fahrzeuge, string dateiPfad)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var document = new iTextSharp.text.Document(PageSize.A4.Rotate(), 30, 30, 30, 30))
|
using var document = new Document(PageSize.A4.Rotate());
|
||||||
|
PdfWriter.GetInstance(document, new FileStream(dateiPfad, FileMode.Create));
|
||||||
|
document.Open();
|
||||||
|
var table = new PdfPTable(8) { WidthPercentage = 100 };
|
||||||
|
string[] headers = { "Marke", "Modell", "Baujahr", "Leistung", "Kilometer", "Kaufpreis", "Farbe", "Aktueller Wert" };
|
||||||
|
foreach (var h in headers)
|
||||||
|
table.AddCell(new PdfPCell(new Phrase(h)) { BackgroundColor = BaseColor.LIGHT_GRAY });
|
||||||
|
foreach (var f in fahrzeuge)
|
||||||
{
|
{
|
||||||
using (var writer = PdfWriter.GetInstance(document, new FileStream(dateiPfad, FileMode.Create)))
|
table.AddCell(f.Marke);
|
||||||
{
|
table.AddCell(f.Modell);
|
||||||
document.Open();
|
table.AddCell(f.Baujahr.ToString());
|
||||||
|
table.AddCell($"{f.Leistung} PS");
|
||||||
// Titel
|
table.AddCell(f.KilometerstandFormatiert);
|
||||||
var titel = new iTextSharp.text.Paragraph("FAHRZEUGLISTE",
|
table.AddCell(f.KaufpreisFormatiert);
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 16, BaseColor.DARK_GRAY))
|
table.AddCell(f.Farbe);
|
||||||
{
|
table.AddCell(f.AktuellerWertFormatiert);
|
||||||
Alignment = Element.ALIGN_CENTER,
|
|
||||||
SpacingAfter = 20
|
|
||||||
};
|
|
||||||
document.Add(titel);
|
|
||||||
|
|
||||||
// Datum und Anzahl
|
|
||||||
var info = new iTextSharp.text.Paragraph($"Erstellt am: {DateTime.Now:dd.MM.yyyy HH:mm} | Anzahl Fahrzeuge: {fahrzeuge.Count}",
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA, 10, BaseColor.GRAY))
|
|
||||||
{
|
|
||||||
Alignment = Element.ALIGN_CENTER,
|
|
||||||
SpacingAfter = 20
|
|
||||||
};
|
|
||||||
document.Add(info);
|
|
||||||
|
|
||||||
// Tabelle mit allen Fahrzeugen
|
|
||||||
var table = new PdfPTable(8) { WidthPercentage = 100 };
|
|
||||||
table.SetWidths(new float[] { 1f, 1.2f, 0.8f, 0.8f, 1f, 1f, 0.8f, 1.2f });
|
|
||||||
|
|
||||||
// Header
|
|
||||||
var headerFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 10, BaseColor.WHITE);
|
|
||||||
var headers = new[] { "Marke", "Modell", "Baujahr", "Leistung", "Kilometer", "Kaufpreis", "Farbe", "Akt. Wert" };
|
|
||||||
|
|
||||||
foreach (var header in headers)
|
|
||||||
{
|
|
||||||
var headerCell = new PdfPCell(new Phrase(header, headerFont))
|
|
||||||
{
|
|
||||||
BackgroundColor = BaseColor.DARK_GRAY,
|
|
||||||
Padding = 5,
|
|
||||||
HorizontalAlignment = Element.ALIGN_CENTER
|
|
||||||
};
|
|
||||||
table.AddCell(headerCell);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Datenzeilen
|
|
||||||
var contentFont = FontFactory.GetFont(FontFactory.HELVETICA, 9, BaseColor.BLACK);
|
|
||||||
foreach (var fahrzeug in fahrzeuge)
|
|
||||||
{
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.Marke, contentFont)) { Padding = 5 });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.Modell, contentFont)) { Padding = 5 });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.Baujahr.ToString(), contentFont)) { Padding = 5, HorizontalAlignment = Element.ALIGN_CENTER });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase($"{fahrzeug.Leistung} PS", contentFont)) { Padding = 5, HorizontalAlignment = Element.ALIGN_CENTER });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.KilometerstandFormatiert, contentFont)) { Padding = 5, HorizontalAlignment = Element.ALIGN_RIGHT });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.KaufpreisFormatiert, contentFont)) { Padding = 5, HorizontalAlignment = Element.ALIGN_RIGHT });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.Farbe, contentFont)) { Padding = 5 });
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(fahrzeug.AktuellerWertFormatiert, contentFont)) { Padding = 5, HorizontalAlignment = Element.ALIGN_RIGHT });
|
|
||||||
}
|
|
||||||
|
|
||||||
document.Add(table);
|
|
||||||
|
|
||||||
// Zusammenfassung
|
|
||||||
var gesamtKaufpreis = fahrzeuge.Sum(f => f.Kaufpreis);
|
|
||||||
var gesamtAktuellerWert = fahrzeuge.Sum(f => f.AktuellerWert);
|
|
||||||
var gesamtWertverlust = gesamtKaufpreis - gesamtAktuellerWert;
|
|
||||||
|
|
||||||
var zusammenfassung = new iTextSharp.text.Paragraph($"\nZUSAMMENFASSUNG:\n" +
|
|
||||||
$"Gesamter Kaufpreis: {gesamtKaufpreis:C}\n" +
|
|
||||||
$"Gesamter aktueller Wert: {gesamtAktuellerWert:C}\n" +
|
|
||||||
$"Gesamter Wertverlust: {gesamtWertverlust:C} ({(gesamtWertverlust / gesamtKaufpreis * 100):F1}%)",
|
|
||||||
FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11, BaseColor.DARK_GRAY))
|
|
||||||
{
|
|
||||||
SpacingBefore = 20
|
|
||||||
};
|
|
||||||
document.Add(zusammenfassung);
|
|
||||||
|
|
||||||
document.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
document.Add(table);
|
||||||
|
document.Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
throw new Exception($"Fehler beim Erstellen der Fahrzeugliste: {ex.Message}");
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user