Compare commits

..

18 Commits

Author SHA1 Message Date
762680537b New: Readme
All checks were successful
Build and Push Docker Image / build (push) Successful in 4m7s
2026-03-18 11:09:30 +01:00
dbcd9f4872 Update: Rental Form Styles
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m10s
2026-03-18 10:49:04 +01:00
18289006d1 New: better Exception Handling
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m0s
2026-03-18 09:47:58 +01:00
d90a6f970f New: gitignore 2026-03-18 09:46:56 +01:00
4634c4ae98 Fix migration order
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m9s
2026-03-18 01:24:06 +01:00
7afab94810 Delay of 20 seconds before migration 2026-03-18 01:21:54 +01:00
b82ff1bce3 Fix: schema-migration
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m5s
2026-03-18 01:13:46 +01:00
6e8e16757f Fix: Migrations 2
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m6s
2026-03-18 01:07:41 +01:00
1c81d28cfd Fix: Create Schema Migration
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m4s
2026-03-18 01:01:30 +01:00
9cb299706d Use correct hostname
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m3s
2026-03-18 00:45:21 +01:00
530e79d581 Tooling: Use correct paths
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m3s
2026-03-18 00:39:15 +01:00
291cc195b1 Fix: Tooling-Container actually run migrations
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m58s
2026-03-18 00:36:14 +01:00
7f99284809 Use correct path for entrypoint.sh
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m13s
2026-03-17 23:16:17 +01:00
6afbb807a1 Fix: tooling-container
Some checks failed
Build and Push Docker Image / build (push) Failing after 1m52s
2026-03-17 23:13:07 +01:00
ab117c263d New: Create Snapshot in migration
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m59s
2026-03-17 22:20:35 +01:00
6575fc1d60 Fix: Buildah push
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m1s
2026-03-17 21:55:04 +01:00
c290a3af0a Fix: Docker build Paths
Some checks failed
Build and Push Docker Image / build (push) Failing after 1m48s
2026-03-17 21:51:11 +01:00
e285270621 Fix: Dockerfile Paths
Some checks failed
Build and Push Docker Image / build (push) Failing after 1m50s
2026-03-17 21:40:53 +01:00
19 changed files with 269 additions and 169 deletions

View File

@@ -28,11 +28,11 @@ jobs:
- name: Buildah Build
run: |
buildah build -t ${{ github.sha }} ./Einheit_4/2025_5BHITN_Konstantin_Hintermayer_smarterrent/Dockerfile
buildah build -t ${{ github.sha }}-tooling ./Einheit_4/tooling_container/Dockerfile
buildah build -t ${{ github.sha }}-tooling -f ./Einheit_4/tooling_container/Dockerfile .
buildah tag ${{ github.sha }} latest
- name: Push Docker Images
run: |
buildah push ${{ github.sha }} docker://git.kocoder.xyz/kocoded/2025_5BHITN_Hintermayer_Konstantin_smarterrent_db:${{ github.sha }}
buildah push ${{ github.sha }}-tooling docker://git.kocoder.xyz/kocoded/2025_5BHITN_Hintermayer_Konstantin_smarterrent_db_init_db:${{ github.sha }}
buildah push latest docker://git.kocoder.xyz/kocoded/2025_5BHITN_Hintermayer_Konstantin_smarterrent_db:latest
buildah push ${{ github.sha }} docker://git.kocoder.xyz/kocoded/kocoder_smarterrent:${{ github.sha }}
buildah push ${{ github.sha }}-tooling docker://git.kocoder.xyz/kocoded/kocoder_smarterrent_init_db:${{ github.sha }}
buildah push latest docker://git.kocoder.xyz/kocoded/kocoder_smarterrent:latest

View File

