Add Verpflegungsmehraufwand (VMA) as fixed facility condition field
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 17s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Successful in 6s
Docker-Images bauen und veröffentlichen / build (, omsorgapp/Dockerfile, omsorgapp) (push) Successful in 18s

Adds MealAllowanceRate as a flat, nullable EUR amount on Facility, following
the same pattern as the existing TravelCostRate/BillingRate fields — a fixed
per-facility rate, not the statutory day-based VMA tiers, per explicit
request.

Both generated API clients are regenerated/rebuilt as required after any
Contract/Controller change (see omsorgCore/CLAUDE.md, "Generierte API-
Clients"). The PHP client regen also picks up the DELETE /api/roles/{id}
endpoint added in a previous backend change but never synced to this client
until now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Felix Kemmler
2026-08-10 20:45:40 +02:00
co-authored by Claude Sonnet 5
parent 99b5e07390
commit 019b4286fd
23 changed files with 1820 additions and 138 deletions
+5 -5
View File
@@ -164,7 +164,7 @@ Vollständig implementiert: `PasswordResetCode`-Entity + `PasswordResetService`
- Connection-String-Key: `ConnectionStrings:OmsorgCore` (Format `Host=...;Port=5432;Database=omsorg_core;Username=...;Password=...`). - Connection-String-Key: `ConnectionStrings:OmsorgCore` (Format `Host=...;Port=5432;Database=omsorg_core;Username=...;Password=...`).
- `dotnet-ef` ist als lokales Tool eingerichtet (`.config/dotnet-tools.json`) — vor erster Nutzung `dotnet tool restore`. Wird nur noch zum **Erzeugen** neuer Migrationen gebraucht (`dotnet ef migrations add ...`), nicht mehr zum Anwenden. - `dotnet-ef` ist als lokales Tool eingerichtet (`.config/dotnet-tools.json`) — vor erster Nutzung `dotnet tool restore`. Wird nur noch zum **Erzeugen** neuer Migrationen gebraucht (`dotnet ef migrations add ...`), nicht mehr zum Anwenden.
- **`Program.cs` ruft bei jedem Start `db.Database.MigrateAsync()` auf, in jeder Umgebung** (nicht nur Development) — ausstehende Migrationen werden automatisch angewendet, bevor der Server Requests annimmt. Ein manuelles `dotnet ef database update` ist dadurch nur noch zum gezielten Vorab-Prüfen/Debuggen einer Migration nötig, nicht mehr für den normalen Start/Deploy. Schlägt die Migration fehl, crasht der Start bewusst fatal (fail-fast) statt mit einem veralteten Schema weiterzulaufen. - **`Program.cs` ruft bei jedem Start `db.Database.MigrateAsync()` auf, in jeder Umgebung** (nicht nur Development) — ausstehende Migrationen werden automatisch angewendet, bevor der Server Requests annimmt. Ein manuelles `dotnet ef database update` ist dadurch nur noch zum gezielten Vorab-Prüfen/Debuggen einer Migration nötig, nicht mehr für den normalen Start/Deploy. Schlägt die Migration fehl, crasht der Start bewusst fatal (fail-fast) statt mit einem veralteten Schema weiterzulaufen.
- Migrationen `InitialCreate`, `AddRefreshTokens`, `AddUserSecurityStamp`, `AddEmployeeContactFieldConstraints` und `AddAuditableSoftDelete` existieren (`src/OmsorgCore.Infrastructure/Persistence/Migrations/`) und wurden erfolgreich gegen eine echte PostgreSQL-Instanz angewendet. `AddContractDetailsAndQueryFilter` ist erzeugt, aber noch nicht gegen eine echte Instanz verifiziert (wird beim nächsten API-Start automatisch angewendet). `AddPermissionScope` (fügt `Scope` auf `role_permissions`/`user_permission_overrides` hinzu, siehe "Rechtesystem") wurde per `dotnet ef database update` erfolgreich gegen die echte Instanz angewendet. `AddFacilityConditionsAndQualificationRates` (Konditionen-Felder auf `Facility` + Tabelle `facility_qualification_rates`, FR-EIN-4), `AddAbsences` (Tabelle `absences`, FR-CON-1/FR-EM-3) und `AddTimeEntryStatusAndSurchargeHours` (`TimeEntry.StatusId`+Zuschlagsstunden, `ValueListItem.IsEditableByOwner`, `ValueListItemTransition.RequiresApproval`, FR-ZE-1/FR-ZE-2) wurden beim automatischen API-Start erfolgreich gegen die echte Instanz angewendet. `AddTravelCostModeAndEmployeeFacilityDistances` (`Facility.TravelCostMode`/`TravelCostPerKm` + Tabelle `employee_facility_distances`, siehe "Konditionen einer Einrichtung") ist erzeugt (`dotnet build`/`dotnet test` grün), aber noch nicht gegen eine echte Instanz verifiziert. - Migrationen `InitialCreate`, `AddRefreshTokens`, `AddUserSecurityStamp`, `AddEmployeeContactFieldConstraints` und `AddAuditableSoftDelete` existieren (`src/OmsorgCore.Infrastructure/Persistence/Migrations/`) und wurden erfolgreich gegen eine echte PostgreSQL-Instanz angewendet. `AddContractDetailsAndQueryFilter` ist erzeugt, aber noch nicht gegen eine echte Instanz verifiziert (wird beim nächsten API-Start automatisch angewendet). `AddPermissionScope` (fügt `Scope` auf `role_permissions`/`user_permission_overrides` hinzu, siehe "Rechtesystem") wurde per `dotnet ef database update` erfolgreich gegen die echte Instanz angewendet. `AddFacilityConditionsAndQualificationRates` (Konditionen-Felder auf `Facility` + Tabelle `facility_qualification_rates`, FR-EIN-4), `AddAbsences` (Tabelle `absences`, FR-CON-1/FR-EM-3) und `AddTimeEntryStatusAndSurchargeHours` (`TimeEntry.StatusId`+Zuschlagsstunden, `ValueListItem.IsEditableByOwner`, `ValueListItemTransition.RequiresApproval`, FR-ZE-1/FR-ZE-2) wurden beim automatischen API-Start erfolgreich gegen die echte Instanz angewendet. `AddTravelCostModeAndEmployeeFacilityDistances` (`Facility.TravelCostMode`/`TravelCostPerKm` + Tabelle `employee_facility_distances`, siehe "Konditionen einer Einrichtung") und `RemoveFacilityBreakPolicy` (löscht die Spalte `BreakPolicy` von `facilities` wieder) sind erzeugt (`dotnet build`/`dotnet test` grün), aber noch nicht gegen eine echte Instanz verifiziert.
## Build- und Run-Befehle ## Build- und Run-Befehle
@@ -233,14 +233,14 @@ Dropdown-Werte, die früher als hartcodierte Arrays im `omsorgapp`-Frontend lebt
## Konditionen einer Einrichtung (FR-EIN-4) ## Konditionen einer Einrichtung (FR-EIN-4)
Elf der zwölf Blueprint-19.2-Konditionsfelder (Verrechnungssatz, vier Zuschläge, Fahrtkosten, Mindeststunden, Pausenregelung, Abrechnungsintervall, Zahlungsziel, individuelle Vereinbarungen) sind flache, nullable Felder direkt auf `Facility` — kein `OwnsOne`/keine eigene Tabelle, analog zu Adresse/Rechnungsadresse auf `Facility` selbst und den Finanzfeldern auf `Contract`: Zehn der zwölf Blueprint-19.2-Konditionsfelder (Verrechnungssatz, vier Zuschläge, Fahrtkosten, Mindeststunden, Abrechnungsintervall, Zahlungsziel, individuelle Vereinbarungen) sind flache, nullable Felder direkt auf `Facility` — kein `OwnsOne`/keine eigene Tabelle, analog zu Adresse/Rechnungsadresse auf `Facility` selbst und den Finanzfeldern auf `Contract`. **Pausenregelung wurde am 2026-08-10 wieder entfernt** (fachlich nicht gebraucht, `BreakPolicy` auf `Facility`/`UpdateFacilityRequest`/`FacilityResponse` gelöscht, Migration `RemoveFacilityBreakPolicy`, beide generierten Clients neu erzeugt, `FacilityForm.jsx`/`FacilityDetailPanel.jsx` bereinigt) — falls sie doch wieder gebraucht wird, ist das ein Neuanlegen, kein Wiederherstellen (Hard-Delete der Spalte, kein Soft-Delete-Konzept für Schema-Felder):
- `BillingRate` (Verrechnungssatz, EUR/Std.), `NightSurchargePercent`/`SaturdaySurchargePercent`/`SundaySurchargePercent`/`HolidaySurchargePercent` (Zuschläge als **Prozent** auf den Verrechnungssatz, nicht als EUR-Betrag), `MinimumHours` (Mindeststunden je Einsatz), `BreakPolicy` (Pausenregelung, Freitext), `PaymentTermDays` (Zahlungsziel in Tagen), `IndividualAgreements` (Freitext). - `BillingRate` (Verrechnungssatz, EUR/Std.), `NightSurchargePercent`/`SaturdaySurchargePercent`/`SundaySurchargePercent`/`HolidaySurchargePercent` (Zuschläge als **Prozent** auf den Verrechnungssatz, nicht als EUR-Betrag), `MealAllowanceRate` (Verpflegungsmehraufwand, EUR-Pauschale je Einsatz — bewusst kein tageweises/gesetzliches Stufenmodell wie beim echten VMA, sondern wie `TravelCostRate` ein einziger fixer Betrag je Einrichtung), `MinimumHours` (Mindeststunden je Einsatz), `PaymentTermDays` (Zahlungsziel in Tagen), `IndividualAgreements` (Freitext).
- **Fahrtkosten (seit 2026-08-10 zwei Modi statt nur Pauschale):** `TravelCostMode` (`"Pauschale"` oder `"ProKilometer"`, Default `"Pauschale"`, im Controller gegen ein festes Literal-Array geprüft — **bewusst keine `ValueList`**, da die Rechnungserstellung später hart zwischen genau diesen zwei Fällen unterscheiden muss, ein dritter admin-hinzufügbarer Wert würde die künftige `FR-RE-1`-Berechnungslogik lautlos brechen, analog zur Begründung bei `AbsenceStatus.IsInitial`) entscheidet, welches Feld gilt: `TravelCostRate` (Pauschale je Einsatz, EUR) oder `TravelCostPerKm` (EUR/km) × `EmployeeFacilityDistance.DistanceKm`. Eine feste Facility-Distanz reicht nicht, weil jeder Mitarbeiter von einem anderen Wohnort anfährt — daher `EmployeeFacilityDistance` (`Facility`×`Employee``DistanceKm`, `AuditableEntity`) als **zweite** 1:n-Unterressource von Facility, exakt nach dem `FacilityQualificationRate`-Muster: `GET/POST/PUT/DELETE /api/facilities/{facilityId}/employee-distances[/...]` (`EmployeeFacilityDistancesController`), gegated über dieselben `Facilities`-Rechte, kein eigener `ModuleType`. `Create` validiert zusätzlich, dass `EmployeeId` auf einen existierenden Mitarbeiter zeigt (`IEmployeeService.GetByIdAsync`) und dass für das Facility/Employee-Paar noch keine (nicht gelöschte) Distanz existiert. Soft-Delete, über `TrashController` (`api/trash/employee-facility-distances/...`) wiederherstellbar. - **Fahrtkosten (seit 2026-08-10 zwei Modi statt nur Pauschale):** `TravelCostMode` (`"Pauschale"` oder `"ProKilometer"`, Default `"Pauschale"`, im Controller gegen ein festes Literal-Array geprüft — **bewusst keine `ValueList`**, da die Rechnungserstellung später hart zwischen genau diesen zwei Fällen unterscheiden muss, ein dritter admin-hinzufügbarer Wert würde die künftige `FR-RE-1`-Berechnungslogik lautlos brechen, analog zur Begründung bei `AbsenceStatus.IsInitial`) entscheidet, welches Feld gilt: `TravelCostRate` (Pauschale je Einsatz, EUR) oder `TravelCostPerKm` (EUR/km) × `EmployeeFacilityDistance.DistanceKm`. Eine feste Facility-Distanz reicht nicht, weil jeder Mitarbeiter von einem anderen Wohnort anfährt — daher `EmployeeFacilityDistance` (`Facility`×`Employee``DistanceKm`, `AuditableEntity`) als **zweite** 1:n-Unterressource von Facility, exakt nach dem `FacilityQualificationRate`-Muster: `GET/POST/PUT/DELETE /api/facilities/{facilityId}/employee-distances[/...]` (`EmployeeFacilityDistancesController`), gegated über dieselben `Facilities`-Rechte, kein eigener `ModuleType`. `Create` validiert zusätzlich, dass `EmployeeId` auf einen existierenden Mitarbeiter zeigt (`IEmployeeService.GetByIdAsync`) und dass für das Facility/Employee-Paar noch keine (nicht gelöschte) Distanz existiert. Soft-Delete, über `TrashController` (`api/trash/employee-facility-distances/...`) wiederherstellbar.
- **Selbstbedienung durch den Außendienst (seit 2026-08-10, `MyFacilityDistancesController`, Route `api/me/facility-distances`):** Mitarbeiter sollen ihre eigene Fahrtstrecke selbst über `omsorgWeb/mitarbeiter-app` pflegen können, statt dass das Büro jede Kilometerangabe manuell einträgt. Dafür bewusst **kein** `Facilities`-Recht (das würde Konditionen/CRM-Daten offenlegen, die dem Außendienst laut Rechtematrix nicht zustehen), sondern ein neuer, eigenständiger `ModuleType.EmployeeFacilityDistances` (siehe "Rechtesystem" oben) — `GET /api/me/facility-distances` (eigene Distanzen inkl. `FacilityName`), `GET /api/me/facility-distances/facilities` (minimale Einrichtungsauswahl, nur `Id`/`Name` über `FacilityOptionResponse`, für das Formular-Dropdown), `POST`/`PUT` (Anlegen/Bearbeiten). `EmployeeId` kommt bei jeder Aktion ausschließlich aus `ICurrentUserService.EmployeeId` (JWT-Claim), nie vom Client — bei fehlender Verknüpfung `400` statt eines FK-Fehlers, analog zum `AbsenceService.CreateAsync`-Fallback. Bewusst **kein** `DELETE` hier (Löschen bleibt Büro-Aufgabe über den Papierkorb). Nutzt intern denselben `IEmployeeFacilityDistanceService`/dieselbe Tabelle wie `EmployeeFacilityDistancesController` — zwei Controller auf demselben Application-Service, unterschiedliche Zugriffsrechte, kein Datenmodell-Unterschied. - **Selbstbedienung durch den Außendienst (seit 2026-08-10, `MyFacilityDistancesController`, Route `api/me/facility-distances`):** Mitarbeiter sollen ihre eigene Fahrtstrecke selbst über `omsorgWeb/mitarbeiter-app` pflegen können, statt dass das Büro jede Kilometerangabe manuell einträgt. Dafür bewusst **kein** `Facilities`-Recht (das würde Konditionen/CRM-Daten offenlegen, die dem Außendienst laut Rechtematrix nicht zustehen), sondern ein neuer, eigenständiger `ModuleType.EmployeeFacilityDistances` (siehe "Rechtesystem" oben) — `GET /api/me/facility-distances` (eigene Distanzen inkl. `FacilityName`), `GET /api/me/facility-distances/facilities` (minimale Einrichtungsauswahl, nur `Id`/`Name` über `FacilityOptionResponse`, für das Formular-Dropdown), `POST`/`PUT` (Anlegen/Bearbeiten). `EmployeeId` kommt bei jeder Aktion ausschließlich aus `ICurrentUserService.EmployeeId` (JWT-Claim), nie vom Client — bei fehlender Verknüpfung `400` statt eines FK-Fehlers, analog zum `AbsenceService.CreateAsync`-Fallback. Bewusst **kein** `DELETE` hier (Löschen bleibt Büro-Aufgabe über den Papierkorb). Nutzt intern denselben `IEmployeeFacilityDistanceService`/dieselbe Tabelle wie `EmployeeFacilityDistancesController` — zwei Controller auf demselben Application-Service, unterschiedliche Zugriffsrechte, kein Datenmodell-Unterschied.
- **Zugleich behobener Bestandsfehler:** `FacilityService.UpdateAsync` kopierte die elf Konditionsfelder bislang gar nicht auf die getrackte Entität — der Controller validierte sie korrekt, aber `PUT /api/facilities/{id}` verwarf sie stillschweigend (kein Fehler, kein Log, das Feld blieb einfach `null`/unverändert). Betraf `BillingRate`/alle vier Zuschläge/`TravelCostRate`/`MinimumHours`/`BreakPolicy`/`BillingInterval`/`PaymentTermDays`/`IndividualAgreements` seit deren Einführung. Jetzt behoben, Regressionstest: `FacilityServiceTests.UpdateAsync_PersistsKonditionenFields`. - **Zugleich behobener Bestandsfehler:** `FacilityService.UpdateAsync` kopierte die elf Konditionsfelder bislang gar nicht auf die getrackte Entität — der Controller validierte sie korrekt, aber `PUT /api/facilities/{id}` verwarf sie stillschweigend (kein Fehler, kein Log, das Feld blieb einfach `null`/unverändert). Betraf `BillingRate`/alle vier Zuschläge/`TravelCostRate`/`MinimumHours`/`BillingInterval`/`PaymentTermDays`/`IndividualAgreements` seit deren Einführung (damals inkl. `BreakPolicy`, seit 2026-08-10 entfernt, siehe oben). Jetzt behoben, Regressionstest: `FacilityServiceTests.UpdateAsync_PersistsKonditionenFields`.
- `BillingInterval` wird wie `FacilityType`/`ContractType` gegen die admin-editierbare `ValueList` `"BillingInterval"` (Wöchentlich/Monatlich/Quartalsweise) validiert — siehe "Konfigurierbare Auswahllisten". - `BillingInterval` wird wie `FacilityType`/`ContractType` gegen die admin-editierbare `ValueList` `"BillingInterval"` (Wöchentlich/Monatlich/Quartalsweise) validiert — siehe "Konfigurierbare Auswahllisten".
- Alle elf Felder sind nur über `PUT /api/facilities/{id}` (`UpdateFacilityRequest`) setzbar, nicht beim Anlegen (`CreateFacilityRequest`) — analog zu `CrmStatus`, der ebenfalls erst nach dem Anlegen über "Bearbeiten" gepflegt wird. - Alle zwölf Felder sind nur über `PUT /api/facilities/{id}` (`UpdateFacilityRequest`) setzbar, nicht beim Anlegen (`CreateFacilityRequest`) — analog zu `CrmStatus`, der ebenfalls erst nach dem Anlegen über "Bearbeiten" gepflegt wird.
**Ausnahme "Qualifikationsabhängige Preise":** eine variable Liste (ein Satz je Qualifikationsstufe) lässt sich nicht als feste Spaltengruppe abbilden — dafür die neue Entität `FacilityQualificationRate` (1:n zu `Facility`, `Qualification` gegen die ValueList `"Qualification"` validiert — dieselbe Liste wie `Employee.Qualification`/`Order.RequiredQualification`, siehe "Wo welches Feld referenziert wird" oben) als 1:n-Unterressource unter `GET/POST/PUT/DELETE /api/facilities/{facilityId}/qualification-rates[/...]` (`FacilityQualificationRatesController`) — exakt nach dem Muster von `FacilityContact`, kein eigener `ModuleType`, gegated über dieselben `Facilities`-Rechte. Löschen ist Soft-Delete, über `TrashController` (`api/trash/facility-qualification-rates/...`) wiederherstellbar. **Ausnahme "Qualifikationsabhängige Preise":** eine variable Liste (ein Satz je Qualifikationsstufe) lässt sich nicht als feste Spaltengruppe abbilden — dafür die neue Entität `FacilityQualificationRate` (1:n zu `Facility`, `Qualification` gegen die ValueList `"Qualification"` validiert — dieselbe Liste wie `Employee.Qualification`/`Order.RequiredQualification`, siehe "Wo welches Feld referenziert wird" oben) als 1:n-Unterressource unter `GET/POST/PUT/DELETE /api/facilities/{facilityId}/qualification-rates[/...]` (`FacilityQualificationRatesController`) — exakt nach dem Muster von `FacilityContact`, kein eigener `ModuleType`, gegated über dieselben `Facilities`-Rechte. Löschen ist Soft-Delete, über `TrashController` (`api/trash/facility-qualification-rates/...`) wiederherstellbar.
@@ -23,8 +23,8 @@ public record FacilityResponse(
decimal? TravelCostRate, decimal? TravelCostRate,
string TravelCostMode, string TravelCostMode,
decimal? TravelCostPerKm, decimal? TravelCostPerKm,
decimal? MealAllowanceRate,
decimal? MinimumHours, decimal? MinimumHours,
string? BreakPolicy,
string? BillingInterval, string? BillingInterval,
int? PaymentTermDays, int? PaymentTermDays,
string? IndividualAgreements); string? IndividualAgreements);
@@ -22,8 +22,8 @@ public record UpdateFacilityRequest(
decimal? TravelCostRate, decimal? TravelCostRate,
string TravelCostMode, string TravelCostMode,
decimal? TravelCostPerKm, decimal? TravelCostPerKm,
decimal? MealAllowanceRate,
decimal? MinimumHours, decimal? MinimumHours,
string? BreakPolicy,
string? BillingInterval, string? BillingInterval,
int? PaymentTermDays, int? PaymentTermDays,
string? IndividualAgreements); string? IndividualAgreements);
@@ -202,11 +202,6 @@ public class FacilitiesController : ControllerBase
return BadRequest(billingAddressError); return BadRequest(billingAddressError);
} }
if (request.BreakPolicy is { Length: > 1000 })
{
return BadRequest("BreakPolicy darf maximal 1000 Zeichen lang sein.");
}
if (request.IndividualAgreements is { Length: > 2000 }) if (request.IndividualAgreements is { Length: > 2000 })
{ {
return BadRequest("IndividualAgreements darf maximal 2000 Zeichen lang sein."); return BadRequest("IndividualAgreements darf maximal 2000 Zeichen lang sein.");
@@ -224,6 +219,7 @@ public class FacilitiesController : ControllerBase
if (request.BillingRate is < 0 if (request.BillingRate is < 0
|| request.TravelCostRate is < 0 || request.TravelCostRate is < 0
|| request.TravelCostPerKm is < 0 || request.TravelCostPerKm is < 0
|| request.MealAllowanceRate is < 0
|| request.MinimumHours is < 0 || request.MinimumHours is < 0
|| request.NightSurchargePercent is < 0 || request.NightSurchargePercent is < 0
|| request.SaturdaySurchargePercent is < 0 || request.SaturdaySurchargePercent is < 0
@@ -252,8 +248,8 @@ public class FacilitiesController : ControllerBase
TravelCostRate = request.TravelCostRate, TravelCostRate = request.TravelCostRate,
TravelCostMode = request.TravelCostMode, TravelCostMode = request.TravelCostMode,
TravelCostPerKm = request.TravelCostPerKm, TravelCostPerKm = request.TravelCostPerKm,
MealAllowanceRate = request.MealAllowanceRate,
MinimumHours = request.MinimumHours, MinimumHours = request.MinimumHours,
BreakPolicy = request.BreakPolicy,
BillingInterval = request.BillingInterval, BillingInterval = request.BillingInterval,
PaymentTermDays = request.PaymentTermDays, PaymentTermDays = request.PaymentTermDays,
IndividualAgreements = request.IndividualAgreements, IndividualAgreements = request.IndividualAgreements,
@@ -330,8 +326,8 @@ public class FacilitiesController : ControllerBase
facility.TravelCostRate, facility.TravelCostRate,
facility.TravelCostMode, facility.TravelCostMode,
facility.TravelCostPerKm, facility.TravelCostPerKm,
facility.MealAllowanceRate,
facility.MinimumHours, facility.MinimumHours,
facility.BreakPolicy,
facility.BillingInterval, facility.BillingInterval,
facility.PaymentTermDays, facility.PaymentTermDays,
facility.IndividualAgreements); facility.IndividualAgreements);
@@ -63,8 +63,8 @@ public class FacilityService : IFacilityService
facility.TravelCostRate = updates.TravelCostRate; facility.TravelCostRate = updates.TravelCostRate;
facility.TravelCostMode = updates.TravelCostMode; facility.TravelCostMode = updates.TravelCostMode;
facility.TravelCostPerKm = updates.TravelCostPerKm; facility.TravelCostPerKm = updates.TravelCostPerKm;
facility.MealAllowanceRate = updates.MealAllowanceRate;
facility.MinimumHours = updates.MinimumHours; facility.MinimumHours = updates.MinimumHours;
facility.BreakPolicy = updates.BreakPolicy;
facility.BillingInterval = updates.BillingInterval; facility.BillingInterval = updates.BillingInterval;
facility.PaymentTermDays = updates.PaymentTermDays; facility.PaymentTermDays = updates.PaymentTermDays;
facility.IndividualAgreements = updates.IndividualAgreements; facility.IndividualAgreements = updates.IndividualAgreements;
@@ -39,8 +39,8 @@ public class Facility : AuditableEntity
public string TravelCostMode { get; set; } = "Pauschale"; public string TravelCostMode { get; set; } = "Pauschale";
public decimal? TravelCostRate { get; set; } public decimal? TravelCostRate { get; set; }
public decimal? TravelCostPerKm { get; set; } public decimal? TravelCostPerKm { get; set; }
public decimal? MealAllowanceRate { get; set; }
public decimal? MinimumHours { get; set; } public decimal? MinimumHours { get; set; }
public string? BreakPolicy { get; set; }
public string? BillingInterval { get; set; } public string? BillingInterval { get; set; }
public int? PaymentTermDays { get; set; } public int? PaymentTermDays { get; set; }
public string? IndividualAgreements { get; set; } public string? IndividualAgreements { get; set; }
@@ -31,8 +31,8 @@ public class FacilityConfiguration : IEntityTypeConfiguration<Facility>
builder.Property(f => f.TravelCostRate).HasColumnType("decimal(10,2)"); builder.Property(f => f.TravelCostRate).HasColumnType("decimal(10,2)");
builder.Property(f => f.TravelCostMode).IsRequired().HasMaxLength(20); builder.Property(f => f.TravelCostMode).IsRequired().HasMaxLength(20);
builder.Property(f => f.TravelCostPerKm).HasColumnType("decimal(10,2)"); builder.Property(f => f.TravelCostPerKm).HasColumnType("decimal(10,2)");
builder.Property(f => f.MealAllowanceRate).HasColumnType("decimal(10,2)");
builder.Property(f => f.MinimumHours).HasColumnType("decimal(5,2)"); builder.Property(f => f.MinimumHours).HasColumnType("decimal(5,2)");
builder.Property(f => f.BreakPolicy).HasMaxLength(1000);
builder.Property(f => f.BillingInterval).HasMaxLength(50); builder.Property(f => f.BillingInterval).HasMaxLength(50);
builder.Property(f => f.IndividualAgreements).HasMaxLength(2000); builder.Property(f => f.IndividualAgreements).HasMaxLength(2000);
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace OmsorgCore.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class AddFacilityMealAllowanceRate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "MealAllowanceRate",
table: "facilities",
type: "numeric(10,2)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "MealAllowanceRate",
table: "facilities");
}
}
}
@@ -426,10 +426,6 @@ namespace OmsorgCore.Infrastructure.Persistence.Migrations
.HasMaxLength(200) .HasMaxLength(200)
.HasColumnType("character varying(200)"); .HasColumnType("character varying(200)");
b.Property<string>("BreakPolicy")
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");
b.Property<string>("City") b.Property<string>("City")
.HasMaxLength(100) .HasMaxLength(100)
.HasColumnType("character varying(100)"); .HasColumnType("character varying(100)");
@@ -466,6 +462,9 @@ namespace OmsorgCore.Infrastructure.Persistence.Migrations
b.Property<bool>("IsDeleted") b.Property<bool>("IsDeleted")
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<decimal?>("MealAllowanceRate")
.HasColumnType("decimal(10,2)");
b.Property<decimal?>("MinimumHours") b.Property<decimal?>("MinimumHours")
.HasColumnType("decimal(5,2)"); .HasColumnType("decimal(5,2)");
@@ -103,8 +103,8 @@ public class FacilityServiceTests
TravelCostMode = "ProKilometer", TravelCostMode = "ProKilometer",
TravelCostRate = 10, TravelCostRate = 10,
TravelCostPerKm = 0.42m, TravelCostPerKm = 0.42m,
MealAllowanceRate = 14,
MinimumHours = 4, MinimumHours = 4,
BreakPolicy = "30 Min. ab 6 Std.",
BillingInterval = "Monatlich", BillingInterval = "Monatlich",
PaymentTermDays = 14, PaymentTermDays = 14,
IndividualAgreements = "Sonderkonditionen Wochenende" IndividualAgreements = "Sonderkonditionen Wochenende"
@@ -121,8 +121,8 @@ public class FacilityServiceTests
Assert.Equal("ProKilometer", updated.TravelCostMode); Assert.Equal("ProKilometer", updated.TravelCostMode);
Assert.Equal(10, updated.TravelCostRate); Assert.Equal(10, updated.TravelCostRate);
Assert.Equal(0.42m, updated.TravelCostPerKm); Assert.Equal(0.42m, updated.TravelCostPerKm);
Assert.Equal(14, updated.MealAllowanceRate);
Assert.Equal(4, updated.MinimumHours); Assert.Equal(4, updated.MinimumHours);
Assert.Equal("30 Min. ab 6 Std.", updated.BreakPolicy);
Assert.Equal("Monatlich", updated.BillingInterval); Assert.Equal("Monatlich", updated.BillingInterval);
Assert.Equal(14, updated.PaymentTermDays); Assert.Equal(14, updated.PaymentTermDays);
Assert.Equal("Sonderkonditionen Wochenende", updated.IndividualAgreements); Assert.Equal("Sonderkonditionen Wochenende", updated.IndividualAgreements);
@@ -231,13 +231,3 @@ lib/Model/ValueListTransitionResponse.php
lib/Model/ValueListUsageResponse.php lib/Model/ValueListUsageResponse.php
lib/ObjectSerializer.php lib/ObjectSerializer.php
phpunit.xml.dist phpunit.xml.dist
test/Api/EmployeeFacilityDistancesApiTest.php
test/Api/MyFacilityDistancesApiTest.php
test/Model/CreateEmployeeFacilityDistanceRequestTest.php
test/Model/CreateMyFacilityDistanceRequestTest.php
test/Model/EmployeeFacilityDistanceResponseTest.php
test/Model/FacilityOptionResponseTest.php
test/Model/MyFacilityDistanceResponseTest.php
test/Model/TrashEmployeeFacilityDistanceResponseTest.php
test/Model/UpdateEmployeeFacilityDistanceRequestTest.php
test/Model/UpdateMyFacilityDistanceRequestTest.php
@@ -143,6 +143,7 @@ Class | Method | HTTP request | Description
*OrdersApi* | [**apiOrdersIdPut**](docs/Api/OrdersApi.md#apiordersidput) | **PUT** /api/orders/{id} | *OrdersApi* | [**apiOrdersIdPut**](docs/Api/OrdersApi.md#apiordersidput) | **PUT** /api/orders/{id} |
*OrdersApi* | [**apiOrdersPost**](docs/Api/OrdersApi.md#apiorderspost) | **POST** /api/orders | *OrdersApi* | [**apiOrdersPost**](docs/Api/OrdersApi.md#apiorderspost) | **POST** /api/orders |
*RolesApi* | [**apiRolesGet**](docs/Api/RolesApi.md#apirolesget) | **GET** /api/roles | *RolesApi* | [**apiRolesGet**](docs/Api/RolesApi.md#apirolesget) | **GET** /api/roles |
*RolesApi* | [**apiRolesIdDelete**](docs/Api/RolesApi.md#apirolesiddelete) | **DELETE** /api/roles/{id} |
*RolesApi* | [**apiRolesIdGet**](docs/Api/RolesApi.md#apirolesidget) | **GET** /api/roles/{id} | *RolesApi* | [**apiRolesIdGet**](docs/Api/RolesApi.md#apirolesidget) | **GET** /api/roles/{id} |
*RolesApi* | [**apiRolesIdPermissionsPut**](docs/Api/RolesApi.md#apirolesidpermissionsput) | **PUT** /api/roles/{id}/permissions | *RolesApi* | [**apiRolesIdPermissionsPut**](docs/Api/RolesApi.md#apirolesidpermissionsput) | **PUT** /api/roles/{id}/permissions |
*RolesApi* | [**apiRolesPost**](docs/Api/RolesApi.md#apirolespost) | **POST** /api/roles | *RolesApi* | [**apiRolesPost**](docs/Api/RolesApi.md#apirolespost) | **POST** /api/roles |
@@ -5,6 +5,7 @@ All URIs are relative to http://localhost, except if the operation defines anoth
| Method | HTTP request | Description | | Method | HTTP request | Description |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| [**apiRolesGet()**](RolesApi.md#apiRolesGet) | **GET** /api/roles | | | [**apiRolesGet()**](RolesApi.md#apiRolesGet) | **GET** /api/roles | |
| [**apiRolesIdDelete()**](RolesApi.md#apiRolesIdDelete) | **DELETE** /api/roles/{id} | |
| [**apiRolesIdGet()**](RolesApi.md#apiRolesIdGet) | **GET** /api/roles/{id} | | | [**apiRolesIdGet()**](RolesApi.md#apiRolesIdGet) | **GET** /api/roles/{id} | |
| [**apiRolesIdPermissionsPut()**](RolesApi.md#apiRolesIdPermissionsPut) | **PUT** /api/roles/{id}/permissions | | | [**apiRolesIdPermissionsPut()**](RolesApi.md#apiRolesIdPermissionsPut) | **PUT** /api/roles/{id}/permissions | |
| [**apiRolesPost()**](RolesApi.md#apiRolesPost) | **POST** /api/roles | | | [**apiRolesPost()**](RolesApi.md#apiRolesPost) | **POST** /api/roles | |
@@ -65,6 +66,63 @@ This endpoint does not need any parameter.
[[Back to Model list]](../../README.md#models) [[Back to Model list]](../../README.md#models)
[[Back to README]](../../README.md) [[Back to README]](../../README.md)
## `apiRolesIdDelete()`
```php
apiRolesIdDelete($id)
```
### Example
```php
<?php
require_once(__DIR__ . '/vendor/autoload.php');
// Configure Bearer (JWT) authorization: Bearer
$config = OmsorgCoreClient\Configuration::getDefaultConfiguration()->setAccessToken('YOUR_ACCESS_TOKEN');
$apiInstance = new OmsorgCoreClient\Api\RolesApi(
// If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`.
// This is optional, `GuzzleHttp\Client` will be used as default.
new GuzzleHttp\Client(),
$config
);
$id = 'id_example'; // string
try {
$apiInstance->apiRolesIdDelete($id);
} catch (Exception $e) {
echo 'Exception when calling RolesApi->apiRolesIdDelete: ', $e->getMessage(), PHP_EOL;
}
```
### Parameters
| Name | Type | Description | Notes |
| ------------- | ------------- | ------------- | ------------- |
| **id** | **string**| | |
### Return type
void (empty response body)
### Authorization
[Bearer](../../README.md#Bearer)
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
[[Back to top]](#) [[Back to API list]](../../README.md#endpoints)
[[Back to Model list]](../../README.md#models)
[[Back to README]](../../README.md)
## `apiRolesIdGet()` ## `apiRolesIdGet()`
```php ```php
@@ -26,8 +26,8 @@ Name | Type | Description | Notes
**travel_cost_rate** | **float** | | [optional] **travel_cost_rate** | **float** | | [optional]
**travel_cost_mode** | **string** | | [optional] **travel_cost_mode** | **string** | | [optional]
**travel_cost_per_km** | **float** | | [optional] **travel_cost_per_km** | **float** | | [optional]
**meal_allowance_rate** | **float** | | [optional]
**minimum_hours** | **float** | | [optional] **minimum_hours** | **float** | | [optional]
**break_policy** | **string** | | [optional]
**billing_interval** | **string** | | [optional] **billing_interval** | **string** | | [optional]
**payment_term_days** | **int** | | [optional] **payment_term_days** | **int** | | [optional]
**individual_agreements** | **string** | | [optional] **individual_agreements** | **string** | | [optional]
@@ -25,8 +25,8 @@ Name | Type | Description | Notes
**travel_cost_rate** | **float** | | [optional] **travel_cost_rate** | **float** | | [optional]
**travel_cost_mode** | **string** | | [optional] **travel_cost_mode** | **string** | | [optional]
**travel_cost_per_km** | **float** | | [optional] **travel_cost_per_km** | **float** | | [optional]
**meal_allowance_rate** | **float** | | [optional]
**minimum_hours** | **float** | | [optional] **minimum_hours** | **float** | | [optional]
**break_policy** | **string** | | [optional]
**billing_interval** | **string** | | [optional] **billing_interval** | **string** | | [optional]
**payment_term_days** | **int** | | [optional] **payment_term_days** | **int** | | [optional]
**individual_agreements** | **string** | | [optional] **individual_agreements** | **string** | | [optional]
@@ -77,6 +77,9 @@ class RolesApi
'apiRolesGet' => [ 'apiRolesGet' => [
'application/json', 'application/json',
], ],
'apiRolesIdDelete' => [
'application/json',
],
'apiRolesIdGet' => [ 'apiRolesIdGet' => [
'application/json', 'application/json',
], ],
@@ -382,6 +385,220 @@ class RolesApi
); );
} }
/**
* Operation apiRolesIdDelete
*
* @param string $id id (required)
* @param string $contentType The value for the Content-Type header. Check self::contentTypes['apiRolesIdDelete'] to see the possible values for this operation
*
* @throws \OmsorgCoreClient\ApiException on non-2xx response or if the response body is not in the expected format
* @throws \InvalidArgumentException
* @return void
*/
public function apiRolesIdDelete($id, string $contentType = self::contentTypes['apiRolesIdDelete'][0])
{
$this->apiRolesIdDeleteWithHttpInfo($id, $contentType);
}
/**
* Operation apiRolesIdDeleteWithHttpInfo
*
* @param string $id (required)
* @param string $contentType The value for the Content-Type header. Check self::contentTypes['apiRolesIdDelete'] to see the possible values for this operation
*
* @throws \OmsorgCoreClient\ApiException on non-2xx response or if the response body is not in the expected format
* @throws \InvalidArgumentException
* @return array of null, HTTP status code, HTTP response headers (array of strings)
*/
public function apiRolesIdDeleteWithHttpInfo($id, string $contentType = self::contentTypes['apiRolesIdDelete'][0])
{
$request = $this->apiRolesIdDeleteRequest($id, $contentType);
try {
$options = $this->createHttpClientOption();
try {
$response = $this->client->send($request, $options);
} catch (RequestException $e) {
throw new ApiException(
"[{$e->getCode()}] {$e->getMessage()}",
(int) $e->getCode(),
$e->getResponse() ? $e->getResponse()->getHeaders() : null,
$e->getResponse() ? (string) $e->getResponse()->getBody() : null
);
} catch (ConnectException $e) {
throw new ApiException(
"[{$e->getCode()}] {$e->getMessage()}",
(int) $e->getCode(),
null,
null
);
}
$statusCode = $response->getStatusCode();
return [null, $statusCode, $response->getHeaders()];
} catch (ApiException $e) {
switch ($e->getCode()) {
}
throw $e;
}
}
/**
* Operation apiRolesIdDeleteAsync
*
* @param string $id (required)
* @param string $contentType The value for the Content-Type header. Check self::contentTypes['apiRolesIdDelete'] to see the possible values for this operation
*
* @throws \InvalidArgumentException
* @return \GuzzleHttp\Promise\PromiseInterface
*/
public function apiRolesIdDeleteAsync($id, string $contentType = self::contentTypes['apiRolesIdDelete'][0])
{
return $this->apiRolesIdDeleteAsyncWithHttpInfo($id, $contentType)
->then(
function ($response) {
return $response[0];
}
);
}
/**
* Operation apiRolesIdDeleteAsyncWithHttpInfo
*
* @param string $id (required)
* @param string $contentType The value for the Content-Type header. Check self::contentTypes['apiRolesIdDelete'] to see the possible values for this operation
*
* @throws \InvalidArgumentException
* @return \GuzzleHttp\Promise\PromiseInterface
*/
public function apiRolesIdDeleteAsyncWithHttpInfo($id, string $contentType = self::contentTypes['apiRolesIdDelete'][0])
{
$returnType = '';
$request = $this->apiRolesIdDeleteRequest($id, $contentType);
return $this->client
->sendAsync($request, $this->createHttpClientOption())
->then(
function ($response) use ($returnType) {
return [null, $response->getStatusCode(), $response->getHeaders()];
},
function ($exception) {
$response = $exception->getResponse();
$statusCode = $response->getStatusCode();
throw new ApiException(
sprintf(
'[%d] Error connecting to the API (%s)',
$statusCode,
$exception->getRequest()->getUri()
),
$statusCode,
$response->getHeaders(),
(string) $response->getBody()
);
}
);
}
/**
* Create request for operation 'apiRolesIdDelete'
*
* @param string $id (required)
* @param string $contentType The value for the Content-Type header. Check self::contentTypes['apiRolesIdDelete'] to see the possible values for this operation
*
* @throws \InvalidArgumentException
* @return \GuzzleHttp\Psr7\Request
*/
public function apiRolesIdDeleteRequest($id, string $contentType = self::contentTypes['apiRolesIdDelete'][0])
{
// verify the required parameter 'id' is set
if ($id === null || (is_array($id) && count($id) === 0)) {
throw new \InvalidArgumentException(
'Missing the required parameter $id when calling apiRolesIdDelete'
);
}
$resourcePath = '/api/roles/{id}';
$formParams = [];
$queryParams = [];
$headerParams = [];
$httpBody = '';
$multipart = false;
// path params
if ($id !== null) {
$resourcePath = str_replace(
'{' . 'id' . '}',
ObjectSerializer::toPathValue($id),
$resourcePath
);
}
$headers = $this->headerSelector->selectHeaders(
[],
$contentType,
$multipart
);
// for model (json/xml)
if (count($formParams) > 0) {
if ($multipart) {
$multipartContents = [];
foreach ($formParams as $formParamName => $formParamValue) {
$formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
foreach ($formParamValueItems as $formParamValueItem) {
$multipartContents[] = [
'name' => $formParamName,
'contents' => $formParamValueItem
];
}
}
// for HTTP post (form)
$httpBody = new MultipartStream($multipartContents);
} elseif (stripos($headers['Content-Type'], 'application/json') !== false) {
# if Content-Type contains "application/json", json_encode the form parameters
$httpBody = \GuzzleHttp\Utils::jsonEncode($formParams);
} else {
// for HTTP post (form)
$httpBody = ObjectSerializer::buildQuery($formParams);
}
}
// this endpoint requires Bearer (JWT) authentication (access token)
if (!empty($this->config->getAccessToken())) {
$headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
}
$defaultHeaders = [];
if ($this->config->getUserAgent()) {
$defaultHeaders['User-Agent'] = $this->config->getUserAgent();
}
$headers = array_merge(
$defaultHeaders,
$headerParams,
$headers
);
$operationHost = $this->config->getHost();
$query = ObjectSerializer::buildQuery($queryParams);
return new Request(
'DELETE',
$operationHost . $resourcePath . ($query ? "?{$query}" : ''),
$headers,
$httpBody
);
}
/** /**
* Operation apiRolesIdGet * Operation apiRolesIdGet
* *
@@ -79,8 +79,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => 'float', 'travel_cost_rate' => 'float',
'travel_cost_mode' => 'string', 'travel_cost_mode' => 'string',
'travel_cost_per_km' => 'float', 'travel_cost_per_km' => 'float',
'meal_allowance_rate' => 'float',
'minimum_hours' => 'float', 'minimum_hours' => 'float',
'break_policy' => 'string',
'billing_interval' => 'string', 'billing_interval' => 'string',
'payment_term_days' => 'int', 'payment_term_days' => 'int',
'individual_agreements' => 'string' 'individual_agreements' => 'string'
@@ -116,8 +116,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => 'double', 'travel_cost_rate' => 'double',
'travel_cost_mode' => null, 'travel_cost_mode' => null,
'travel_cost_per_km' => 'double', 'travel_cost_per_km' => 'double',
'meal_allowance_rate' => 'double',
'minimum_hours' => 'double', 'minimum_hours' => 'double',
'break_policy' => null,
'billing_interval' => null, 'billing_interval' => null,
'payment_term_days' => 'int32', 'payment_term_days' => 'int32',
'individual_agreements' => null 'individual_agreements' => null
@@ -151,8 +151,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => true, 'travel_cost_rate' => true,
'travel_cost_mode' => true, 'travel_cost_mode' => true,
'travel_cost_per_km' => true, 'travel_cost_per_km' => true,
'meal_allowance_rate' => true,
'minimum_hours' => true, 'minimum_hours' => true,
'break_policy' => true,
'billing_interval' => true, 'billing_interval' => true,
'payment_term_days' => true, 'payment_term_days' => true,
'individual_agreements' => true 'individual_agreements' => true
@@ -266,8 +266,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => 'travelCostRate', 'travel_cost_rate' => 'travelCostRate',
'travel_cost_mode' => 'travelCostMode', 'travel_cost_mode' => 'travelCostMode',
'travel_cost_per_km' => 'travelCostPerKm', 'travel_cost_per_km' => 'travelCostPerKm',
'meal_allowance_rate' => 'mealAllowanceRate',
'minimum_hours' => 'minimumHours', 'minimum_hours' => 'minimumHours',
'break_policy' => 'breakPolicy',
'billing_interval' => 'billingInterval', 'billing_interval' => 'billingInterval',
'payment_term_days' => 'paymentTermDays', 'payment_term_days' => 'paymentTermDays',
'individual_agreements' => 'individualAgreements' 'individual_agreements' => 'individualAgreements'
@@ -301,8 +301,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => 'setTravelCostRate', 'travel_cost_rate' => 'setTravelCostRate',
'travel_cost_mode' => 'setTravelCostMode', 'travel_cost_mode' => 'setTravelCostMode',
'travel_cost_per_km' => 'setTravelCostPerKm', 'travel_cost_per_km' => 'setTravelCostPerKm',
'meal_allowance_rate' => 'setMealAllowanceRate',
'minimum_hours' => 'setMinimumHours', 'minimum_hours' => 'setMinimumHours',
'break_policy' => 'setBreakPolicy',
'billing_interval' => 'setBillingInterval', 'billing_interval' => 'setBillingInterval',
'payment_term_days' => 'setPaymentTermDays', 'payment_term_days' => 'setPaymentTermDays',
'individual_agreements' => 'setIndividualAgreements' 'individual_agreements' => 'setIndividualAgreements'
@@ -336,8 +336,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
'travel_cost_rate' => 'getTravelCostRate', 'travel_cost_rate' => 'getTravelCostRate',
'travel_cost_mode' => 'getTravelCostMode', 'travel_cost_mode' => 'getTravelCostMode',
'travel_cost_per_km' => 'getTravelCostPerKm', 'travel_cost_per_km' => 'getTravelCostPerKm',
'meal_allowance_rate' => 'getMealAllowanceRate',
'minimum_hours' => 'getMinimumHours', 'minimum_hours' => 'getMinimumHours',
'break_policy' => 'getBreakPolicy',
'billing_interval' => 'getBillingInterval', 'billing_interval' => 'getBillingInterval',
'payment_term_days' => 'getPaymentTermDays', 'payment_term_days' => 'getPaymentTermDays',
'individual_agreements' => 'getIndividualAgreements' 'individual_agreements' => 'getIndividualAgreements'
@@ -422,8 +422,8 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
$this->setIfExists('travel_cost_rate', $data ?? [], null); $this->setIfExists('travel_cost_rate', $data ?? [], null);
$this->setIfExists('travel_cost_mode', $data ?? [], null); $this->setIfExists('travel_cost_mode', $data ?? [], null);
$this->setIfExists('travel_cost_per_km', $data ?? [], null); $this->setIfExists('travel_cost_per_km', $data ?? [], null);
$this->setIfExists('meal_allowance_rate', $data ?? [], null);
$this->setIfExists('minimum_hours', $data ?? [], null); $this->setIfExists('minimum_hours', $data ?? [], null);
$this->setIfExists('break_policy', $data ?? [], null);
$this->setIfExists('billing_interval', $data ?? [], null); $this->setIfExists('billing_interval', $data ?? [], null);
$this->setIfExists('payment_term_days', $data ?? [], null); $this->setIfExists('payment_term_days', $data ?? [], null);
$this->setIfExists('individual_agreements', $data ?? [], null); $this->setIfExists('individual_agreements', $data ?? [], null);
@@ -1212,6 +1212,40 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
return $this; return $this;
} }
/**
* Gets meal_allowance_rate
*
* @return float|null
*/
public function getMealAllowanceRate()
{
return $this->container['meal_allowance_rate'];
}
/**
* Sets meal_allowance_rate
*
* @param float|null $meal_allowance_rate meal_allowance_rate
*
* @return self
*/
public function setMealAllowanceRate($meal_allowance_rate)
{
if (is_null($meal_allowance_rate)) {
array_push($this->openAPINullablesSetToNull, 'meal_allowance_rate');
} else {
$nullablesSetToNull = $this->getOpenAPINullablesSetToNull();
$index = array_search('meal_allowance_rate', $nullablesSetToNull);
if ($index !== FALSE) {
unset($nullablesSetToNull[$index]);
$this->setOpenAPINullablesSetToNull($nullablesSetToNull);
}
}
$this->container['meal_allowance_rate'] = $meal_allowance_rate;
return $this;
}
/** /**
* Gets minimum_hours * Gets minimum_hours
* *
@@ -1246,40 +1280,6 @@ class FacilityResponse implements ModelInterface, ArrayAccess, \JsonSerializable
return $this; return $this;
} }
/**
* Gets break_policy
*
* @return string|null
*/
public function getBreakPolicy()
{
return $this->container['break_policy'];
}
/**
* Sets break_policy
*
* @param string|null $break_policy break_policy
*
* @return self
*/
public function setBreakPolicy($break_policy)
{
if (is_null($break_policy)) {
array_push($this->openAPINullablesSetToNull, 'break_policy');
} else {
$nullablesSetToNull = $this->getOpenAPINullablesSetToNull();
$index = array_search('break_policy', $nullablesSetToNull);
if ($index !== FALSE) {
unset($nullablesSetToNull[$index]);
$this->setOpenAPINullablesSetToNull($nullablesSetToNull);
}
}
$this->container['break_policy'] = $break_policy;
return $this;
}
/** /**
* Gets billing_interval * Gets billing_interval
* *
@@ -78,8 +78,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => 'float', 'travel_cost_rate' => 'float',
'travel_cost_mode' => 'string', 'travel_cost_mode' => 'string',
'travel_cost_per_km' => 'float', 'travel_cost_per_km' => 'float',
'meal_allowance_rate' => 'float',
'minimum_hours' => 'float', 'minimum_hours' => 'float',
'break_policy' => 'string',
'billing_interval' => 'string', 'billing_interval' => 'string',
'payment_term_days' => 'int', 'payment_term_days' => 'int',
'individual_agreements' => 'string' 'individual_agreements' => 'string'
@@ -114,8 +114,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => 'double', 'travel_cost_rate' => 'double',
'travel_cost_mode' => null, 'travel_cost_mode' => null,
'travel_cost_per_km' => 'double', 'travel_cost_per_km' => 'double',
'meal_allowance_rate' => 'double',
'minimum_hours' => 'double', 'minimum_hours' => 'double',
'break_policy' => null,
'billing_interval' => null, 'billing_interval' => null,
'payment_term_days' => 'int32', 'payment_term_days' => 'int32',
'individual_agreements' => null 'individual_agreements' => null
@@ -148,8 +148,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => true, 'travel_cost_rate' => true,
'travel_cost_mode' => true, 'travel_cost_mode' => true,
'travel_cost_per_km' => true, 'travel_cost_per_km' => true,
'meal_allowance_rate' => true,
'minimum_hours' => true, 'minimum_hours' => true,
'break_policy' => true,
'billing_interval' => true, 'billing_interval' => true,
'payment_term_days' => true, 'payment_term_days' => true,
'individual_agreements' => true 'individual_agreements' => true
@@ -262,8 +262,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => 'travelCostRate', 'travel_cost_rate' => 'travelCostRate',
'travel_cost_mode' => 'travelCostMode', 'travel_cost_mode' => 'travelCostMode',
'travel_cost_per_km' => 'travelCostPerKm', 'travel_cost_per_km' => 'travelCostPerKm',
'meal_allowance_rate' => 'mealAllowanceRate',
'minimum_hours' => 'minimumHours', 'minimum_hours' => 'minimumHours',
'break_policy' => 'breakPolicy',
'billing_interval' => 'billingInterval', 'billing_interval' => 'billingInterval',
'payment_term_days' => 'paymentTermDays', 'payment_term_days' => 'paymentTermDays',
'individual_agreements' => 'individualAgreements' 'individual_agreements' => 'individualAgreements'
@@ -296,8 +296,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => 'setTravelCostRate', 'travel_cost_rate' => 'setTravelCostRate',
'travel_cost_mode' => 'setTravelCostMode', 'travel_cost_mode' => 'setTravelCostMode',
'travel_cost_per_km' => 'setTravelCostPerKm', 'travel_cost_per_km' => 'setTravelCostPerKm',
'meal_allowance_rate' => 'setMealAllowanceRate',
'minimum_hours' => 'setMinimumHours', 'minimum_hours' => 'setMinimumHours',
'break_policy' => 'setBreakPolicy',
'billing_interval' => 'setBillingInterval', 'billing_interval' => 'setBillingInterval',
'payment_term_days' => 'setPaymentTermDays', 'payment_term_days' => 'setPaymentTermDays',
'individual_agreements' => 'setIndividualAgreements' 'individual_agreements' => 'setIndividualAgreements'
@@ -330,8 +330,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
'travel_cost_rate' => 'getTravelCostRate', 'travel_cost_rate' => 'getTravelCostRate',
'travel_cost_mode' => 'getTravelCostMode', 'travel_cost_mode' => 'getTravelCostMode',
'travel_cost_per_km' => 'getTravelCostPerKm', 'travel_cost_per_km' => 'getTravelCostPerKm',
'meal_allowance_rate' => 'getMealAllowanceRate',
'minimum_hours' => 'getMinimumHours', 'minimum_hours' => 'getMinimumHours',
'break_policy' => 'getBreakPolicy',
'billing_interval' => 'getBillingInterval', 'billing_interval' => 'getBillingInterval',
'payment_term_days' => 'getPaymentTermDays', 'payment_term_days' => 'getPaymentTermDays',
'individual_agreements' => 'getIndividualAgreements' 'individual_agreements' => 'getIndividualAgreements'
@@ -415,8 +415,8 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
$this->setIfExists('travel_cost_rate', $data ?? [], null); $this->setIfExists('travel_cost_rate', $data ?? [], null);
$this->setIfExists('travel_cost_mode', $data ?? [], null); $this->setIfExists('travel_cost_mode', $data ?? [], null);
$this->setIfExists('travel_cost_per_km', $data ?? [], null); $this->setIfExists('travel_cost_per_km', $data ?? [], null);
$this->setIfExists('meal_allowance_rate', $data ?? [], null);
$this->setIfExists('minimum_hours', $data ?? [], null); $this->setIfExists('minimum_hours', $data ?? [], null);
$this->setIfExists('break_policy', $data ?? [], null);
$this->setIfExists('billing_interval', $data ?? [], null); $this->setIfExists('billing_interval', $data ?? [], null);
$this->setIfExists('payment_term_days', $data ?? [], null); $this->setIfExists('payment_term_days', $data ?? [], null);
$this->setIfExists('individual_agreements', $data ?? [], null); $this->setIfExists('individual_agreements', $data ?? [], null);
@@ -1178,6 +1178,40 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
return $this; return $this;
} }
/**
* Gets meal_allowance_rate
*
* @return float|null
*/
public function getMealAllowanceRate()
{
return $this->container['meal_allowance_rate'];
}
/**
* Sets meal_allowance_rate
*
* @param float|null $meal_allowance_rate meal_allowance_rate
*
* @return self
*/
public function setMealAllowanceRate($meal_allowance_rate)
{
if (is_null($meal_allowance_rate)) {
array_push($this->openAPINullablesSetToNull, 'meal_allowance_rate');
} else {
$nullablesSetToNull = $this->getOpenAPINullablesSetToNull();
$index = array_search('meal_allowance_rate', $nullablesSetToNull);
if ($index !== FALSE) {
unset($nullablesSetToNull[$index]);
$this->setOpenAPINullablesSetToNull($nullablesSetToNull);
}
}
$this->container['meal_allowance_rate'] = $meal_allowance_rate;
return $this;
}
/** /**
* Gets minimum_hours * Gets minimum_hours
* *
@@ -1212,40 +1246,6 @@ class UpdateFacilityRequest implements ModelInterface, ArrayAccess, \JsonSeriali
return $this; return $this;
} }
/**
* Gets break_policy
*
* @return string|null
*/
public function getBreakPolicy()
{
return $this->container['break_policy'];
}
/**
* Sets break_policy
*
* @param string|null $break_policy break_policy
*
* @return self
*/
public function setBreakPolicy($break_policy)
{
if (is_null($break_policy)) {
array_push($this->openAPINullablesSetToNull, 'break_policy');
} else {
$nullablesSetToNull = $this->getOpenAPINullablesSetToNull();
$index = array_search('break_policy', $nullablesSetToNull);
if ($index !== FALSE) {
unset($nullablesSetToNull[$index]);
$this->setOpenAPINullablesSetToNull($nullablesSetToNull);
}
}
$this->container['break_policy'] = $break_policy;
return $this;
}
/** /**
* Gets billing_interval * Gets billing_interval
* *
@@ -156,13 +156,13 @@ export interface FacilityResponse {
* @type {number} * @type {number}
* @memberof FacilityResponse * @memberof FacilityResponse
*/ */
minimumHours?: number | null; mealAllowanceRate?: number | null;
/** /**
* *
* @type {string} * @type {number}
* @memberof FacilityResponse * @memberof FacilityResponse
*/ */
breakPolicy?: string | null; minimumHours?: number | null;
/** /**
* *
* @type {string} * @type {string}
@@ -222,8 +222,8 @@ export function FacilityResponseFromJSONTyped(json: any, ignoreDiscriminator: bo
'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'], 'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'],
'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'], 'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'],
'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'], 'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'],
'mealAllowanceRate': json['mealAllowanceRate'] == null ? undefined : json['mealAllowanceRate'],
'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'], 'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'],
'breakPolicy': json['breakPolicy'] == null ? undefined : json['breakPolicy'],
'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'], 'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'],
'paymentTermDays': json['paymentTermDays'] == null ? undefined : json['paymentTermDays'], 'paymentTermDays': json['paymentTermDays'] == null ? undefined : json['paymentTermDays'],
'individualAgreements': json['individualAgreements'] == null ? undefined : json['individualAgreements'], 'individualAgreements': json['individualAgreements'] == null ? undefined : json['individualAgreements'],
@@ -263,8 +263,8 @@ export function FacilityResponseToJSONTyped(value?: FacilityResponse | null, ign
'travelCostRate': value['travelCostRate'], 'travelCostRate': value['travelCostRate'],
'travelCostMode': value['travelCostMode'], 'travelCostMode': value['travelCostMode'],
'travelCostPerKm': value['travelCostPerKm'], 'travelCostPerKm': value['travelCostPerKm'],
'mealAllowanceRate': value['mealAllowanceRate'],
'minimumHours': value['minimumHours'], 'minimumHours': value['minimumHours'],
'breakPolicy': value['breakPolicy'],
'billingInterval': value['billingInterval'], 'billingInterval': value['billingInterval'],
'paymentTermDays': value['paymentTermDays'], 'paymentTermDays': value['paymentTermDays'],
'individualAgreements': value['individualAgreements'], 'individualAgreements': value['individualAgreements'],
@@ -150,13 +150,13 @@ export interface UpdateFacilityRequest {
* @type {number} * @type {number}
* @memberof UpdateFacilityRequest * @memberof UpdateFacilityRequest
*/ */
minimumHours?: number | null; mealAllowanceRate?: number | null;
/** /**
* *
* @type {string} * @type {number}
* @memberof UpdateFacilityRequest * @memberof UpdateFacilityRequest
*/ */
breakPolicy?: string | null; minimumHours?: number | null;
/** /**
* *
* @type {string} * @type {string}
@@ -215,8 +215,8 @@ export function UpdateFacilityRequestFromJSONTyped(json: any, ignoreDiscriminato
'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'], 'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'],
'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'], 'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'],
'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'], 'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'],
'mealAllowanceRate': json['mealAllowanceRate'] == null ? undefined : json['mealAllowanceRate'],
'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'], 'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'],
'breakPolicy': json['breakPolicy'] == null ? undefined : json['breakPolicy'],
'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'], 'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'],
'paymentTermDays': json['paymentTermDays'] == null ? undefined : json['paymentTermDays'], 'paymentTermDays': json['paymentTermDays'] == null ? undefined : json['paymentTermDays'],
'individualAgreements': json['individualAgreements'] == null ? undefined : json['individualAgreements'], 'individualAgreements': json['individualAgreements'] == null ? undefined : json['individualAgreements'],
@@ -255,8 +255,8 @@ export function UpdateFacilityRequestToJSONTyped(value?: UpdateFacilityRequest |
'travelCostRate': value['travelCostRate'], 'travelCostRate': value['travelCostRate'],
'travelCostMode': value['travelCostMode'], 'travelCostMode': value['travelCostMode'],
'travelCostPerKm': value['travelCostPerKm'], 'travelCostPerKm': value['travelCostPerKm'],
'mealAllowanceRate': value['mealAllowanceRate'],
'minimumHours': value['minimumHours'], 'minimumHours': value['minimumHours'],
'breakPolicy': value['breakPolicy'],
'billingInterval': value['billingInterval'], 'billingInterval': value['billingInterval'],
'paymentTermDays': value['paymentTermDays'], 'paymentTermDays': value['paymentTermDays'],
'individualAgreements': value['individualAgreements'], 'individualAgreements': value['individualAgreements'],
@@ -151,13 +151,13 @@ export default function FacilityDetailPanel({ facility, onUpdated }) {
</div> </div>
<div> <div>
<strong>Mindeststunden</strong> <strong>Verpflegungsmehraufwand</strong>
<p>{facility.minimumHours ?? "—"}</p> <p>{facility.mealAllowanceRate != null ? `${facility.mealAllowanceRate} EUR (Pauschale je Einsatz)` : "—"}</p>
</div> </div>
<div> <div>
<strong>Pausenregelung</strong> <strong>Mindeststunden</strong>
<p>{facility.breakPolicy ?? "—"}</p> <p>{facility.minimumHours ?? "—"}</p>
</div> </div>
<div> <div>
@@ -24,8 +24,8 @@ export const emptyFacilityForm = {
travelCostMode: "Pauschale", travelCostMode: "Pauschale",
travelCostRate: "", travelCostRate: "",
travelCostPerKm: "", travelCostPerKm: "",
mealAllowanceRate: "",
minimumHours: "", minimumHours: "",
breakPolicy: "",
billingInterval: "", billingInterval: "",
paymentTermDays: "", paymentTermDays: "",
individualAgreements: "", individualAgreements: "",
@@ -53,8 +53,8 @@ export function facilityToFormValues(facility) {
travelCostMode: facility.travelCostMode ?? "Pauschale", travelCostMode: facility.travelCostMode ?? "Pauschale",
travelCostRate: facility.travelCostRate ?? "", travelCostRate: facility.travelCostRate ?? "",
travelCostPerKm: facility.travelCostPerKm ?? "", travelCostPerKm: facility.travelCostPerKm ?? "",
mealAllowanceRate: facility.mealAllowanceRate ?? "",
minimumHours: facility.minimumHours ?? "", minimumHours: facility.minimumHours ?? "",
breakPolicy: facility.breakPolicy ?? "",
billingInterval: facility.billingInterval ?? "", billingInterval: facility.billingInterval ?? "",
paymentTermDays: facility.paymentTermDays ?? "", paymentTermDays: facility.paymentTermDays ?? "",
individualAgreements: facility.individualAgreements ?? "", individualAgreements: facility.individualAgreements ?? "",
@@ -87,8 +87,8 @@ export function facilityFormToPayload(form, { includeCrmStatus = false, followUp
payload.travelCostMode = form.travelCostMode || "Pauschale"; payload.travelCostMode = form.travelCostMode || "Pauschale";
payload.travelCostRate = form.travelCostRate === "" ? null : Number(form.travelCostRate); payload.travelCostRate = form.travelCostRate === "" ? null : Number(form.travelCostRate);
payload.travelCostPerKm = form.travelCostPerKm === "" ? null : Number(form.travelCostPerKm); payload.travelCostPerKm = form.travelCostPerKm === "" ? null : Number(form.travelCostPerKm);
payload.mealAllowanceRate = form.mealAllowanceRate === "" ? null : Number(form.mealAllowanceRate);
payload.minimumHours = form.minimumHours === "" ? null : Number(form.minimumHours); payload.minimumHours = form.minimumHours === "" ? null : Number(form.minimumHours);
payload.breakPolicy = form.breakPolicy.trim() || null;
payload.billingInterval = form.billingInterval || null; payload.billingInterval = form.billingInterval || null;
payload.paymentTermDays = form.paymentTermDays === "" ? null : Number(form.paymentTermDays); payload.paymentTermDays = form.paymentTermDays === "" ? null : Number(form.paymentTermDays);
payload.individualAgreements = form.individualAgreements.trim() || null; payload.individualAgreements = form.individualAgreements.trim() || null;
@@ -282,10 +282,12 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
)} )}
</div> </div>
<div className="form-row">
<label className="form-field"> <label className="form-field">
<span>Pausenregelung</span> <span>Verpflegungsmehraufwand (EUR, Pauschale je Einsatz)</span>
<input value={form.breakPolicy} onChange={updateField("breakPolicy")} /> <input type="number" min="0" step="0.01" value={form.mealAllowanceRate} onChange={updateField("mealAllowanceRate")} />
</label> </label>
</div>
<div className="form-row"> <div className="form-row">
<label className="form-field"> <label className="form-field">