diff --git a/JavaJPA.iml b/JavaJPA.iml
new file mode 100644
index 00000000..51151a37
--- /dev/null
+++ b/JavaJPA.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d586b911..6e5f5df6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,8 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.example
@@ -9,46 +10,101 @@
1.0-SNAPSHOT
- 25
+ 17
UTF-8
- 6.0.1
- 3.27.6
- 5.21.0
+ 21.0.1
+ 6.4.1.Final
+
+
- org.junit.jupiter
- junit-jupiter
- ${junit.jupiter.version}
- test
+ org.openjfx
+ javafx-controls
+ ${javafx.version}
- org.assertj
- assertj-core
- ${assertj.core.version}
- test
-
-
- org.mockito
- mockito-junit-jupiter
- ${mockito.version}
- test
+ org.openjfx
+ javafx-fxml
+ ${javafx.version}
+
+
org.hibernate.orm
hibernate-core
- 7.2.0.Final
+ ${hibernate.version}
+
+ jakarta.persistence
+ jakarta.persistence-api
+ 3.1.0
+
+
+
com.mysql
mysql-connector-j
- 9.5.0
- runtime
+ 9.1.0
+
+
- io.github.classgraph
- classgraph
- 4.8.184
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.10.1
+ test
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.13.0
+
+ 17
+
+
+
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+ org.example.Main
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.0
+
+
+ package
+
+ shade
+
+
+
+
+ org.example.Main
+
+
+ META-INF/persistence.xml
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/org/example/App.java b/src/main/java/org/example/App.java
index f2f67ca3..c275f9cc 100644
--- a/src/main/java/org/example/App.java
+++ b/src/main/java/org/example/App.java
@@ -1,57 +1,54 @@
package org.example;
import jakarta.persistence.EntityManager;
-import jakarta.persistence.EntityManagerFactory;
-import jakarta.persistence.Persistence;
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import org.example.util.DataInitializer;
+import org.example.util.JPAUtil;
+
+public class App extends Application {
+// ... existing code ...
+
+ @Override
+ public void start(Stage stage) {
+ try {
+ // 1. Initiera databasen och ladda testdata (seed)
+ initDatabase();
+
+ // 2. Ladda gränssnittet
+ FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("/fxml/main_view.fxml"));
+ Scene scene = new Scene(fxmlLoader.load(), 1000, 600);
+
+ // Koppla på CSS för "Hertz-looken"
+ // scene.getStylesheets().add(App.class.getResource("/css/main.css").toExternalForm());
+
+ stage.setTitle("Hertz Biluthyrning - Grupp 7");
+ stage.setScene(scene);
+ stage.show();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.println("Kunde inte starta applikationen: " + e.getMessage());
+ }
+ }
-public class App {
- public static void main(String[] args) {
- EntityManagerFactory emf = Persistence.createEntityManagerFactory("carRentalPU");
- EntityManager em = emf.createEntityManager();
-
- em.getTransaction().begin();
-
- // Rensa tabellen innan vi lägger in nya bilar
- em.createQuery("DELETE FROM Car").executeUpdate();
-
- // Skapa och persist 20 bilar med rimliga dagspriser
- em.persist(createCar("Volvo", "XC90", 2025, "Lyxbil", 800_000));
- em.persist(createCar("BMW", "7 Series", 2024, "Lyxbil", 1_000_000));
- em.persist(createCar("Audi", "A8", 2023, "Lyxbil", 900_000));
- em.persist(createCar("Toyota", "Corolla", 2022, "Personbil", 200_000));
- em.persist(createCar("Honda", "Civic", 2021, "Personbil", 190_000));
- em.persist(createCar("Ford", "Focus", 2022, "Personbil", 210_000));
- em.persist(createCar("Mercedes", "Sprinter", 2023, "Minibuss", 350_000));
- em.persist(createCar("Volkswagen", "Transporter", 2023, "Minibuss", 330_000));
- em.persist(createCar("Renault", "Kangoo", 2022, "Minibuss", 300_000));
- em.persist(createCar("Fiat", "500", 2023, "Småbil", 120_000));
- em.persist(createCar("Mini", "Cooper", 2022, "Småbil", 150_000));
- em.persist(createCar("Volkswagen", "Up!", 2022, "Småbil", 110_000));
- em.persist(createCar("Porsche", "911", 2025, "Sportbil", 1_500_000));
- em.persist(createCar("Ferrari", "Roma", 2024, "Sportbil", 2_000_000));
- em.persist(createCar("Lamborghini", "Huracan", 2025, "Sportbil", 2_500_000));
- em.persist(createCar("Tesla", "Model S", 2023, "Lyxbil", 900_000));
- em.persist(createCar("Kia", "Rio", 2022, "Småbil", 130_000));
- em.persist(createCar("Hyundai", "i30", 2023, "Personbil", 195_000));
- em.persist(createCar("Opel", "Vivaro", 2022, "Minibuss", 320_000));
- em.persist(createCar("Jaguar", "F-Type", 2024, "Sportbil", 1_600_000));
-
- em.getTransaction().commit();
- em.close();
- emf.close();
-
- System.out.println("20 cars saved successfully!");
+ private void initDatabase() {
+ EntityManager em = JPAUtil.getEntityManagerFactory().createEntityManager();
+ try {
+ DataInitializer.seed(em);
+ } finally {
+ em.close();
+ }
}
- // Skapar bil och sätter dagspris till 0,5% av priset
- private static Car createCar(String brand, String model, int year, String type, double price) {
- Car car = new Car;
- car.setBrand(brand);
- car.setModel(model);
- car.setYear(year);
- car.setType(type);
- car.setPrice(price);
- car.setDailyPrice(price * 0.005); // 0,5% av totalpris
- return car;
+ @Override
+ public void stop() {
+ // Stäng ner JPA snyggt när appen stängs
+ JPAUtil.shutdown();
+ }
+
+ public static void main(String[] args) {
+ launch();
}
}
diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java
new file mode 100644
index 00000000..6bf26dd2
--- /dev/null
+++ b/src/main/java/org/example/Main.java
@@ -0,0 +1,7 @@
+package org.example;
+
+public class Main {
+ public static void main(String[] args) {
+ App.main(args);
+ }
+}
diff --git a/src/main/java/org/example/controller/BookingController.java b/src/main/java/org/example/controller/BookingController.java
index 7c7a57e5..9b300fa3 100644
--- a/src/main/java/org/example/controller/BookingController.java
+++ b/src/main/java/org/example/controller/BookingController.java
@@ -1,4 +1,139 @@
package org.example.controller;
+import javafx.fxml.FXML;
+import javafx.scene.control.*;
+import javafx.scene.layout.VBox;
+import org.example.model.Car;
+import org.example.model.Extra;
+import org.example.util.JPAUtil;
+import jakarta.persistence.EntityManager;
+import java.util.ArrayList;
+import java.util.List;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
public class BookingController {
+
+ @FXML private ComboBox carComboBox;
+ @FXML private DatePicker startDatePicker;
+ @FXML private DatePicker endDatePicker;
+ @FXML private TextField customerEmailField;
+ @FXML private VBox extrasContainer;
+ @FXML private Label daysLabel;
+ @FXML private Label carPriceLabel;
+ @FXML private Label totalAmountLabel;
+
+ private List extraCheckBoxes = new ArrayList<>();
+
+ @FXML
+ public void initialize() {
+ loadExtras();
+ loadAvailableCars(); // <--- Anropa den nya metoden här
+ }
+
+ private void loadAvailableCars() {
+ EntityManager em = JPAUtil.getEntityManagerFactory().createEntityManager();
+ try {
+ // Hämtar alla bilar som är markerade som tillgängliga
+ List availableCars = em.createQuery("SELECT c FROM Car c WHERE c.available = true", Car.class).getResultList();
+ carComboBox.getItems().setAll(availableCars);
+ } finally {
+ em.close();
+ }
+ }
+
+ private void loadExtras() {
+ EntityManager em = JPAUtil.getEntityManagerFactory().createEntityManager();
+ try {
+ List allExtras = em.createQuery("SELECT e FROM Extra e", Extra.class).getResultList();
+
+ extrasContainer.getChildren().clear();
+ extraCheckBoxes.clear();
+
+ for (Extra extra : allExtras) {
+ CheckBox cb = new CheckBox(extra.getName() + " (" + extra.getPrice() + " kr)");
+ cb.setUserData(extra);
+ cb.setOnAction(e -> updatePriceDisplay()); // Uppdatera totalpris när man klickar
+ extraCheckBoxes.add(cb);
+ extrasContainer.getChildren().add(cb);
+ }
+ } finally {
+ em.close();
+ }
+ }
+
+ @FXML
+ public void updatePriceDisplay() {
+ Car selectedCar = carComboBox.getSelectionModel().getSelectedItem();
+ LocalDate start = startDatePicker.getValue();
+ LocalDate end = endDatePicker.getValue();
+
+ long days = 0;
+ double carTotal = 0;
+ double extrasTotal = 0;
+
+ // 1. Räkna ut antal dagar
+ if (start != null && end != null && !end.isBefore(start)) {
+ days = ChronoUnit.DAYS.between(start, end);
+ if (days == 0) days = 1; // Räkna påbörjad dag som 1 dag
+ }
+
+ // 2. Räkna ut bilens pris
+ if (selectedCar != null) {
+ carTotal = selectedCar.getDailyPrice() * days;
+ }
+
+ // 3. Räkna ut tilläggens pris
+ extrasTotal = extraCheckBoxes.stream()
+ .filter(CheckBox::isSelected)
+ .mapToDouble(cb -> ((Extra) cb.getUserData()).getPrice())
+ .sum();
+
+ // 4. Uppdatera labels i UI
+ daysLabel.setText(String.valueOf(days));
+ carPriceLabel.setText(String.format("%.2f kr", carTotal));
+
+ double total = carTotal + extrasTotal;
+ totalAmountLabel.setText(String.format("%.2f kr", total));
+ }
+
+ @FXML
+ public void onConfirmBooking() {
+ // Kontrollera att allt är ifyllt
+ if (carComboBox.getValue() == null || startDatePicker.getValue() == null || customerEmailField.getText().isEmpty()) {
+ Alert alert = new Alert(Alert.AlertType.ERROR);
+ alert.setContentText("Vänligen fyll i alla uppgifter!");
+ alert.show();
+ return;
+ }
+
+ // HÄR SKER SJÄLVA SPARANDET I DATABASEN (Logik läggs till i BookingService sen)
+
+ // Tack-meddelande
+ Alert alert = new Alert(Alert.AlertType.INFORMATION);
+ alert.setTitle("Bokning Bekräftad");
+ alert.setHeaderText("Tack för din bokning!");
+ alert.setContentText("Din bil är nu reserverad. Välkommen att hämta den på valt startdatum.");
+
+ alert.showAndWait();
+
+ // Rensa formuläret eller hoppa tillbaka till huvudvyn
+ clearForm();
+ }
+
+ private void clearForm() {
+ carComboBox.getSelectionModel().clearSelection();
+ startDatePicker.setValue(null);
+ endDatePicker.setValue(null);
+ customerEmailField.clear();
+ extraCheckBoxes.forEach(cb -> cb.setSelected(false));
+ updatePriceDisplay();
+ }
+
+ public void setSelectedCar(Car car) {
+ if (carComboBox != null && car != null) {
+ carComboBox.getSelectionModel().select(car);
+ updatePriceDisplay();
+ }
+ }
}
diff --git a/src/main/java/org/example/controller/CarController.java b/src/main/java/org/example/controller/CarController.java
index 49de64a5..d9254192 100644
--- a/src/main/java/org/example/controller/CarController.java
+++ b/src/main/java/org/example/controller/CarController.java
@@ -1,11 +1,79 @@
package org.example.controller;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.control.*;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.layout.StackPane;
+import javafx.beans.property.SimpleStringProperty;
+import org.example.model.Car;
+import org.example.model.CarType;
+import org.example.service.CarService;
+import java.io.IOException;
+
public class CarController {
- boolean CarDamage=false;
- boolean CarRented=false;
- boolean CarAvailable=true;
- boolean CarBooked=false;
- boolean CarBroke=false;
- boolean CarReturned=false;
+ @FXML private TableView carTable;
+ @FXML private TableColumn brandColumn;
+ @FXML private TableColumn modelColumn;
+ @FXML private TableColumn typeColumn;
+ @FXML
+ private TableColumn priceColumn;
+ @FXML
+ private TableColumn statusColumn;
+ @FXML
+ private TextField searchField;
+
+ private final CarService carService = new CarService();
+
+ @FXML
+ public void initialize() {
+ // Koppla kolumnerna till Car-modellens fält via getters
+ brandColumn.setCellValueFactory(new PropertyValueFactory<>("brand"));
+ modelColumn.setCellValueFactory(new PropertyValueFactory<>("model"));
+ typeColumn.setCellValueFactory(new PropertyValueFactory<>("type"));
+ priceColumn.setCellValueFactory(new PropertyValueFactory<>("dailyPrice"));
+
+ // Specialhantering för status-kolumnen för att visa ikoner/text istället för boolean
+ statusColumn.setCellValueFactory(cellData -> {
+ boolean available = cellData.getValue().isAvailable();
+ boolean damaged = cellData.getValue().isDamaged();
+
+ if (damaged) return new SimpleStringProperty("🛠 Trasig");
+ return new SimpleStringProperty(available ? "✅ Tillgänglig" : "❌ Uthyrd");
+ });
+
+ loadCars();
+ }
+
+ private void loadCars() {
+ // Vi hämtar alla bilar för att visa hela vagnparken i tabellen
+ carTable.getItems().setAll(carService.getAllCars());
+ }
+
+ @FXML
+ public void handleBookingAction() {
+ Car selectedCar = carTable.getSelectionModel().getSelectedItem();
+ if (selectedCar != null && selectedCar.isAvailable() && !selectedCar.isDamaged()) {
+ try {
+ // 1. Ladda bokningsvyn
+ FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/booking_view.fxml"));
+ Parent bookingView = loader.load();
+
+ // 2. Skicka med den valda bilen till BookingController (valfritt men bra!)
+ BookingController bookingController = loader.getController();
+ bookingController.setSelectedCar(selectedCar);
+
+ // 3. Hitta contentArea och byt ut innehållet
+ StackPane contentArea = (StackPane) carTable.getScene().lookup("#contentArea");
+ if (contentArea != null) {
+ contentArea.getChildren().setAll(bookingView);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/src/main/java/org/example/controller/CustomerController.java b/src/main/java/org/example/controller/CustomerController.java
index 6cbcc5d9..59c63ef6 100644
--- a/src/main/java/org/example/controller/CustomerController.java
+++ b/src/main/java/org/example/controller/CustomerController.java
@@ -1,5 +1,31 @@
package org.example.controller;
-public interface CustomerController {
- int addCustomer();
+import javafx.fxml.FXML;
+import javafx.scene.control.TextField;
+import org.example.model.Customer;
+import org.example.service.CustomerService;
+
+public class CustomerController {
+
+ @FXML
+ private TextField firstNameField;
+ @FXML
+ private TextField lastNameField;
+ @FXML
+ private TextField emailField;
+
+ private final CustomerService customerService = new CustomerService();
+
+ @FXML
+ public void handleAddCustomer() {
+ String firstName = firstNameField.getText();
+ String lastName = lastNameField.getText();
+ String email = emailField.getText();
+
+ // Nu matchar vi konstruktorn Customer(String, String, String)
+ Customer customer = new Customer(firstName, lastName, email);
+ customerService.saveCustomer(customer);
+
+ System.out.println("Kund sparad: " + firstName + " " + lastName);
+ }
}
diff --git a/src/main/java/org/example/controller/MainViewController.java b/src/main/java/org/example/controller/MainViewController.java
index aa1a0cdc..6b188b2d 100644
--- a/src/main/java/org/example/controller/MainViewController.java
+++ b/src/main/java/org/example/controller/MainViewController.java
@@ -1,4 +1,40 @@
package org.example.controller;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.layout.StackPane;
+import java.io.IOException;
+
public class MainViewController {
+
+ @FXML
+ private StackPane contentArea;
+
+ @FXML
+ public void showCarView() {
+ loadView("/fxml/car_view.fxml");
+ }
+
+ @FXML
+ public void showBookingView() {
+ loadView("/fxml/booking_view.fxml");
+ }
+
+ @FXML
+ public void showCustomerView() {
+ loadView("/fxml/customer_view.fxml");
+ }
+
+ private void loadView(String fxmlPath) {
+ try {
+ Parent view = FXMLLoader.load(getClass().getResource(fxmlPath));
+ contentArea.getChildren().setAll(view);
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.err.println("Kunde inte ladda vyn: " + fxmlPath);
+ }
+ }
}
+
+
diff --git a/src/main/java/org/example/model/Booking.java b/src/main/java/org/example/model/Booking.java
index 52fd6bb4..e64a340f 100644
--- a/src/main/java/org/example/model/Booking.java
+++ b/src/main/java/org/example/model/Booking.java
@@ -1,58 +1,52 @@
package org.example.model;
import jakarta.persistence.*;
-
-
-import javax.tools.DocumentationTool;
-import javax.xml.stream.Location;
import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
@Entity
public class Booking {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
-
- @ManyToOne(optional = false)
- @JoinColumn(name = "customer_id")
- Customer customer;
-
- @ManyToOne(optional = false)
- @JoinColumn(name = "car_id")
- private Car car;
+ private LocalDate startDate;
+ private LocalDate endDate;
+ @Enumerated(EnumType.STRING)
+ private BookingStatus status;
@ManyToOne
- @JoinColumn(name = "pickup_location_id")
- private Location pickupLocation;
+ private Car car;
@ManyToOne
- @JoinColumn(name = "dropoff_location_id")
- private Location dropoffLocation;
-
- @OneToMany
- @JoinColumn(name = "booking_id")
- private List extras;
+ private Customer customer;
- @OneToOne
- @JoinColumn(name = "payment_id")
- private Payment payment;
+ @ManyToMany
+ private List extras = new ArrayList<>();
- private LocalDate startDate;
- private LocalDate endDate;
-
- protected Booking() {
- // JPA requires a no-arg constructor
- }
-
- public Booking(Customer customer, Car car, Location pickupLocation, Location dropoffLocation, LocalDate startDate, LocalDate endDate) {
+ public Booking(Customer customer, Car car, LocalDate startDate, LocalDate endDate) {
this.customer = customer;
this.car = car;
this.startDate = startDate;
this.endDate = endDate;
this.status = BookingStatus.RESERVED;
- this.createdAt = LocalDateTime.now();
+ }
+
+ public void addExtra(Extra extra) {
+ this.extras.add(extra);
+ }
+ public long getDurationInDays() {
+ if (startDate == null || endDate == null) return 0;
+ return java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate);
}
+ // Getters och Setters
+ public Long getId() { return id; }
+ public Customer getCustomer() { return customer; }
+ public Car getCar() { return car; }
+ public LocalDate getStartDate() { return startDate; }
+ public LocalDate getEndDate() { return endDate; }
+ public List getExtras() { return extras; }
+ public void setStatus(BookingStatus status) { this.status = status; }
}
diff --git a/src/main/java/org/example/model/Car.java b/src/main/java/org/example/model/Car.java
index b5ec40f0..5aa518c8 100644
--- a/src/main/java/org/example/model/Car.java
+++ b/src/main/java/org/example/model/Car.java
@@ -1,12 +1,12 @@
-package org.example;
+package org.example.model;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
+import jakarta.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
@Entity
public class Car {
+
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@@ -14,28 +14,41 @@ public class Car {
private String brand;
private String model;
private int year;
- private String type;
- private double price;
- private double dailyPrice; // ny egenskap
- // Getters och setters
+ @Enumerated(EnumType.STRING)
+ private CarType type;
+ private double dailyPrice;
+ private boolean available = true;
+ private boolean damaged = false;
+
+ public Car() {}
+ public Car(String brand, String model, int year, CarType type, double dailyPrice) {
+ this.brand = brand;
+ this.model = model;
+ this.year = year;
+ this.type = type;
+ this.dailyPrice = dailyPrice;
+ }
+
+ // Getters som krävs för TableView (PropertyValueFactory)
public Long getId() { return id; }
-
public String getBrand() { return brand; }
- public void setBrand(String brand) { this.brand = brand; }
-
public String getModel() { return model; }
- public void setModel(String model) { this.model = model; }
-
public int getYear() { return year; }
- public void setYear(int year) { this.year = year; }
-
- public String getType() { return type; }
- public void setType(String type) { this.type = type; }
+ public CarType getType() { return type; }
+ public double getDailyPrice() { return dailyPrice; }
+ public boolean isAvailable() { return available; }
+ public boolean isDamaged() { return damaged; }
- public double getPrice() { return price; }
- public void setPrice(double price) { this.price = price; }
+ // Setters
+ public void setAvailable(boolean available) { this.available = available; }
+ public void setDamaged(boolean damaged) { this.damaged = damaged; }
- public double getDailyPrice() { return dailyPrice; }
- public void setDailyPrice(double dailyPrice) { this.dailyPrice = dailyPrice; }
+ @Override
+ public String toString() {
+ return brand + " " + model + " (" + year + ") - " + dailyPrice + " kr/dag";
+ }
}
+
+
+
diff --git a/src/main/java/org/example/model/CarType.java b/src/main/java/org/example/model/CarType.java
new file mode 100644
index 00000000..8ff7a84b
--- /dev/null
+++ b/src/main/java/org/example/model/CarType.java
@@ -0,0 +1,9 @@
+package org.example.model;
+
+public enum CarType {
+ SMALL,
+ FAMILY,
+ VAN,
+ SPORT,
+ LUXURY
+}
diff --git a/src/main/java/org/example/model/Customer.java b/src/main/java/org/example/model/Customer.java
index 1a66e22d..79ed55d3 100644
--- a/src/main/java/org/example/model/Customer.java
+++ b/src/main/java/org/example/model/Customer.java
@@ -8,14 +8,64 @@
public class Customer {
@Id
- @GeneratedValue
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
- private String name;
+ private String firstName;
+ private String lastName;
private String email;
+ // -------- One-to-Many --------
@OneToMany(mappedBy = "customer")
private List bookings = new ArrayList<>();
- // getters & setters
+ // -------- Constructors --------
+ protected Customer() {
+ // JPA kräver tom konstruktor
+ }
+
+ public Customer(String firstName, String lastName, String email) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.email = email;
+ }
+
+ // -------- Getters & setters --------
+ public Long getId() {
+ return id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public List getBookings() {
+ return bookings;
+ }
+
+ // -------- Nice to have --------
+ @Override
+ public String toString() {
+ return firstName + " " + lastName + " (" + email + ")";
+ }
}
diff --git a/src/main/java/org/example/model/Extra.java b/src/main/java/org/example/model/Extra.java
new file mode 100644
index 00000000..016a8fb7
--- /dev/null
+++ b/src/main/java/org/example/model/Extra.java
@@ -0,0 +1,31 @@
+package org.example.model;
+
+import jakarta.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+public class Extra {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+ private double price;
+
+ @ManyToMany(mappedBy = "extras")
+ private List bookings = new ArrayList<>();
+
+ public Extra() {}
+
+ public Extra(String name, double price) {
+ this.name = name;
+ this.price = price;
+ }
+
+ public double getPrice() { return price; }
+ public void setPrice(double price) { this.price = price; }
+ public String getName() { return name; }
+}
+
diff --git a/src/main/java/org/example/model/Location.java b/src/main/java/org/example/model/Location.java
new file mode 100644
index 00000000..24f1e81a
--- /dev/null
+++ b/src/main/java/org/example/model/Location.java
@@ -0,0 +1,24 @@
+package org.example.model;
+
+import jakarta.persistence.*;
+
+@Entity
+public class Location {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+
+ protected Location() {}
+
+ public Location(String name) {
+ this.name = name;
+ }
+
+ public Long getId() { return id; }
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+}
+
diff --git a/src/main/java/org/example/model/Payment.java b/src/main/java/org/example/model/Payment.java
index 0e4a6dd0..e543d069 100644
--- a/src/main/java/org/example/model/Payment.java
+++ b/src/main/java/org/example/model/Payment.java
@@ -1,7 +1,27 @@
package org.example.model;
import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
@Entity
public class Payment {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private double amount;
+ private String method;
+
+ // getters och setters
+ public Long getId() { return id; }
+ public void setId(Long id) { this.id = id; }
+
+ public double getAmount() { return amount; }
+ public void setAmount(double amount) { this.amount = amount; }
+
+ public String getMethod() { return method; }
+ public void setMethod(String method) { this.method = method; }
}
diff --git a/src/main/java/org/example/repository/BookingRepository.java b/src/main/java/org/example/repository/BookingRepository.java
index a63b50d4..6baa468e 100644
--- a/src/main/java/org/example/repository/BookingRepository.java
+++ b/src/main/java/org/example/repository/BookingRepository.java
@@ -1,4 +1,33 @@
package org.example.repository;
+import org.example.model.Booking;
+import jakarta.persistence.EntityManager;
+import org.example.util.JPAUtil;
+import java.util.List;
+
public class BookingRepository {
+
+ public void save(Booking booking) {
+ EntityManager em = JPAUtil.getEntityManager();
+ try {
+ em.getTransaction().begin();
+ if (booking.getId() == null) {
+ em.persist(booking);
+ } else {
+ em.merge(booking);
+ }
+ em.getTransaction().commit();
+ } catch (Exception e) {
+ if (em.getTransaction().isActive()) em.getTransaction().rollback();
+ throw e;
+ } finally {
+ em.close();
+ }
+ }
+
+ public List findAll() {
+ try (EntityManager em = JPAUtil.getEntityManager()) {
+ return em.createQuery("SELECT b FROM Booking b", Booking.class).getResultList();
+ }
+ }
}
diff --git a/src/main/java/org/example/repository/CarRepository.java b/src/main/java/org/example/repository/CarRepository.java
index cff21c7b..77237737 100644
--- a/src/main/java/org/example/repository/CarRepository.java
+++ b/src/main/java/org/example/repository/CarRepository.java
@@ -1,21 +1,37 @@
package org.example.repository;
import org.example.model.Car;
-import org.example.util.JPAUtil;
-
import jakarta.persistence.EntityManager;
+import org.example.util.JPAUtil;
import java.util.List;
public class CarRepository {
public List findAll() {
- EntityManager em = JPAUtil.getEntityManager();
+ try (EntityManager em = JPAUtil.getEntityManager()) {
+ return em.createQuery("SELECT c FROM Car c", Car.class).getResultList();
+ }
+ }
- List cars =
- em.createQuery("SELECT c FROM Car c", Car.class)
- .getResultList();
+ public List findAvailableCars() {
+ try (EntityManager em = JPAUtil.getEntityManager()) {
+ return em.createQuery("SELECT c FROM Car c WHERE c.available = true AND c.damaged = false", Car.class)
+ .getResultList();
+ }
+ }
- em.close();
- return cars;
+ public void save(Car car) {
+ EntityManager em = JPAUtil.getEntityManager();
+ try {
+ em.getTransaction().begin();
+ if (car.getId() == null) {
+ em.persist(car);
+ } else {
+ em.merge(car);
+ }
+ em.getTransaction().commit();
+ } finally {
+ em.close();
+ }
}
}
diff --git a/src/main/java/org/example/repository/CustomerRepository.java b/src/main/java/org/example/repository/CustomerRepository.java
index 38b788c2..36c35862 100644
--- a/src/main/java/org/example/repository/CustomerRepository.java
+++ b/src/main/java/org/example/repository/CustomerRepository.java
@@ -1,4 +1,41 @@
+
package org.example.repository;
+import org.example.model.Customer;
+import jakarta.persistence.EntityManager;
+import org.example.util.JPAUtil;
+import java.util.List;
+import java.util.Optional;
+
public class CustomerRepository {
+
+ public void save(Customer customer) {
+ EntityManager em = JPAUtil.getEntityManager();
+ try {
+ em.getTransaction().begin();
+ if (customer.getId() == null) {
+ em.persist(customer);
+ } else {
+ em.merge(customer);
+ }
+ em.getTransaction().commit();
+ } finally {
+ em.close();
+ }
+ }
+
+ public Optional findByEmail(String email) {
+ try (EntityManager em = JPAUtil.getEntityManager()) {
+ return em.createQuery("SELECT c FROM Customer c WHERE c.email = :email", Customer.class)
+ .setParameter("email", email)
+ .getResultStream()
+ .findFirst();
+ }
+ }
+
+ public List findAll() {
+ try (EntityManager em = JPAUtil.getEntityManager()) {
+ return em.createQuery("SELECT c FROM Customer c", Customer.class).getResultList();
+ }
+ }
}
diff --git a/src/main/java/org/example/service/BookingService.java b/src/main/java/org/example/service/BookingService.java
index aea99093..2957b158 100644
--- a/src/main/java/org/example/service/BookingService.java
+++ b/src/main/java/org/example/service/BookingService.java
@@ -1,4 +1,46 @@
package org.example.service;
+import org.example.model.Booking;
+import org.example.model.BookingStatus;
+import org.example.model.Extra;
+import org.example.repository.BookingRepository;
+import org.example.repository.CarRepository;
+import java.util.List;
+
public class BookingService {
+
+ private final BookingRepository bookingRepository = new BookingRepository();
+ private final CarRepository carRepository = new CarRepository();
+
+ public double calculateTotalPrice(Booking booking) {
+ if (booking.getCar() == null) return 0.0;
+
+ long days = booking.getDurationInDays();
+ if (days <= 0) days = 1;
+
+ double carTotal = booking.getCar().getDailyPrice() * days;
+ double extrasTotal = booking.getExtras().stream()
+ .mapToDouble(Extra::getPrice)
+ .sum();
+
+ return carTotal + extrasTotal;
+ }
+
+ public void createBooking(Booking booking) {
+ if (booking.getCar() == null || !booking.getCar().isAvailable()) {
+ throw new IllegalStateException("Bilen är inte tillgänglig för bokning.");
+ }
+
+ // Sätt status och spara
+ booking.setStatus(BookingStatus.RESERVED);
+ bookingRepository.save(booking);
+
+ // Uppdatera bilens status så den inte kan bokas av någon annan
+ booking.getCar().setAvailable(false);
+ carRepository.save(booking.getCar());
+ }
+
+ public List getAllBookings() {
+ return bookingRepository.findAll();
+ }
}
diff --git a/src/main/java/org/example/service/CarService.java b/src/main/java/org/example/service/CarService.java
index e81e1ea5..fee0ef7b 100644
--- a/src/main/java/org/example/service/CarService.java
+++ b/src/main/java/org/example/service/CarService.java
@@ -1,4 +1,29 @@
package org.example.service;
+import org.example.model.Car;
+import org.example.repository.CarRepository;
+import java.util.List;
+
public class CarService {
+
+ private final CarRepository carRepository = new CarRepository();
+
+ public List getAllCars() {
+ return carRepository.findAll();
+ }
+
+ public List getAvailableCars() {
+ return carRepository.findAvailableCars();
+ }
+
+ public void markAsDamaged(Car car) {
+ car.setDamaged(true);
+ car.setAvailable(false);
+ carRepository.save(car);
+ }
+
+ public void updateCarStatus(Car car, boolean available) {
+ car.setAvailable(available);
+ carRepository.save(car);
+ }
}
diff --git a/src/main/java/org/example/service/CustomerService.java b/src/main/java/org/example/service/CustomerService.java
index 4c00baea..436ff3a3 100644
--- a/src/main/java/org/example/service/CustomerService.java
+++ b/src/main/java/org/example/service/CustomerService.java
@@ -1,4 +1,29 @@
package org.example.service;
+import org.example.model.Customer;
+import org.example.repository.CustomerRepository;
+import java.util.List;
+import java.util.Optional;
+
public class CustomerService {
+
+ private final CustomerRepository customerRepository = new CustomerRepository();
+
+ public void saveCustomer(Customer customer) {
+ // Validering: kolla om e-post redan finns
+ Optional existing = customerRepository.findByEmail(customer.getEmail());
+ if (existing.isPresent()) {
+ System.out.println("Kunden finns redan i systemet.");
+ return;
+ }
+ customerRepository.save(customer);
+ }
+
+ public List getAllCustomers() {
+ return customerRepository.findAll();
+ }
+
+ public Optional findCustomerByEmail(String email) {
+ return customerRepository.findByEmail(email);
+ }
}
diff --git a/src/main/java/org/example/util/DataInitializer.java b/src/main/java/org/example/util/DataInitializer.java
new file mode 100644
index 00000000..9bdf24fe
--- /dev/null
+++ b/src/main/java/org/example/util/DataInitializer.java
@@ -0,0 +1,53 @@
+package org.example.util;
+
+import jakarta.persistence.EntityManager;
+import org.example.model.*;
+
+public class DataInitializer {
+
+ public static void seed(EntityManager em) {
+
+
+ if (!em.createQuery("SELECT c FROM Car c").getResultList().isEmpty()) {
+ return;
+ }
+
+ em.getTransaction().begin();
+
+ // ---------------- Cars (20 st) ----------------
+ em.persist(new Car("Volkswagen", "Polo", 2022, CarType.SMALL, 399));
+ em.persist(new Car("Toyota", "Yaris", 2023, CarType.SMALL, 429));
+ em.persist(new Car("Hyundai", "i20", 2021, CarType.SMALL, 389));
+ em.persist(new Car("Kia", "Rio", 2022, CarType.SMALL, 399));
+
+ em.persist(new Car("Volvo", "V60", 2023, CarType.FAMILY, 699));
+ em.persist(new Car("Volkswagen", "Passat", 2022, CarType.FAMILY, 649));
+ em.persist(new Car("Skoda", "Octavia", 2023, CarType.FAMILY, 629));
+ em.persist(new Car("Toyota", "Corolla Touring", 2022, CarType.FAMILY, 619));
+
+ em.persist(new Car("Volkswagen", "Transporter", 2021, CarType.VAN, 899));
+ em.persist(new Car("Ford", "Transit", 2022, CarType.VAN, 949));
+ em.persist(new Car("Mercedes", "Vito", 2023, CarType.VAN, 999));
+ em.persist(new Car("Renault", "Trafic", 2021, CarType.VAN, 879));
+
+ em.persist(new Car("BMW", "M3", 2023, CarType.SPORT, 1999));
+ em.persist(new Car("Audi", "RS5", 2022, CarType.SPORT, 1899));
+ em.persist(new Car("Porsche", "911", 2023, CarType.SPORT, 2999));
+ em.persist(new Car("Mercedes", "AMG GT", 2022, CarType.SPORT, 2799));
+
+ em.persist(new Car("Mazda", "CX-5", 2022, CarType.FAMILY, 679));
+ em.persist(new Car("Tesla", "Model Y", 2023, CarType.FAMILY, 799));
+ em.persist(new Car("Mini", "Cooper", 2022, CarType.SMALL, 459));
+ em.persist(new Car("Seat", "Leon", 2023, CarType.FAMILY, 599));
+
+ // ---------------- Extras ----------------
+ em.persist(new Extra("Försäkring", 149));
+ em.persist(new Extra("Takbox", 99));
+ em.persist(new Extra("GPS", 59));
+ em.persist(new Extra("Barnstol", 79));
+
+ em.getTransaction().commit();
+
+ System.out.println(" Seed-data skapad (20 bilar + extras)");
+ }
+}
diff --git a/src/main/java/org/example/util/JPAUtil.java b/src/main/java/org/example/util/JPAUtil.java
new file mode 100644
index 00000000..f5a56eb7
--- /dev/null
+++ b/src/main/java/org/example/util/JPAUtil.java
@@ -0,0 +1,24 @@
+package org.example.util;
+
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.EntityManagerFactory;
+import jakarta.persistence.Persistence;
+
+public class JPAUtil {
+ private static final EntityManagerFactory emf =
+ Persistence.createEntityManagerFactory("carRentalPU");
+
+ public static EntityManagerFactory getEntityManagerFactory() {
+ return emf;
+ }
+
+ public static EntityManager getEntityManager() {
+ return emf.createEntityManager();
+ }
+
+ public static void shutdown() {
+ if (emf != null && emf.isOpen()) {
+ emf.close();
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
index b43c6854..a7d6d15d 100644
--- a/src/main/resources/META-INF/persistence.xml
+++ b/src/main/resources/META-INF/persistence.xml
@@ -1,17 +1,34 @@
-
-
+
+
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+
+
+ org.example.model.Car
+ org.example.model.Customer
+ org.example.model.Booking
+ org.example.model.Extra
+ org.example.model.Location
+ org.example.model.Payment
+
+ value="jdbc:mysql://127.0.0.1:3306/carrental?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"/>
-
-
+
+
-
+
+
+
+
+
diff --git a/src/main/resources/css/main.css b/src/main/resources/css/main.css
index 90bc399a..342d5100 100644
--- a/src/main/resources/css/main.css
+++ b/src/main/resources/css/main.css
@@ -1,3 +1,130 @@
-tabell med bilar
-uthyrnings tabell med many2man
-kund tabell
+/* Färgtema: Midnight Gold */
+.main-container {
+ -fx-background-color: #f4f7f6;
+}
+
+.sidebar {
+ -fx-background-color: #1a2a3a; /* Mörk marinblå */
+}
+
+.logo-text {
+ -fx-text-fill: #ffcc00; /* Guld/Gul */
+ -fx-margin-bottom: 20;
+}
+
+.nav-button {
+ -fx-background-color: transparent;
+ -fx-text-fill: #ffffff;
+ -fx-alignment: CENTER_LEFT;
+ -fx-font-size: 14px;
+ -fx-cursor: hand;
+ -fx-padding: 10 15;
+ -fx-border-radius: 5;
+}
+
+.nav-button:hover {
+ -fx-background-color: #2c3e50;
+ -fx-text-fill: #ffcc00;
+}
+
+.welcome-header {
+ -fx-font-size: 32px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #1a2a3a;
+}
+
+.welcome-subtext {
+ -fx-font-size: 16px;
+ -fx-text-fill: #7f8c8d;
+}
+
+.content-pane {
+ -fx-background-color: white;
+ -fx-background-radius: 10 0 0 10;
+ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.1), 10, 0, 0, 0);
+}
+
+.view-header {
+ -fx-font-size: 28px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #1a2a3a;
+}
+
+.view-subheader {
+ -fx-font-size: 14px;
+ -fx-text-fill: #7f8c8d;
+}
+
+.search-field {
+ -fx-background-radius: 20;
+ -fx-padding: 8 15;
+ -fx-border-color: #dcdde1;
+ -fx-border-radius: 20;
+}
+
+.modern-table {
+ -fx-background-color: transparent;
+ -fx-border-color: #dcdde1;
+ -fx-border-radius: 5;
+}
+
+.modern-table .column-header {
+ -fx-background-color: #f8f9fa;
+ -fx-padding: 10;
+}
+
+.primary-button {
+ -fx-background-color: #ffcc00; /* Guld */
+ -fx-text-fill: #1a2a3a;
+ -fx-font-weight: bold;
+ -fx-padding: 10 25;
+ -fx-background-radius: 5;
+ -fx-cursor: hand;
+}
+
+.primary-button:hover {
+ -fx-background-color: #e6b800;
+}
+
+.secondary-button {
+ -fx-background-color: transparent;
+ -fx-border-color: #1a2a3a;
+ -fx-text-fill: #1a2a3a;
+ -fx-padding: 10 25;
+ -fx-background-radius: 5;
+ -fx-cursor: hand;
+}
+
+.summary-pane {
+ -fx-background-color: #f8f9fa;
+ -fx-border-color: #dcdde1;
+ -fx-border-radius: 10;
+ -fx-background-radius: 10;
+}
+
+.summary-header {
+ -fx-font-size: 18px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #1a2a3a;
+}
+
+.total-label {
+ -fx-font-weight: bold;
+ -fx-font-size: 14px;
+}
+
+.total-price {
+ -fx-font-size: 22px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #1a2a3a;
+}
+
+.section-header {
+ -fx-font-size: 16px;
+ -fx-font-weight: bold;
+ -fx-padding: 10 0;
+}
+
+.bold-text {
+ -fx-font-weight: bold;
+}
diff --git a/src/main/resources/fxml/booking_view.fxml b/src/main/resources/fxml/booking_view.fxml
index e69de29b..73ae9564 100644
--- a/src/main/resources/fxml/booking_view.fxml
+++ b/src/main/resources/fxml/booking_view.fxml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fxml/car_view.fxml b/src/main/resources/fxml/car_view.fxml
index e69de29b..edc6aa0c 100644
--- a/src/main/resources/fxml/car_view.fxml
+++ b/src/main/resources/fxml/car_view.fxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fxml/customer_view.fxml b/src/main/resources/fxml/customer_view.fxml
index e69de29b..de9b0b19 100644
--- a/src/main/resources/fxml/customer_view.fxml
+++ b/src/main/resources/fxml/customer_view.fxml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fxml/main_view.fxml b/src/main/resources/fxml/main_view.fxml
index 6fe83308..b91cb73c 100644
--- a/src/main/resources/fxml/main_view.fxml
+++ b/src/main/resources/fxml/main_view.fxml
@@ -2,9 +2,41 @@
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
diff --git a/src/main/resources/init.sql b/src/main/resources/init.sql
deleted file mode 100644
index 34ac4841..00000000
--- a/src/main/resources/init.sql
+++ /dev/null
@@ -1,105 +0,0 @@
--- ============================
--- DATABASE
--- ============================
-CREATE DATABASE IF NOT EXISTS carrental;
-USE carrental;
-
--- ============================
--- CUSTOMER
--- ============================
-CREATE TABLE customer (
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
- name VARCHAR(100) NOT NULL,
- email VARCHAR(150) UNIQUE NOT NULL
-);
-
--- ============================
--- CAR
--- ============================
-CREATE TABLE car (
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
- brand VARCHAR(100) NOT NULL,
- model VARCHAR(100) NOT NULL,
- price_per_day DOUBLE NOT NULL
-);
-
--- ============================
--- BOOKING
--- ============================
-CREATE TABLE booking (
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
- start_date DATE NOT NULL,
- end_date DATE NOT NULL,
- customer_id BIGINT NOT NULL,
-
- CONSTRAINT fk_booking_customer
- FOREIGN KEY (customer_id)
- REFERENCES customer(id)
- ON DELETE CASCADE
-);
-
--- ============================
--- BOOKING_CAR (Many-to-Many)
--- ============================
-CREATE TABLE booking_car (
- booking_id BIGINT NOT NULL,
- car_id BIGINT NOT NULL,
-
- PRIMARY KEY (booking_id, car_id),
-
- CONSTRAINT fk_bookingcar_booking
- FOREIGN KEY (booking_id)
- REFERENCES booking(id)
- ON DELETE CASCADE,
-
- CONSTRAINT fk_bookingcar_car
- FOREIGN KEY (car_id)
- REFERENCES car(id)
- ON DELETE CASCADE
-);
-
--- =================================================
--- ================== TESTDATA =====================
--- =================================================
-
--- ============================
--- CUSTOMERS
--- ============================
-INSERT INTO customer (name, email) VALUES
- ('Eric Thilen', 'eric@test.se'),
- ('Torsten Wihlborg', 'torsten@test.se'),
- ('Viktor Lindell', 'viktor@test.se');
-
--- ============================
--- CARS (BILAR ATT HYRA)
--- ============================
-INSERT INTO car (brand, model, price_per_day) VALUES
- ('Volvo', 'XC60', 899),
- ('Volvo', 'V90', 999),
- ('BMW', 'X5', 1199),
- ('Audi', 'A6', 1099),
- ('Tesla', 'Model 3', 1299),
- ('Toyota', 'Corolla', 699),
- ('Honda', 'Civic', 599),
- ('Skoda', 'Octavia', 499),
- ('Seat', 'Leon', 399),
- ('Seat', 'Ibiza', 299),
- ('Fiat', 'Multipla', 399);
-
-
--- ============================
--- BOOKINGS
--- ============================
-INSERT INTO booking (start_date, end_date, customer_id) VALUES
- ('2025-01-10', '2025-01-15', 1),
- ('2025-02-01', '2025-02-05', 2),
- ('2025-03-20', '2025-03-25', 3);
-
--- ============================
--- BOOKING ↔ CAR
--- ============================
-INSERT INTO booking_car (booking_id, car_id) VALUES
- (1, 1),
- (1, 2),
- (2, 3),
- (3, 5);