@@ -1,44 +1,46 @@
CREATE DATABASE "2025_5bhitn_konstantin_hintermayer_smarter_rentDB";
GO
USE "2025_5bhitn_konstantin_hintermayer_smarter_rentDB";
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '2025_5bhitn_konstantin_hintermayer_smarter_rentDB')
BEGIN
CREATE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
END;
GO
DROP TABLE IF EXISTS Rental;
USE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
GO
DROP TABLE IF EXISTS Customer;
DROP TABLE IF EXISTS [Location];
DROP TABLE IF EXISTS Vehicle;
DROP TABLE IF EXISTS VehicleCategory;
CREATE TABLE Customer (
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Customer]') AND type = 'U')
BEGIN
CREATE TABLE Customer (
id BIGINT NOT NULL IDENTITY (1, 1),
[name] VARCHAR(50) NOT NULL,
Adress VARCHAR(100) NOT NULL,
driverlicenseid VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
);
END;
CREATE TABLE Location (
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Location]') AND type = 'U')
BEGIN
CREATE TABLE Location (
id BIGINT NOT NULL IDENTITY (1, 1),
[name] VARCHAR(250) NOT NULL,
[address] VARCHAR(250) NOT NULL,
PRIMARY KEY (id)
);
);
END;
CREATE TABLE Rental (
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[VehicleCategory]') AND type = 'U')
BEGIN
CREATE TABLE VehicleCategory (
id BIGINT NOT NULL IDENTITY (1, 1),
rentalStart DATETIME NOT NULL,
rentalEnd DATETIME NOT NULL,
actualEnd DATETIME NULL,
customerID BIGINT NOT NULL,
vehicleID BIGINT NOT NULL,
[description] VARCHAR(250) NOT NULL,
pricePerDay DECIMAL NOT NULL,
PRIMARY KEY (id)
);
);
END;
CREATE TABLE Vehicle (
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Vehicle]') AND type = 'U')
BEGIN
CREATE TABLE Vehicle (
id BIGINT NOT NULL IDENTITY (1, 1),
brand VARCHAR(50) NOT NULL,
model VARCHAR(50) NOT NULL,
@@ -47,23 +49,34 @@ CREATE TABLE Vehicle (
locationID BIGINT NOT NULL,
vehicleCategoryID BIGINT NOT NULL,
PRIMARY KEY (id)
);
);
CREATE TABLE VehicleCategory (
ALTER TABLE Vehicle
ADD CONSTRAINT FK_Location_TO_Vehicle FOREIGN KEY (locationID) REFERENCES Location (id);
ALTER TABLE Vehicle
ADD CONSTRAINT FK_VehicleCategory_TO_Vehicle FOREIGN KEY (vehicleCategoryID) REFERENCES VehicleCategory (id);
END;
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Rental]') AND type = 'U')
BEGIN
CREATE TABLE Rental (
id BIGINT NOT NULL IDENTITY (1, 1),
[description] VARCHAR(250) NOT NULL,
pricePerDay DECIMAL NOT NULL,
rentalStart DATETIME NOT NULL,
rentalEnd DATETIME NOT NULL,
actualEnd DATETIME NULL,
customerID BIGINT NOT NULL,
vehicleID BIGINT NOT NULL,
PRIMARY KEY (id)
);
);
ALTER TABLE Rental
ADD CONSTRAINT FK_Customer_TO_Rental FOREIGN KEY (customerID) REFERENCES Customer (id);
ALTER TABLE Rental
ADD CONSTRAINT FK_Vehicle_TO_Rental FOREIGN KEY (vehicleID) REFERENCES Vehicle (id);
ALTER TABLE Rental
ADD CONSTRAINT FK_Customer_TO_Rental FOREIGN KEY (customerID) REFERENCES Customer (id);
ALTER TABLE Rental
ADD CONSTRAINT FK_Vehicle_TO_Rental FOREIGN KEY (vehicleID) REFERENCES Vehicle (id);
END;
ALTER TABLE Vehicle
ADD CONSTRAINT FK_Location_TO_Vehicle FOREIGN KEY (locationID) REFERENCES Location (id);
ALTER TABLE Vehicle
ADD CONSTRAINT FK_VehicleCategory_TO_Vehicle FOREIGN KEY (vehicleCategoryID) REFERENCES VehicleCategory (id);

View File

@@ -1,3 +1,6 @@
USE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
GO
-- Insert test data into the Location table
INSERT INTO [dbo].[Location] ([name], [address])
VALUES

View File

@@ -1,3 +1,7 @@
USE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
GO
-- ####################################################
-- # STORED PROCEDURES #
-- ####################################################

View File

@@ -0,0 +1,2 @@
bin/
obj/

View File

@@ -1,4 +1,9 @@
@inherits LayoutComponentBase
@using Services
@inherits LayoutComponentBase
@implements IDisposable
@rendermode RenderMode.InteractiveServer
@inject IErrorService ErrorService
<div class="page">
<div class="sidebar">
@@ -7,6 +12,13 @@
<main>
<article class="content px-4">
@if(ErrorService.ex != null) {
<div class="alert alert-danger m-3" role="alert">
@ErrorService.ex.Message
<button type="button" class="btn-close float-end" aria-label="Close" @onclick="DismissError"></button>
</div>
}
@Body
</article>
</main>
@@ -17,3 +29,20 @@
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
@code {
protected override void OnInitialized()
{
ErrorService.OnChange += StateHasChanged;
}
private void DismissError()
{
ErrorService.ex = null;
}
public void Dispose()
{
ErrorService.OnChange -= StateHasChanged;
}
}

View File

@@ -0,0 +1,18 @@
@page "/ErrorTest"
@using Microsoft.Data.SqlClient
@using Services
@inject IErrorService ErrorService
<PageTitle>Error Test</PageTitle>
<h1>Error Page</h1>
<button @onclick="SetError" class="btn btn-primary">Set Error</button>
@code {
private void SetError() {
ErrorService.ex = new Exception("Hello World");
}
}

View File

@@ -1,7 +1,9 @@
@page "/"
@using Models
@using Services
@using System.Runtime.InteropServices
@inject IRentService RentService
@inject IErrorService ErrorService
<PageTitle>Home</PageTitle>
@@ -45,9 +47,11 @@
protected override void OnInitialized()
{
try {
_vehicles = RentService.GetAvailableCars();
Console.WriteLine("VC" + _vehicles.Count);
@* return Task.CompletedTask; *@
} catch (Exception e) {
ErrorService.ex = e;
}
}
}

View File

@@ -1,33 +1,48 @@
@page "/rent"
@using Models
@using Services
@using System.Runtime.InteropServices
@inject IRentService RentService
@inject NavigationManager NavigationManager
@inject IErrorService ErrorService
<PageTitle>Rent</PageTitle>
<h1>Rent</h1>
<form @onsubmit="RentCar">
<InputSelect @bind-Value="_vehicleId">
<div class="form-group mb-3">
<label for="vehicle">Vehicle: </label>
<InputSelect @bind-Value="_vehicleId" id="vehicle" class="form-control" placeholder="Fahrzeug">
@foreach (Vehicle v in _vehicles)
{
<option value=@v.Id>@v.Id - @v.Brand - @v.Model</option>
}
</InputSelect>
</div>
<InputSelect @bind-Value="_customerId">
<div class="form-group mb-3">
<label for="customer">Kunde: </label>
<InputSelect @bind-Value="_customerId" id="customer" class="form-control" placeholder="Kunde">
@foreach (Customer c in _customers)
{
<option value=@c.Id>@c.Name</option>
}
</InputSelect>
</div>
<InputDate @bind-Value="_from"/>
<div class="form-group mb-3">
<label for="from">Von: </label>
<InputDate @bind-Value="_from" class="form-control" id="from" />
</div>
<InputDate @bind-Value="_thru"/>
<div class="form-group mb-3">
<label for="thru">Bis: </label>
<InputDate @bind-Value="_thru" class="form-control" id="thru" />
</div>
<button type="submit">Submit</button>
<button type="submit" class="btn btn-primary">Mieten!</button>
</form>
@code {
@@ -41,15 +56,22 @@
protected override void OnInitialized()
{
try {
_vehicles = RentService.GetAvailableCars();
_customers = RentService.GetCustomers();
} catch (Exception e) {
ErrorService.ex = e;
}
}
private Task RentCar()
{
try {
RentService.RentCar(_customerId, _vehicleId, _from, _thru);
Console.WriteLine("Rented Car");
NavigationManager.NavigateTo("/");
} catch (Exception e) {
ErrorService.ex = e;
}
return Task.CompletedTask;
}
}

View File

@@ -2,6 +2,7 @@
@using Models
@using Services
@inject IRollbackService RollbackService
@inject IErrorService ErrorService
<PageTitle>Rollback</PageTitle>
@@ -12,7 +13,11 @@
@code {
private Task PerformRollback() {
try {
RollbackService.ResetToDefaults();
} catch (Exception e) {
ErrorService.ex = e;
}
return Task.CompletedTask;
}
}

View File

@@ -17,6 +17,7 @@ public static class ServiceCollectionExtension
services.Services.AddScoped<IRentService, RentService>();
services.Services.AddScoped<IRollbackService, RollbackService>();
services.Services.AddScoped<IErrorService, ErrorService>();
return services;
}
}

View File

@@ -1,19 +0,0 @@
SELECT * FROM Vehicle;
SELECT * FROM Rental;
SELECT * FROM v_VerfuegbareFahrzeuge;
-- Create Snapshot;
CREATE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB_snapshot]
ON
(
NAME = [2025_5bhitn_konstantin_hintermayer_smarter_rentDB],
FILENAME = N'/var/opt/mssql/data/smarter_rentDB.ss'
) AS SNAPSHOT OF [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
GO
-- Restore Snapshot
USE [master];
ALTER DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] FROM DATABASE_SNAPSHOT = '2025_5bhitn_konstantin_hintermayer_smarter_rentDB_snapshot';
GO

View File

@@ -0,0 +1,30 @@
using System.Data;
using Configuration;
using Microsoft.Data.SqlClient;
using Models;
namespace Services
{
public interface IErrorService
{
Exception? ex { get; set; }
event Action? OnChange;
}
public class ErrorService : IErrorService
{
private Exception? _ex;
public Exception? ex
{
get => _ex;
set
{
_ex = value;
NotifyStateChanged();
}
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
}

View File

@@ -17,8 +17,7 @@ namespace Services
public List<Vehicle> GetAvailableCars()
{
List<Vehicle> vehicles = new List<Vehicle>();
try
{
using SqlConnection conn = sqlConnectionFactory.CreateSqlConnection();
string sql = "SELECT * FROM v_VerfuegbareFahrzeuge;";
SqlCommand cmd = new SqlCommand(sql, conn);
@@ -29,11 +28,6 @@ namespace Services
{
vehicles.Add(Vehicle.FromReader(reader));
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return vehicles;
}
@@ -41,8 +35,7 @@ namespace Services
public List<Customer> GetCustomers()
{
List<Customer> customers = new List<Customer>();
try
{
using SqlConnection conn = sqlConnectionFactory.CreateSqlConnection();
string sql = "SELECT * FROM Customer;";
SqlCommand cmd = new SqlCommand(sql, conn);
@@ -53,19 +46,13 @@ namespace Services
{
customers.Add(Customer.FromReader(reader));
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return customers;
}
public void RentCar(long customerId, long vehicleId, DateTime start, DateTime end)
{
try
{
using SqlConnection conn = sqlConnectionFactory.CreateSqlConnection();
using SqlCommand cmd = new SqlCommand("sp_MieteFahrzeug", conn);
cmd.CommandType = CommandType.StoredProcedure;
@@ -76,10 +63,6 @@ namespace Services
cmd.Parameters.AddWithValue("@Ende", end);
cmd.ExecuteNonQuery();
}catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}

View File

@@ -13,25 +13,18 @@ namespace Services
public class RollbackService(SqlConnectionFactory sqlConnectionFactory) : IRollbackService
{
public void ResetToDefaults()
{
try
{
using SqlConnection conn = sqlConnectionFactory.CreateSqlConnection();
string sql = @"
USE [master];
ALTER DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] FROM DATABASE_SNAPSHOT = '2025_5bhitn_konstantin_hintermayer_smarter_rentDB_snapshot';
ALTER DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] SET MULTI_USER;";
USE [master];
ALTER DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] FROM DATABASE_SNAPSHOT = '2025_5bhitn_konstantin_hintermayer_smarter_rentDB_snapshot';
ALTER DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB] SET MULTI_USER;";
using SqlCommand cmd = new SqlCommand(sql, conn);
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}

View File

@@ -2,8 +2,11 @@ FROM mcr.microsoft.com/mssql-tools
WORKDIR /App
# Copy everything
COPY ../../Einheit_1/2025_5BHITN_Konstantin_Hintermayer_create_schema.sql ./01.sql
COPY ../../Einheit_2/2025_5BHITN_Konstantin_Hintermayer_seed_database.sql ./02.sql
COPY ../../Einheit_3/2025_5BHITN_Konstantin_Hintermayer_procedures_and_triggers.sql ./03.sql
COPY ./Einheit_1/2025_5BHITN_Konstantin_Hintermayer_create_schema.sql ./01.sql
COPY ./Einheit_2/2025_5BHITN_Konstantin_Hintermayer_seed_database.sql ./02.sql
COPY ./Einheit_3/2025_5BHITN_Konstantin_Hintermayer_procedures_and_triggers.sql ./03.sql
COPY ./Einheit_5/2025_5BHITN_Konstantin_Hintermayer_snapshot_from_database.sql ./04.sql
ENTRYPOINT ["sqlcmd", "-D", ""]
COPY ./Einheit_4/tooling_container/entrypoint.sh .
ENTRYPOINT ["./entrypoint.sh"]

View File

@@ -1,16 +1,15 @@
#!/bin/bash
# Wait for SQL Server to boot up (adjust sleep if needed)
echo "Waiting for SQL Server to start..."
sleep 20s
# Run the three SQL files using sqlcmd
# -S: Server, -U: User, -P: Password (passed via ENV)
sleep 20
echo "Applying SQL files..."
for migration in $(ls . | grep -E '\.sql$')
do
echo "Applying $migration."
/opt/mssql-tools/bin/sqlcmd -D $DSN_PASSWORD -i $migration.sql
/opt/mssql-tools/bin/sqlcmd -S mssql-service -U sa -C -P "$DSN_PASSWORD" -i $migration
done
echo "Database initialization complete."

View File

@@ -0,0 +1,7 @@
CREATE DATABASE [2025_5bhitn_konstantin_hintermayer_smarter_rentDB_snapshot]
ON
(
NAME = [2025_5bhitn_konstantin_hintermayer_smarter_rentDB],
FILENAME = N'/var/opt/mssql/data/smarter_rentDB.ss'
) AS SNAPSHOT OF [2025_5bhitn_konstantin_hintermayer_smarter_rentDB];
GO

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# Smartrent
Deployed unter: https://sr.kocoder.xyz