Add kilometer-based Fahrtkosten billing, self-service distance entry, role deletion
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 16s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Successful in 5s
Docker-Images bauen und veröffentlichen / build (, omsorgapp/Dockerfile, omsorgapp) (push) Successful in 19s

- Facility: TravelCostMode (Pauschale/ProKilometer) + TravelCostPerKm, alongside
  the existing flat rate; fixes FacilityService.UpdateAsync silently dropping all
  Konditionen fields on update.
- New EmployeeFacilityDistance (Mitarbeiter x Einrichtung -> km) with full
  office-side CRUD in omsorgapp, plus a self-service endpoint/UI so field staff
  can maintain their own commute distance via OMSORG Connect (new
  ModuleType.EmployeeFacilityDistances, Own-scope, no Facilities access needed).
- Roles can now be deleted (blocked with a 409 while still assigned to a user).
- Fix employeesApi.js missing the Date-object conversion for dateOfBirth/entryDate/
  exitDate that crashed employee creation whenever a date was filled in; add a
  clear/remove control for those date fields.
- Requirements: flesh out FR-REC-3 with a staged Akquise cadence, add FR-REC-5/6
  for CRM feature scope and success metrics.
- Regenerate api-client-ts and api-client-php for all of the above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Felix Kemmler
2026-08-10 20:15:42 +02:00
co-authored by Claude Sonnet 5
parent 09dce2ab98
commit ffa2c4a9e7
120 changed files with 13433 additions and 36 deletions
+4 -4
View File
File diff suppressed because one or more lines are too long
@@ -9,11 +9,13 @@ src/apis/AuditLogApi.ts
src/apis/AuthApi.ts
src/apis/ContractsApi.ts
src/apis/DocumentsApi.ts
src/apis/EmployeeFacilityDistancesApi.ts
src/apis/EmployeesApi.ts
src/apis/FacilitiesApi.ts
src/apis/FacilityContactsApi.ts
src/apis/FacilityQualificationRatesApi.ts
src/apis/HealthApi.ts
src/apis/MyFacilityDistancesApi.ts
src/apis/OrdersApi.ts
src/apis/RolesApi.ts
src/apis/TimeEntriesApi.ts
@@ -34,19 +36,23 @@ src/models/ContractResponse.ts
src/models/ContractResponsePagedResponse.ts
src/models/CreateAbsenceRequest.ts
src/models/CreateContractRequest.ts
src/models/CreateEmployeeFacilityDistanceRequest.ts
src/models/CreateEmployeeRequest.ts
src/models/CreateFacilityContactRequest.ts
src/models/CreateFacilityQualificationRateRequest.ts
src/models/CreateFacilityRequest.ts
src/models/CreateMyFacilityDistanceRequest.ts
src/models/CreateOrderRequest.ts
src/models/CreateRoleRequest.ts
src/models/CreateTimeEntryRequest.ts
src/models/CreateUserRequest.ts
src/models/CreateValueListItemRequest.ts
src/models/DocumentResponse.ts
src/models/EmployeeFacilityDistanceResponse.ts
src/models/EmployeeResponse.ts
src/models/EmployeeResponsePagedResponse.ts
src/models/FacilityContactResponse.ts
src/models/FacilityOptionResponse.ts
src/models/FacilityQualificationRateResponse.ts
src/models/FacilityResponse.ts
src/models/FacilityResponsePagedResponse.ts
@@ -60,6 +66,7 @@ src/models/LoginResponse.ts
src/models/LogoutRequest.ts
src/models/MeResponse.ts
src/models/ModuleType.ts
src/models/MyFacilityDistanceResponse.ts
src/models/OrderResponse.ts
src/models/OrderResponsePagedResponse.ts
src/models/PasswordPolicyResponse.ts
@@ -79,6 +86,7 @@ src/models/TimeEntryResponse.ts
src/models/TimeEntryResponsePagedResponse.ts
src/models/TrashAbsenceResponse.ts
src/models/TrashContractResponse.ts
src/models/TrashEmployeeFacilityDistanceResponse.ts
src/models/TrashEmployeeResponse.ts
src/models/TrashFacilityContactResponse.ts
src/models/TrashFacilityQualificationRateResponse.ts
@@ -88,10 +96,12 @@ src/models/TrashTimeEntryResponse.ts
src/models/UpdateAbsenceRequest.ts
src/models/UpdateContractRequest.ts
src/models/UpdateDocumentRequest.ts
src/models/UpdateEmployeeFacilityDistanceRequest.ts
src/models/UpdateEmployeeRequest.ts
src/models/UpdateFacilityContactRequest.ts
src/models/UpdateFacilityQualificationRateRequest.ts
src/models/UpdateFacilityRequest.ts
src/models/UpdateMyFacilityDistanceRequest.ts
src/models/UpdateOrderRequest.ts
src/models/UpdateRolePermissionsRequest.ts
src/models/UpdateTimeEntryRequest.ts
@@ -0,0 +1,249 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
CreateEmployeeFacilityDistanceRequest,
EmployeeFacilityDistanceResponse,
UpdateEmployeeFacilityDistanceRequest,
} from '../models/index';
import {
CreateEmployeeFacilityDistanceRequestFromJSON,
CreateEmployeeFacilityDistanceRequestToJSON,
EmployeeFacilityDistanceResponseFromJSON,
EmployeeFacilityDistanceResponseToJSON,
UpdateEmployeeFacilityDistanceRequestFromJSON,
UpdateEmployeeFacilityDistanceRequestToJSON,
} from '../models/index';
export interface ApiFacilitiesFacilityIdEmployeeDistancesGetRequest {
facilityId: string;
}
export interface ApiFacilitiesFacilityIdEmployeeDistancesIdDeleteRequest {
facilityId: string;
id: string;
}
export interface ApiFacilitiesFacilityIdEmployeeDistancesIdPutRequest {
facilityId: string;
id: string;
updateEmployeeFacilityDistanceRequest?: UpdateEmployeeFacilityDistanceRequest;
}
export interface ApiFacilitiesFacilityIdEmployeeDistancesPostRequest {
facilityId: string;
createEmployeeFacilityDistanceRequest?: CreateEmployeeFacilityDistanceRequest;
}
/**
*
*/
export class EmployeeFacilityDistancesApi extends runtime.BaseAPI {
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesGetRaw(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<EmployeeFacilityDistanceResponse>>> {
if (requestParameters['facilityId'] == null) {
throw new runtime.RequiredError(
'facilityId',
'Required parameter "facilityId" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesGet().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/facilities/{facilityId}/employee-distances`;
urlPath = urlPath.replace(`{${"facilityId"}}`, encodeURIComponent(String(requestParameters['facilityId'])));
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(EmployeeFacilityDistanceResponseFromJSON));
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesGet(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<EmployeeFacilityDistanceResponse>> {
const response = await this.apiFacilitiesFacilityIdEmployeeDistancesGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesIdDeleteRaw(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesIdDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters['facilityId'] == null) {
throw new runtime.RequiredError(
'facilityId',
'Required parameter "facilityId" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesIdDelete().'
);
}
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesIdDelete().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/facilities/{facilityId}/employee-distances/{id}`;
urlPath = urlPath.replace(`{${"facilityId"}}`, encodeURIComponent(String(requestParameters['facilityId'])));
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id'])));
const response = await this.request({
path: urlPath,
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesIdDelete(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesIdDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.apiFacilitiesFacilityIdEmployeeDistancesIdDeleteRaw(requestParameters, initOverrides);
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesIdPutRaw(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesIdPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<EmployeeFacilityDistanceResponse>> {
if (requestParameters['facilityId'] == null) {
throw new runtime.RequiredError(
'facilityId',
'Required parameter "facilityId" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesIdPut().'
);
}
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesIdPut().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/facilities/{facilityId}/employee-distances/{id}`;
urlPath = urlPath.replace(`{${"facilityId"}}`, encodeURIComponent(String(requestParameters['facilityId'])));
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id'])));
const response = await this.request({
path: urlPath,
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: UpdateEmployeeFacilityDistanceRequestToJSON(requestParameters['updateEmployeeFacilityDistanceRequest']),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => EmployeeFacilityDistanceResponseFromJSON(jsonValue));
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesIdPut(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesIdPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EmployeeFacilityDistanceResponse> {
const response = await this.apiFacilitiesFacilityIdEmployeeDistancesIdPutRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesPostRaw(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<EmployeeFacilityDistanceResponse>> {
if (requestParameters['facilityId'] == null) {
throw new runtime.RequiredError(
'facilityId',
'Required parameter "facilityId" was null or undefined when calling apiFacilitiesFacilityIdEmployeeDistancesPost().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/facilities/{facilityId}/employee-distances`;
urlPath = urlPath.replace(`{${"facilityId"}}`, encodeURIComponent(String(requestParameters['facilityId'])));
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: CreateEmployeeFacilityDistanceRequestToJSON(requestParameters['createEmployeeFacilityDistanceRequest']),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => EmployeeFacilityDistanceResponseFromJSON(jsonValue));
}
/**
*/
async apiFacilitiesFacilityIdEmployeeDistancesPost(requestParameters: ApiFacilitiesFacilityIdEmployeeDistancesPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<EmployeeFacilityDistanceResponse> {
const response = await this.apiFacilitiesFacilityIdEmployeeDistancesPostRaw(requestParameters, initOverrides);
return await response.value();
}
}
@@ -0,0 +1,202 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
CreateMyFacilityDistanceRequest,
FacilityOptionResponse,
MyFacilityDistanceResponse,
UpdateMyFacilityDistanceRequest,
} from '../models/index';
import {
CreateMyFacilityDistanceRequestFromJSON,
CreateMyFacilityDistanceRequestToJSON,
FacilityOptionResponseFromJSON,
FacilityOptionResponseToJSON,
MyFacilityDistanceResponseFromJSON,
MyFacilityDistanceResponseToJSON,
UpdateMyFacilityDistanceRequestFromJSON,
UpdateMyFacilityDistanceRequestToJSON,
} from '../models/index';
export interface ApiMeFacilityDistancesIdPutRequest {
id: string;
updateMyFacilityDistanceRequest?: UpdateMyFacilityDistanceRequest;
}
export interface ApiMeFacilityDistancesPostRequest {
createMyFacilityDistanceRequest?: CreateMyFacilityDistanceRequest;
}
/**
*
*/
export class MyFacilityDistancesApi extends runtime.BaseAPI {
/**
*/
async apiMeFacilityDistancesFacilitiesGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<FacilityOptionResponse>>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/me/facility-distances/facilities`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(FacilityOptionResponseFromJSON));
}
/**
*/
async apiMeFacilityDistancesFacilitiesGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<FacilityOptionResponse>> {
const response = await this.apiMeFacilityDistancesFacilitiesGetRaw(initOverrides);
return await response.value();
}
/**
*/
async apiMeFacilityDistancesGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<MyFacilityDistanceResponse>>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/me/facility-distances`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(MyFacilityDistanceResponseFromJSON));
}
/**
*/
async apiMeFacilityDistancesGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<MyFacilityDistanceResponse>> {
const response = await this.apiMeFacilityDistancesGetRaw(initOverrides);
return await response.value();
}
/**
*/
async apiMeFacilityDistancesIdPutRaw(requestParameters: ApiMeFacilityDistancesIdPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<MyFacilityDistanceResponse>> {
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiMeFacilityDistancesIdPut().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/me/facility-distances/{id}`;
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id'])));
const response = await this.request({
path: urlPath,
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: UpdateMyFacilityDistanceRequestToJSON(requestParameters['updateMyFacilityDistanceRequest']),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => MyFacilityDistanceResponseFromJSON(jsonValue));
}
/**
*/
async apiMeFacilityDistancesIdPut(requestParameters: ApiMeFacilityDistancesIdPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<MyFacilityDistanceResponse> {
const response = await this.apiMeFacilityDistancesIdPutRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async apiMeFacilityDistancesPostRaw(requestParameters: ApiMeFacilityDistancesPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<MyFacilityDistanceResponse>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/me/facility-distances`;
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: CreateMyFacilityDistanceRequestToJSON(requestParameters['createMyFacilityDistanceRequest']),
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => MyFacilityDistanceResponseFromJSON(jsonValue));
}
/**
*/
async apiMeFacilityDistancesPost(requestParameters: ApiMeFacilityDistancesPostRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<MyFacilityDistanceResponse> {
const response = await this.apiMeFacilityDistancesPostRaw(requestParameters, initOverrides);
return await response.value();
}
}
@@ -31,6 +31,10 @@ import {
UpdateRolePermissionsRequestToJSON,
} from '../models/index';
export interface ApiRolesIdDeleteRequest {
id: string;
}
export interface ApiRolesIdGetRequest {
id: string;
}
@@ -84,6 +88,48 @@ export class RolesApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async apiRolesIdDeleteRaw(requestParameters: ApiRolesIdDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiRolesIdDelete().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/roles/{id}`;
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id'])));
const response = await this.request({
path: urlPath,
method: 'DELETE',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async apiRolesIdDelete(requestParameters: ApiRolesIdDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.apiRolesIdDeleteRaw(requestParameters, initOverrides);
}
/**
*/
async apiRolesIdGetRaw(requestParameters: ApiRolesIdGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RolePermissionsResponse>> {
@@ -17,6 +17,7 @@ import * as runtime from '../runtime';
import type {
TrashAbsenceResponse,
TrashContractResponse,
TrashEmployeeFacilityDistanceResponse,
TrashEmployeeResponse,
TrashFacilityContactResponse,
TrashFacilityQualificationRateResponse,
@@ -29,6 +30,8 @@ import {
TrashAbsenceResponseToJSON,
TrashContractResponseFromJSON,
TrashContractResponseToJSON,
TrashEmployeeFacilityDistanceResponseFromJSON,
TrashEmployeeFacilityDistanceResponseToJSON,
TrashEmployeeResponseFromJSON,
TrashEmployeeResponseToJSON,
TrashFacilityContactResponseFromJSON,
@@ -59,6 +62,14 @@ export interface ApiTrashContractsIdRestorePostRequest {
id: string;
}
export interface ApiTrashEmployeeFacilityDistancesGetRequest {
search?: string;
}
export interface ApiTrashEmployeeFacilityDistancesIdRestorePostRequest {
id: string;
}
export interface ApiTrashEmployeesGetRequest {
search?: string;
}
@@ -274,6 +285,87 @@ export class TrashApi extends runtime.BaseAPI {
await this.apiTrashContractsIdRestorePostRaw(requestParameters, initOverrides);
}
/**
*/
async apiTrashEmployeeFacilityDistancesGetRaw(requestParameters: ApiTrashEmployeeFacilityDistancesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<TrashEmployeeFacilityDistanceResponse>>> {
const queryParameters: any = {};
if (requestParameters['search'] != null) {
queryParameters['search'] = requestParameters['search'];
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/trash/employee-facility-distances`;
const response = await this.request({
path: urlPath,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(TrashEmployeeFacilityDistanceResponseFromJSON));
}
/**
*/
async apiTrashEmployeeFacilityDistancesGet(requestParameters: ApiTrashEmployeeFacilityDistancesGetRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<Array<TrashEmployeeFacilityDistanceResponse>> {
const response = await this.apiTrashEmployeeFacilityDistancesGetRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async apiTrashEmployeeFacilityDistancesIdRestorePostRaw(requestParameters: ApiTrashEmployeeFacilityDistancesIdRestorePostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters['id'] == null) {
throw new runtime.RequiredError(
'id',
'Required parameter "id" was null or undefined when calling apiTrashEmployeeFacilityDistancesIdRestorePost().'
);
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("Bearer", []);
if (tokenString) {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
let urlPath = `/api/trash/employee-facility-distances/{id}/restore`;
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id'])));
const response = await this.request({
path: urlPath,
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async apiTrashEmployeeFacilityDistancesIdRestorePost(requestParameters: ApiTrashEmployeeFacilityDistancesIdRestorePostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.apiTrashEmployeeFacilityDistancesIdRestorePostRaw(requestParameters, initOverrides);
}
/**
*/
async apiTrashEmployeesGetRaw(requestParameters: ApiTrashEmployeesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<Array<TrashEmployeeResponse>>> {
@@ -7,11 +7,13 @@ export * from './AuditLogApi';
export * from './AuthApi';
export * from './ContractsApi';
export * from './DocumentsApi';
export * from './EmployeeFacilityDistancesApi';
export * from './EmployeesApi';
export * from './FacilitiesApi';
export * from './FacilityContactsApi';
export * from './FacilityQualificationRatesApi';
export * from './HealthApi';
export * from './MyFacilityDistancesApi';
export * from './OrdersApi';
export * from './RolesApi';
export * from './TimeEntriesApi';
@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface CreateEmployeeFacilityDistanceRequest
*/
export interface CreateEmployeeFacilityDistanceRequest {
/**
*
* @type {string}
* @memberof CreateEmployeeFacilityDistanceRequest
*/
employeeId?: string;
/**
*
* @type {number}
* @memberof CreateEmployeeFacilityDistanceRequest
*/
distanceKm?: number;
}
/**
* Check if a given object implements the CreateEmployeeFacilityDistanceRequest interface.
*/
export function instanceOfCreateEmployeeFacilityDistanceRequest(value: object): value is CreateEmployeeFacilityDistanceRequest {
return true;
}
export function CreateEmployeeFacilityDistanceRequestFromJSON(json: any): CreateEmployeeFacilityDistanceRequest {
return CreateEmployeeFacilityDistanceRequestFromJSONTyped(json, false);
}
export function CreateEmployeeFacilityDistanceRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreateEmployeeFacilityDistanceRequest {
if (json == null) {
return json;
}
return {
'employeeId': json['employeeId'] == null ? undefined : json['employeeId'],
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function CreateEmployeeFacilityDistanceRequestToJSON(json: any): CreateEmployeeFacilityDistanceRequest {
return CreateEmployeeFacilityDistanceRequestToJSONTyped(json, false);
}
export function CreateEmployeeFacilityDistanceRequestToJSONTyped(value?: CreateEmployeeFacilityDistanceRequest | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'employeeId': value['employeeId'],
'distanceKm': value['distanceKm'],
};
}
@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface CreateMyFacilityDistanceRequest
*/
export interface CreateMyFacilityDistanceRequest {
/**
*
* @type {string}
* @memberof CreateMyFacilityDistanceRequest
*/
facilityId?: string;
/**
*
* @type {number}
* @memberof CreateMyFacilityDistanceRequest
*/
distanceKm?: number;
}
/**
* Check if a given object implements the CreateMyFacilityDistanceRequest interface.
*/
export function instanceOfCreateMyFacilityDistanceRequest(value: object): value is CreateMyFacilityDistanceRequest {
return true;
}
export function CreateMyFacilityDistanceRequestFromJSON(json: any): CreateMyFacilityDistanceRequest {
return CreateMyFacilityDistanceRequestFromJSONTyped(json, false);
}
export function CreateMyFacilityDistanceRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreateMyFacilityDistanceRequest {
if (json == null) {
return json;
}
return {
'facilityId': json['facilityId'] == null ? undefined : json['facilityId'],
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function CreateMyFacilityDistanceRequestToJSON(json: any): CreateMyFacilityDistanceRequest {
return CreateMyFacilityDistanceRequestToJSONTyped(json, false);
}
export function CreateMyFacilityDistanceRequestToJSONTyped(value?: CreateMyFacilityDistanceRequest | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'facilityId': value['facilityId'],
'distanceKm': value['distanceKm'],
};
}
@@ -0,0 +1,105 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface EmployeeFacilityDistanceResponse
*/
export interface EmployeeFacilityDistanceResponse {
/**
*
* @type {string}
* @memberof EmployeeFacilityDistanceResponse
*/
id?: string;
/**
*
* @type {string}
* @memberof EmployeeFacilityDistanceResponse
*/
facilityId?: string;
/**
*
* @type {string}
* @memberof EmployeeFacilityDistanceResponse
*/
employeeId?: string;
/**
*
* @type {string}
* @memberof EmployeeFacilityDistanceResponse
*/
employeeFirstName?: string | null;
/**
*
* @type {string}
* @memberof EmployeeFacilityDistanceResponse
*/
employeeLastName?: string | null;
/**
*
* @type {number}
* @memberof EmployeeFacilityDistanceResponse
*/
distanceKm?: number;
}
/**
* Check if a given object implements the EmployeeFacilityDistanceResponse interface.
*/
export function instanceOfEmployeeFacilityDistanceResponse(value: object): value is EmployeeFacilityDistanceResponse {
return true;
}
export function EmployeeFacilityDistanceResponseFromJSON(json: any): EmployeeFacilityDistanceResponse {
return EmployeeFacilityDistanceResponseFromJSONTyped(json, false);
}
export function EmployeeFacilityDistanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): EmployeeFacilityDistanceResponse {
if (json == null) {
return json;
}
return {
'id': json['id'] == null ? undefined : json['id'],
'facilityId': json['facilityId'] == null ? undefined : json['facilityId'],
'employeeId': json['employeeId'] == null ? undefined : json['employeeId'],
'employeeFirstName': json['employeeFirstName'] == null ? undefined : json['employeeFirstName'],
'employeeLastName': json['employeeLastName'] == null ? undefined : json['employeeLastName'],
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function EmployeeFacilityDistanceResponseToJSON(json: any): EmployeeFacilityDistanceResponse {
return EmployeeFacilityDistanceResponseToJSONTyped(json, false);
}
export function EmployeeFacilityDistanceResponseToJSONTyped(value?: EmployeeFacilityDistanceResponse | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'id': value['id'],
'facilityId': value['facilityId'],
'employeeId': value['employeeId'],
'employeeFirstName': value['employeeFirstName'],
'employeeLastName': value['employeeLastName'],
'distanceKm': value['distanceKm'],
};
}
@@ -0,0 +1,73 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface FacilityOptionResponse
*/
export interface FacilityOptionResponse {
/**
*
* @type {string}
* @memberof FacilityOptionResponse
*/
id?: string;
/**
*
* @type {string}
* @memberof FacilityOptionResponse
*/
name?: string | null;
}
/**
* Check if a given object implements the FacilityOptionResponse interface.
*/
export function instanceOfFacilityOptionResponse(value: object): value is FacilityOptionResponse {
return true;
}
export function FacilityOptionResponseFromJSON(json: any): FacilityOptionResponse {
return FacilityOptionResponseFromJSONTyped(json, false);
}
export function FacilityOptionResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): FacilityOptionResponse {
if (json == null) {
return json;
}
return {
'id': json['id'] == null ? undefined : json['id'],
'name': json['name'] == null ? undefined : json['name'],
};
}
export function FacilityOptionResponseToJSON(json: any): FacilityOptionResponse {
return FacilityOptionResponseToJSONTyped(json, false);
}
export function FacilityOptionResponseToJSONTyped(value?: FacilityOptionResponse | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'id': value['id'],
'name': value['name'],
};
}
@@ -139,6 +139,18 @@ export interface FacilityResponse {
* @memberof FacilityResponse
*/
travelCostRate?: number | null;
/**
*
* @type {string}
* @memberof FacilityResponse
*/
travelCostMode?: string | null;
/**
*
* @type {number}
* @memberof FacilityResponse
*/
travelCostPerKm?: number | null;
/**
*
* @type {number}
@@ -208,6 +220,8 @@ export function FacilityResponseFromJSONTyped(json: any, ignoreDiscriminator: bo
'sundaySurchargePercent': json['sundaySurchargePercent'] == null ? undefined : json['sundaySurchargePercent'],
'holidaySurchargePercent': json['holidaySurchargePercent'] == null ? undefined : json['holidaySurchargePercent'],
'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'],
'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'],
'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'],
'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'],
'breakPolicy': json['breakPolicy'] == null ? undefined : json['breakPolicy'],
'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'],
@@ -247,6 +261,8 @@ export function FacilityResponseToJSONTyped(value?: FacilityResponse | null, ign
'sundaySurchargePercent': value['sundaySurchargePercent'],
'holidaySurchargePercent': value['holidaySurchargePercent'],
'travelCostRate': value['travelCostRate'],
'travelCostMode': value['travelCostMode'],
'travelCostPerKm': value['travelCostPerKm'],
'minimumHours': value['minimumHours'],
'breakPolicy': value['breakPolicy'],
'billingInterval': value['billingInterval'],
@@ -31,7 +31,8 @@ export const ModuleType = {
Documents: 'Documents',
Users: 'Users',
Configuration: 'Configuration',
Absences: 'Absences'
Absences: 'Absences',
EmployeeFacilityDistances: 'EmployeeFacilityDistances'
} as const;
export type ModuleType = typeof ModuleType[keyof typeof ModuleType];
@@ -0,0 +1,89 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface MyFacilityDistanceResponse
*/
export interface MyFacilityDistanceResponse {
/**
*
* @type {string}
* @memberof MyFacilityDistanceResponse
*/
id?: string;
/**
*
* @type {string}
* @memberof MyFacilityDistanceResponse
*/
facilityId?: string;
/**
*
* @type {string}
* @memberof MyFacilityDistanceResponse
*/
facilityName?: string | null;
/**
*
* @type {number}
* @memberof MyFacilityDistanceResponse
*/
distanceKm?: number;
}
/**
* Check if a given object implements the MyFacilityDistanceResponse interface.
*/
export function instanceOfMyFacilityDistanceResponse(value: object): value is MyFacilityDistanceResponse {
return true;
}
export function MyFacilityDistanceResponseFromJSON(json: any): MyFacilityDistanceResponse {
return MyFacilityDistanceResponseFromJSONTyped(json, false);
}
export function MyFacilityDistanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): MyFacilityDistanceResponse {
if (json == null) {
return json;
}
return {
'id': json['id'] == null ? undefined : json['id'],
'facilityId': json['facilityId'] == null ? undefined : json['facilityId'],
'facilityName': json['facilityName'] == null ? undefined : json['facilityName'],
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function MyFacilityDistanceResponseToJSON(json: any): MyFacilityDistanceResponse {
return MyFacilityDistanceResponseToJSONTyped(json, false);
}
export function MyFacilityDistanceResponseToJSONTyped(value?: MyFacilityDistanceResponse | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'id': value['id'],
'facilityId': value['facilityId'],
'facilityName': value['facilityName'],
'distanceKm': value['distanceKm'],
};
}
@@ -0,0 +1,97 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface TrashEmployeeFacilityDistanceResponse
*/
export interface TrashEmployeeFacilityDistanceResponse {
/**
*
* @type {string}
* @memberof TrashEmployeeFacilityDistanceResponse
*/
id?: string;
/**
*
* @type {string}
* @memberof TrashEmployeeFacilityDistanceResponse
*/
facilityId?: string;
/**
*
* @type {string}
* @memberof TrashEmployeeFacilityDistanceResponse
*/
employeeId?: string;
/**
*
* @type {number}
* @memberof TrashEmployeeFacilityDistanceResponse
*/
distanceKm?: number;
/**
*
* @type {Date}
* @memberof TrashEmployeeFacilityDistanceResponse
*/
deletedAt?: Date | null;
}
/**
* Check if a given object implements the TrashEmployeeFacilityDistanceResponse interface.
*/
export function instanceOfTrashEmployeeFacilityDistanceResponse(value: object): value is TrashEmployeeFacilityDistanceResponse {
return true;
}
export function TrashEmployeeFacilityDistanceResponseFromJSON(json: any): TrashEmployeeFacilityDistanceResponse {
return TrashEmployeeFacilityDistanceResponseFromJSONTyped(json, false);
}
export function TrashEmployeeFacilityDistanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): TrashEmployeeFacilityDistanceResponse {
if (json == null) {
return json;
}
return {
'id': json['id'] == null ? undefined : json['id'],
'facilityId': json['facilityId'] == null ? undefined : json['facilityId'],
'employeeId': json['employeeId'] == null ? undefined : json['employeeId'],
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
'deletedAt': json['deletedAt'] == null ? undefined : (new Date(json['deletedAt'])),
};
}
export function TrashEmployeeFacilityDistanceResponseToJSON(json: any): TrashEmployeeFacilityDistanceResponse {
return TrashEmployeeFacilityDistanceResponseToJSONTyped(json, false);
}
export function TrashEmployeeFacilityDistanceResponseToJSONTyped(value?: TrashEmployeeFacilityDistanceResponse | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'id': value['id'],
'facilityId': value['facilityId'],
'employeeId': value['employeeId'],
'distanceKm': value['distanceKm'],
'deletedAt': value['deletedAt'] === null ? null : ((value['deletedAt'] as any)?.toISOString()),
};
}
@@ -0,0 +1,65 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface UpdateEmployeeFacilityDistanceRequest
*/
export interface UpdateEmployeeFacilityDistanceRequest {
/**
*
* @type {number}
* @memberof UpdateEmployeeFacilityDistanceRequest
*/
distanceKm?: number;
}
/**
* Check if a given object implements the UpdateEmployeeFacilityDistanceRequest interface.
*/
export function instanceOfUpdateEmployeeFacilityDistanceRequest(value: object): value is UpdateEmployeeFacilityDistanceRequest {
return true;
}
export function UpdateEmployeeFacilityDistanceRequestFromJSON(json: any): UpdateEmployeeFacilityDistanceRequest {
return UpdateEmployeeFacilityDistanceRequestFromJSONTyped(json, false);
}
export function UpdateEmployeeFacilityDistanceRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): UpdateEmployeeFacilityDistanceRequest {
if (json == null) {
return json;
}
return {
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function UpdateEmployeeFacilityDistanceRequestToJSON(json: any): UpdateEmployeeFacilityDistanceRequest {
return UpdateEmployeeFacilityDistanceRequestToJSONTyped(json, false);
}
export function UpdateEmployeeFacilityDistanceRequestToJSONTyped(value?: UpdateEmployeeFacilityDistanceRequest | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'distanceKm': value['distanceKm'],
};
}
@@ -133,6 +133,18 @@ export interface UpdateFacilityRequest {
* @memberof UpdateFacilityRequest
*/
travelCostRate?: number | null;
/**
*
* @type {string}
* @memberof UpdateFacilityRequest
*/
travelCostMode?: string | null;
/**
*
* @type {number}
* @memberof UpdateFacilityRequest
*/
travelCostPerKm?: number | null;
/**
*
* @type {number}
@@ -201,6 +213,8 @@ export function UpdateFacilityRequestFromJSONTyped(json: any, ignoreDiscriminato
'sundaySurchargePercent': json['sundaySurchargePercent'] == null ? undefined : json['sundaySurchargePercent'],
'holidaySurchargePercent': json['holidaySurchargePercent'] == null ? undefined : json['holidaySurchargePercent'],
'travelCostRate': json['travelCostRate'] == null ? undefined : json['travelCostRate'],
'travelCostMode': json['travelCostMode'] == null ? undefined : json['travelCostMode'],
'travelCostPerKm': json['travelCostPerKm'] == null ? undefined : json['travelCostPerKm'],
'minimumHours': json['minimumHours'] == null ? undefined : json['minimumHours'],
'breakPolicy': json['breakPolicy'] == null ? undefined : json['breakPolicy'],
'billingInterval': json['billingInterval'] == null ? undefined : json['billingInterval'],
@@ -239,6 +253,8 @@ export function UpdateFacilityRequestToJSONTyped(value?: UpdateFacilityRequest |
'sundaySurchargePercent': value['sundaySurchargePercent'],
'holidaySurchargePercent': value['holidaySurchargePercent'],
'travelCostRate': value['travelCostRate'],
'travelCostMode': value['travelCostMode'],
'travelCostPerKm': value['travelCostPerKm'],
'minimumHours': value['minimumHours'],
'breakPolicy': value['breakPolicy'],
'billingInterval': value['billingInterval'],
@@ -0,0 +1,65 @@
/* tslint:disable */
/* eslint-disable */
/**
* OmsorgCore.Api
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface UpdateMyFacilityDistanceRequest
*/
export interface UpdateMyFacilityDistanceRequest {
/**
*
* @type {number}
* @memberof UpdateMyFacilityDistanceRequest
*/
distanceKm?: number;
}
/**
* Check if a given object implements the UpdateMyFacilityDistanceRequest interface.
*/
export function instanceOfUpdateMyFacilityDistanceRequest(value: object): value is UpdateMyFacilityDistanceRequest {
return true;
}
export function UpdateMyFacilityDistanceRequestFromJSON(json: any): UpdateMyFacilityDistanceRequest {
return UpdateMyFacilityDistanceRequestFromJSONTyped(json, false);
}
export function UpdateMyFacilityDistanceRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): UpdateMyFacilityDistanceRequest {
if (json == null) {
return json;
}
return {
'distanceKm': json['distanceKm'] == null ? undefined : json['distanceKm'],
};
}
export function UpdateMyFacilityDistanceRequestToJSON(json: any): UpdateMyFacilityDistanceRequest {
return UpdateMyFacilityDistanceRequestToJSONTyped(json, false);
}
export function UpdateMyFacilityDistanceRequestToJSONTyped(value?: UpdateMyFacilityDistanceRequest | null, ignoreDiscriminator: boolean = false): any {
if (value == null) {
return value;
}
return {
'distanceKm': value['distanceKm'],
};
}
@@ -12,19 +12,23 @@ export * from './ContractResponse';
export * from './ContractResponsePagedResponse';
export * from './CreateAbsenceRequest';
export * from './CreateContractRequest';
export * from './CreateEmployeeFacilityDistanceRequest';
export * from './CreateEmployeeRequest';
export * from './CreateFacilityContactRequest';
export * from './CreateFacilityQualificationRateRequest';
export * from './CreateFacilityRequest';
export * from './CreateMyFacilityDistanceRequest';
export * from './CreateOrderRequest';
export * from './CreateRoleRequest';
export * from './CreateTimeEntryRequest';
export * from './CreateUserRequest';
export * from './CreateValueListItemRequest';
export * from './DocumentResponse';
export * from './EmployeeFacilityDistanceResponse';
export * from './EmployeeResponse';
export * from './EmployeeResponsePagedResponse';
export * from './FacilityContactResponse';
export * from './FacilityOptionResponse';
export * from './FacilityQualificationRateResponse';
export * from './FacilityResponse';
export * from './FacilityResponsePagedResponse';
@@ -38,6 +42,7 @@ export * from './LoginResponse';
export * from './LogoutRequest';
export * from './MeResponse';
export * from './ModuleType';
export * from './MyFacilityDistanceResponse';
export * from './OrderResponse';
export * from './OrderResponsePagedResponse';
export * from './PasswordPolicyResponse';
@@ -57,6 +62,7 @@ export * from './TimeEntryResponse';
export * from './TimeEntryResponsePagedResponse';
export * from './TrashAbsenceResponse';
export * from './TrashContractResponse';
export * from './TrashEmployeeFacilityDistanceResponse';
export * from './TrashEmployeeResponse';
export * from './TrashFacilityContactResponse';
export * from './TrashFacilityQualificationRateResponse';
@@ -66,10 +72,12 @@ export * from './TrashTimeEntryResponse';
export * from './UpdateAbsenceRequest';
export * from './UpdateContractRequest';
export * from './UpdateDocumentRequest';
export * from './UpdateEmployeeFacilityDistanceRequest';
export * from './UpdateEmployeeRequest';
export * from './UpdateFacilityContactRequest';
export * from './UpdateFacilityQualificationRateRequest';
export * from './UpdateFacilityRequest';
export * from './UpdateMyFacilityDistanceRequest';
export * from './UpdateOrderRequest';
export * from './UpdateRolePermissionsRequest';
export * from './UpdateTimeEntryRequest';
@@ -0,0 +1,26 @@
import { EmployeeFacilityDistancesApi } from "omsorgcore-client-ts";
import { configFor, callApi } from "./apiClientHelpers.js";
// Kapselt /api/facilities/{facilityId}/employee-distances von omsorgCore
// (EmployeeFacilityDistancesController) über den generierten Client (omsorgcore-client-ts).
// Mitarbeiter-Einrichtung-Entfernungen sind eine 1:n-Unterressource von Facility (FR-EIN-4,
// Grundlage für die kilometerbasierte Fahrtkostenabrechnung).
export async function listEmployeeFacilityDistances(accessToken, facilityId) {
const api = new EmployeeFacilityDistancesApi(configFor(accessToken));
return callApi(api.apiFacilitiesFacilityIdEmployeeDistancesGetRaw({ facilityId }));
}
export async function createEmployeeFacilityDistance(accessToken, facilityId, payload) {
const api = new EmployeeFacilityDistancesApi(configFor(accessToken));
return callApi(api.apiFacilitiesFacilityIdEmployeeDistancesPostRaw({ facilityId, createEmployeeFacilityDistanceRequest: payload }));
}
export async function updateEmployeeFacilityDistance(accessToken, facilityId, id, payload) {
const api = new EmployeeFacilityDistancesApi(configFor(accessToken));
return callApi(api.apiFacilitiesFacilityIdEmployeeDistancesIdPutRaw({ facilityId, id, updateEmployeeFacilityDistanceRequest: payload }));
}
export async function deleteEmployeeFacilityDistance(accessToken, facilityId, id) {
const api = new EmployeeFacilityDistancesApi(configFor(accessToken));
return callApi(api.apiFacilitiesFacilityIdEmployeeDistancesIdDeleteRaw({ facilityId, id }));
}
+15 -2
View File
@@ -4,6 +4,19 @@ import { configFor, callApi } from "./apiClientHelpers.js";
// Kapselt /api/employees von omsorgCore (EmployeesController) über den generierten
// Client (omsorgcore-client-ts). Feldnamen sind camelCase, da ASP.NET Core
// standardmäßig camelCase-JSON ausgibt.
// dateOfBirth/entryDate/exitDate müssen als Date-Objekte übergeben werden - die generierten
// ...ToJSON-Funktionen rufen .toISOString() darauf auf, ein reiner "YYYY-MM-DD"-String aus einem
// <input type="date"> würde dabei crashen (siehe ordersApi.js für dasselbe Muster).
function toDatePayload(payload) {
return {
...payload,
dateOfBirth: payload.dateOfBirth ? new Date(payload.dateOfBirth) : payload.dateOfBirth,
entryDate: payload.entryDate ? new Date(payload.entryDate) : payload.entryDate,
exitDate: payload.exitDate ? new Date(payload.exitDate) : payload.exitDate
};
}
export async function listEmployees(accessToken, { search, status, employmentType, page = 1, pageSize = 20 } = {}) {
const api = new EmployeesApi(configFor(accessToken));
return callApi(api.apiEmployeesGetRaw({ search, status, employmentType, page, pageSize }));
@@ -11,7 +24,7 @@ export async function listEmployees(accessToken, { search, status, employmentTyp
export async function createEmployee(accessToken, payload) {
const api = new EmployeesApi(configFor(accessToken));
return callApi(api.apiEmployeesPostRaw({ createEmployeeRequest: payload }));
return callApi(api.apiEmployeesPostRaw({ createEmployeeRequest: toDatePayload(payload) }));
}
export async function getEmployee(accessToken, id) {
@@ -21,7 +34,7 @@ export async function getEmployee(accessToken, id) {
export async function updateEmployee(accessToken, id, payload) {
const api = new EmployeesApi(configFor(accessToken));
return callApi(api.apiEmployeesIdPutRaw({ id, updateEmployeeRequest: payload }));
return callApi(api.apiEmployeesIdPutRaw({ id, updateEmployeeRequest: toDatePayload(payload) }));
}
export async function deleteEmployee(accessToken, id) {
+11 -1
View File
@@ -5,6 +5,7 @@ import * as employeesApi from "./employeesApi.js";
import * as facilitiesApi from "./facilitiesApi.js";
import * as facilityContactsApi from "./facilityContactsApi.js";
import * as facilityQualificationRatesApi from "./facilityQualificationRatesApi.js";
import * as employeeFacilityDistancesApi from "./employeeFacilityDistancesApi.js";
import * as ordersApi from "./ordersApi.js";
import * as absencesApi from "./absencesApi.js";
import * as timeEntriesApi from "./timeEntriesApi.js";
@@ -127,6 +128,12 @@ export function buildOmsorgApi() {
update: withAuth(facilityQualificationRatesApi.updateFacilityQualificationRate),
delete: withAuth(facilityQualificationRatesApi.deleteFacilityQualificationRate)
},
employeeFacilityDistances: {
list: withAuth(employeeFacilityDistancesApi.listEmployeeFacilityDistances),
create: withAuth(employeeFacilityDistancesApi.createEmployeeFacilityDistance),
update: withAuth(employeeFacilityDistancesApi.updateEmployeeFacilityDistance),
delete: withAuth(employeeFacilityDistancesApi.deleteEmployeeFacilityDistance)
},
orders: {
list: withAuth(ordersApi.listOrders),
create: withAuth(ordersApi.createOrder),
@@ -162,7 +169,8 @@ export function buildOmsorgApi() {
list: withAuth(rolesApi.listRoles),
get: withAuth(rolesApi.getRole),
create: withAuth(rolesApi.createRole),
updatePermissions: withAuth(rolesApi.updateRolePermissions)
updatePermissions: withAuth(rolesApi.updateRolePermissions),
delete: withAuth(rolesApi.deleteRole)
},
auditLog: {
list: withAuth(auditLogApi.listAuditLog)
@@ -190,6 +198,8 @@ export function buildOmsorgApi() {
restoreFacilityContact: withAuth(trashApi.restoreFacilityContact),
listFacilityQualificationRates: withAuth(trashApi.listDeletedFacilityQualificationRates),
restoreFacilityQualificationRate: withAuth(trashApi.restoreFacilityQualificationRate),
listEmployeeFacilityDistances: withAuth(trashApi.listDeletedEmployeeFacilityDistances),
restoreEmployeeFacilityDistance: withAuth(trashApi.restoreEmployeeFacilityDistance),
listAbsences: withAuth(trashApi.listDeletedAbsences),
restoreAbsence: withAuth(trashApi.restoreAbsence),
listTimeEntries: withAuth(trashApi.listDeletedTimeEntries),
+5
View File
@@ -22,3 +22,8 @@ export async function updateRolePermissions(accessToken, roleId, payload) {
const api = new RolesApi(configFor(accessToken));
return callApi(api.apiRolesIdPermissionsPutRaw({ id: roleId, updateRolePermissionsRequest: payload }));
}
export async function deleteRole(accessToken, roleId) {
const api = new RolesApi(configFor(accessToken));
return callApi(api.apiRolesIdDeleteRaw({ id: roleId }));
}
+10
View File
@@ -64,6 +64,16 @@ export async function restoreFacilityQualificationRate(accessToken, id) {
return callApi(api.apiTrashFacilityQualificationRatesIdRestorePostRaw({ id }));
}
export async function listDeletedEmployeeFacilityDistances(accessToken, search) {
const api = new TrashApi(configFor(accessToken));
return callApi(api.apiTrashEmployeeFacilityDistancesGetRaw({ search }));
}
export async function restoreEmployeeFacilityDistance(accessToken, id) {
const api = new TrashApi(configFor(accessToken));
return callApi(api.apiTrashEmployeeFacilityDistancesIdRestorePostRaw({ id }));
}
export async function listDeletedAbsences(accessToken, search) {
const api = new TrashApi(configFor(accessToken));
return callApi(api.apiTrashAbsencesGetRaw({ search }));
@@ -79,6 +79,10 @@ export default function EmployeeForm({ form, onChange, includeStatus = false })
return (event) => onChange({ ...form, [field]: event.target.value });
}
function clearField(field) {
return () => onChange({ ...form, [field]: "" });
}
return (
<div className="form-grid">
<label className="form-field">
@@ -106,7 +110,14 @@ export default function EmployeeForm({ form, onChange, includeStatus = false })
<label className="form-field">
<span>Geburtsdatum</span>
<input type="date" value={form.dateOfBirth} onChange={updateField("dateOfBirth")} />
<div className="input-with-action">
<input type="date" value={form.dateOfBirth} onChange={updateField("dateOfBirth")} />
{form.dateOfBirth && (
<OmsorgButton type="button" variant="secondary" onClick={clearField("dateOfBirth")}>
Entfernen
</OmsorgButton>
)}
</div>
</label>
<fieldset className="form-field form-field--fieldset">
@@ -147,12 +158,26 @@ export default function EmployeeForm({ form, onChange, includeStatus = false })
<label className="form-field">
<span>Eintrittsdatum</span>
<input type="date" value={form.entryDate} onChange={updateField("entryDate")} />
<div className="input-with-action">
<input type="date" value={form.entryDate} onChange={updateField("entryDate")} />
{form.entryDate && (
<OmsorgButton type="button" variant="secondary" onClick={clearField("entryDate")}>
Entfernen
</OmsorgButton>
)}
</div>
</label>
<label className="form-field">
<span>Austrittsdatum</span>
<input type="date" value={form.exitDate} onChange={updateField("exitDate")} />
<div className="input-with-action">
<input type="date" value={form.exitDate} onChange={updateField("exitDate")} />
{form.exitDate && (
<OmsorgButton type="button" variant="secondary" onClick={clearField("exitDate")}>
Entfernen
</OmsorgButton>
)}
</div>
</label>
<label className="form-field">
@@ -0,0 +1,68 @@
import { useState } from "react";
import EmployeeFacilityDistanceForm, {
emptyEmployeeFacilityDistanceForm,
employeeFacilityDistanceFormToPayload,
FormActions,
} from "./EmployeeFacilityDistanceForm";
import ModalPortal from "../../components/ui/ModalPortal";
function errorMessage(result) {
if (result.status === 403) {
return "Keine Berechtigung, Entfernungen anzulegen.";
}
if (result.status === 400) {
return typeof result.data === "string" ? result.data : "Eingaben prüfen.";
}
return "Entfernung konnte nicht angelegt werden.";
}
export default function CreateEmployeeFacilityDistanceDialog({ facilityId, onClose, onCreated }) {
const [form, setForm] = useState(emptyEmployeeFacilityDistanceForm);
const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(event) {
event.preventDefault();
if (!form.employeeId) {
setError("Mitarbeiter ist erforderlich.");
return;
}
setIsSaving(true);
setError(null);
const result = await window.omsorg.employeeFacilityDistances.create(
facilityId,
employeeFacilityDistanceFormToPayload(form, { includeEmployeeId: true })
);
setIsSaving(false);
if (!result.ok) {
setError(errorMessage(result));
return;
}
onCreated(result.data);
}
return (
<ModalPortal>
<div className="modal-overlay" role="dialog" aria-modal="true" aria-label="Neue Entfernung">
<div className="modal-panel">
<h2>Neue Entfernung</h2>
<form onSubmit={handleSubmit}>
<EmployeeFacilityDistanceForm form={form} onChange={setForm} includeEmployeeSelect />
{error && <p className="login-error form-error">{error}</p>}
<FormActions onCancel={onClose} isSaving={isSaving} submitLabel="Speichern" />
</form>
</div>
</div>
</ModalPortal>
);
}
@@ -0,0 +1,63 @@
import { useState } from "react";
import EmployeeFacilityDistanceForm, {
employeeFacilityDistanceFormToPayload,
employeeFacilityDistanceToFormValues,
FormActions,
} from "./EmployeeFacilityDistanceForm";
import ModalPortal from "../../components/ui/ModalPortal";
function errorMessage(result) {
if (result.status === 403) {
return "Keine Berechtigung, Entfernungen zu bearbeiten.";
}
if (result.status === 400) {
return typeof result.data === "string" ? result.data : "Eingaben prüfen.";
}
return "Entfernung konnte nicht gespeichert werden.";
}
export default function EditEmployeeFacilityDistanceDialog({ facilityId, distance, onClose, onUpdated }) {
const [form, setForm] = useState(() => employeeFacilityDistanceToFormValues(distance));
const [isSaving, setIsSaving] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(event) {
event.preventDefault();
setIsSaving(true);
setError(null);
const payload = employeeFacilityDistanceFormToPayload(form);
const result = await window.omsorg.employeeFacilityDistances.update(facilityId, distance.id, payload);
setIsSaving(false);
if (!result.ok) {
setError(errorMessage(result));
return;
}
onUpdated(result.data);
}
return (
<ModalPortal>
<div className="modal-overlay" role="dialog" aria-modal="true" aria-label="Entfernung bearbeiten">
<div className="modal-panel">
<h2>
{distance.employeeFirstName} {distance.employeeLastName} bearbeiten
</h2>
<form onSubmit={handleSubmit}>
<EmployeeFacilityDistanceForm form={form} onChange={setForm} />
{error && <p className="login-error form-error">{error}</p>}
<FormActions onCancel={onClose} isSaving={isSaving} submitLabel="Speichern" />
</form>
</div>
</div>
</ModalPortal>
);
}
@@ -0,0 +1,86 @@
import { useEffect, useState } from "react";
import OmsorgButton from "../../components/ui/OmsorgButton";
export const emptyEmployeeFacilityDistanceForm = {
employeeId: "",
distanceKm: "",
};
export function employeeFacilityDistanceToFormValues(distance) {
return {
employeeId: distance.employeeId ?? "",
distanceKm: typeof distance.distanceKm === "number" ? String(distance.distanceKm) : "",
};
}
export function employeeFacilityDistanceFormToPayload(form, { includeEmployeeId = false } = {}) {
const payload = {
distanceKm: Number(form.distanceKm) || 0,
};
if (includeEmployeeId) {
payload.employeeId = form.employeeId;
}
return payload;
}
export default function EmployeeFacilityDistanceForm({ form, onChange, includeEmployeeSelect = false }) {
const [employees, setEmployees] = useState([]);
useEffect(() => {
if (!includeEmployeeSelect) return;
let cancelled = false;
window.omsorg.employees.list({ pageSize: 500 }).then((result) => {
if (!cancelled && result.ok) {
setEmployees(result.data?.items ?? []);
}
});
return () => {
cancelled = true;
};
}, [includeEmployeeSelect]);
function updateField(field) {
return (event) => onChange({ ...form, [field]: event.target.value });
}
return (
<div className="form-grid">
{includeEmployeeSelect && (
<label className="form-field">
<span>Mitarbeiter *</span>
<select value={form.employeeId} onChange={updateField("employeeId")} required>
<option value=""> auswählen </option>
{employees.map((employee) => (
<option key={employee.id} value={employee.id}>
{employee.firstName} {employee.lastName}
</option>
))}
</select>
</label>
)}
<label className="form-field">
<span>Entfernung (km, einfache Strecke) *</span>
<input type="number" step="0.1" min="0" value={form.distanceKm} onChange={updateField("distanceKm")} required />
</label>
</div>
);
}
export function FormActions({ onCancel, isSaving, submitLabel }) {
return (
<div className="form-actions">
<OmsorgButton variant="secondary" type="button" onClick={onCancel} disabled={isSaving}>
Abbrechen
</OmsorgButton>
<OmsorgButton type="submit" disabled={isSaving}>
{isSaving ? "Speichert..." : submitLabel}
</OmsorgButton>
</div>
);
}
@@ -0,0 +1,132 @@
import { useCallback, useEffect, useState } from "react";
import { Pencil, Plus, Trash2 } from "lucide-react";
import OmsorgButton from "../../components/ui/OmsorgButton";
import { useAuth } from "../../app/AuthContext";
import CreateEmployeeFacilityDistanceDialog from "./CreateEmployeeFacilityDistanceDialog";
import EditEmployeeFacilityDistanceDialog from "./EditEmployeeFacilityDistanceDialog";
export default function EmployeeFacilityDistancesList({ facilityId }) {
const { hasPermission } = useAuth();
const canCreate = hasPermission("Facilities", "Create");
const canEdit = hasPermission("Facilities", "Edit");
const canDelete = hasPermission("Facilities", "Delete");
const [distances, setDistances] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [editingDistance, setEditingDistance] = useState(null);
const [deletingDistanceId, setDeletingDistanceId] = useState(null);
const loadDistances = useCallback(async () => {
setIsLoading(true);
setError(null);
const result = await window.omsorg.employeeFacilityDistances.list(facilityId);
if (result.ok) {
setDistances(result.data ?? []);
} else {
setError("Entfernungen konnten nicht geladen werden.");
}
setIsLoading(false);
}, [facilityId]);
useEffect(() => {
loadDistances();
}, [loadDistances]);
function handleCreated() {
setIsDialogOpen(false);
loadDistances();
}
function handleUpdated() {
setEditingDistance(null);
loadDistances();
}
async function handleDelete(distance) {
if (!window.confirm(`Entfernung für "${distance.employeeFirstName} ${distance.employeeLastName}" wirklich löschen?`)) {
return;
}
setDeletingDistanceId(distance.id);
const result = await window.omsorg.employeeFacilityDistances.delete(facilityId, distance.id);
setDeletingDistanceId(null);
if (result.ok) {
loadDistances();
}
}
return (
<div className="employee-tab-content">
<div className="page-heading">
<h3>Fahrtstrecken je Mitarbeiter</h3>
{canCreate && (
<OmsorgButton icon={Plus} variant="secondary" onClick={() => setIsDialogOpen(true)}>
Neue Entfernung
</OmsorgButton>
)}
</div>
{error && <p className="login-error">{error}</p>}
{isLoading && <p>Lädt...</p>}
{!isLoading && distances.length === 0 && <p>Noch keine Entfernung erfasst.</p>}
{!isLoading && distances.length > 0 && (
<div className="facility-contacts-list">
{distances.map((distance) => (
<div key={distance.id} className="facility-contact-row">
<div>
<strong>
{distance.employeeFirstName} {distance.employeeLastName}
</strong>
<p>{distance.distanceKm.toFixed(1)} km</p>
</div>
{canEdit && (
<OmsorgButton variant="secondary" icon={Pencil} onClick={() => setEditingDistance(distance)}>
Bearbeiten
</OmsorgButton>
)}
{canDelete && (
<OmsorgButton
variant="secondary"
icon={Trash2}
onClick={() => handleDelete(distance)}
disabled={deletingDistanceId === distance.id}
>
Löschen
</OmsorgButton>
)}
</div>
))}
</div>
)}
{isDialogOpen && (
<CreateEmployeeFacilityDistanceDialog
facilityId={facilityId}
onClose={() => setIsDialogOpen(false)}
onCreated={handleCreated}
/>
)}
{editingDistance && (
<EditEmployeeFacilityDistanceDialog
facilityId={facilityId}
distance={editingDistance}
onClose={() => setEditingDistance(null)}
onUpdated={handleUpdated}
/>
)}
</div>
);
}
@@ -7,6 +7,7 @@ import { useAuth } from "../../app/AuthContext";
import EditFacilityDialog from "./EditFacilityDialog";
import FacilityContactsList from "./FacilityContactsList";
import FacilityQualificationRatesList from "./FacilityQualificationRatesList";
import EmployeeFacilityDistancesList from "./EmployeeFacilityDistancesList";
function formatFollowUpDueDate(followUpDueDate) {
if (!followUpDueDate) {
@@ -138,7 +139,15 @@ export default function FacilityDetailPanel({ facility, onUpdated }) {
<div>
<strong>Fahrtkosten</strong>
<p>{facility.travelCostRate != null ? `${facility.travelCostRate} EUR (Pauschale je Einsatz)` : "—"}</p>
<p>
{facility.travelCostMode === "ProKilometer"
? facility.travelCostPerKm != null
? `${facility.travelCostPerKm} EUR/km`
: "—"
: facility.travelCostRate != null
? `${facility.travelCostRate} EUR (Pauschale je Einsatz)`
: "—"}
</p>
</div>
<div>
@@ -168,6 +177,7 @@ export default function FacilityDetailPanel({ facility, onUpdated }) {
</div>
<FacilityQualificationRatesList facilityId={facility.id} />
{facility.travelCostMode === "ProKilometer" && <EmployeeFacilityDistancesList facilityId={facility.id} />}
<FacilityContactsList facilityId={facility.id} />
</div>
@@ -21,7 +21,9 @@ export const emptyFacilityForm = {
saturdaySurchargePercent: "",
sundaySurchargePercent: "",
holidaySurchargePercent: "",
travelCostMode: "Pauschale",
travelCostRate: "",
travelCostPerKm: "",
minimumHours: "",
breakPolicy: "",
billingInterval: "",
@@ -48,7 +50,9 @@ export function facilityToFormValues(facility) {
saturdaySurchargePercent: facility.saturdaySurchargePercent ?? "",
sundaySurchargePercent: facility.sundaySurchargePercent ?? "",
holidaySurchargePercent: facility.holidaySurchargePercent ?? "",
travelCostMode: facility.travelCostMode ?? "Pauschale",
travelCostRate: facility.travelCostRate ?? "",
travelCostPerKm: facility.travelCostPerKm ?? "",
minimumHours: facility.minimumHours ?? "",
breakPolicy: facility.breakPolicy ?? "",
billingInterval: facility.billingInterval ?? "",
@@ -80,7 +84,9 @@ export function facilityFormToPayload(form, { includeCrmStatus = false, followUp
payload.saturdaySurchargePercent = form.saturdaySurchargePercent === "" ? null : Number(form.saturdaySurchargePercent);
payload.sundaySurchargePercent = form.sundaySurchargePercent === "" ? null : Number(form.sundaySurchargePercent);
payload.holidaySurchargePercent = form.holidaySurchargePercent === "" ? null : Number(form.holidaySurchargePercent);
payload.travelCostMode = form.travelCostMode || "Pauschale";
payload.travelCostRate = form.travelCostRate === "" ? null : Number(form.travelCostRate);
payload.travelCostPerKm = form.travelCostPerKm === "" ? null : Number(form.travelCostPerKm);
payload.minimumHours = form.minimumHours === "" ? null : Number(form.minimumHours);
payload.breakPolicy = form.breakPolicy.trim() || null;
payload.billingInterval = form.billingInterval || null;
@@ -249,8 +255,11 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
<div className="form-row">
<label className="form-field">
<span>Fahrtkosten (EUR, Pauschale je Einsatz)</span>
<input type="number" min="0" step="0.01" value={form.travelCostRate} onChange={updateField("travelCostRate")} />
<span>Fahrtkosten Abrechnungsart</span>
<select value={form.travelCostMode} onChange={updateField("travelCostMode")}>
<option value="Pauschale">Pauschale je Einsatz</option>
<option value="ProKilometer">Pro Kilometer</option>
</select>
</label>
<label className="form-field">
@@ -259,6 +268,20 @@ export default function FacilityForm({ form, onChange, includeCrmStatus = false,
</label>
</div>
<div className="form-row">
{form.travelCostMode === "ProKilometer" ? (
<label className="form-field">
<span>Fahrtkosten (EUR/km)</span>
<input type="number" min="0" step="0.01" value={form.travelCostPerKm} onChange={updateField("travelCostPerKm")} />
</label>
) : (
<label className="form-field">
<span>Fahrtkosten (EUR, Pauschale je Einsatz)</span>
<input type="number" min="0" step="0.01" value={form.travelCostRate} onChange={updateField("travelCostRate")} />
</label>
)}
</div>
<label className="form-field">
<span>Pausenregelung</span>
<input value={form.breakPolicy} onChange={updateField("breakPolicy")} />
+42 -2
View File
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from "react";
import { Plus } from "lucide-react";
import { Plus, Trash2 } from "lucide-react";
import OmsorgButton from "../../components/ui/OmsorgButton";
import RolePermissionMatrix from "./RolePermissionMatrix";
import { useAuth } from "../../app/AuthContext";
@@ -8,6 +8,7 @@ export default function RolesPanel() {
const { hasPermission } = useAuth();
const canCreate = hasPermission("UserManagement", "Create");
const canEdit = hasPermission("UserManagement", "Edit");
const canDelete = hasPermission("UserManagement", "Delete");
const [roles, setRoles] = useState([]);
const [selectedRoleId, setSelectedRoleId] = useState(null);
@@ -16,6 +17,8 @@ export default function RolesPanel() {
const [newRoleName, setNewRoleName] = useState("");
const [isCreating, setIsCreating] = useState(false);
const [createError, setCreateError] = useState(null);
const [deletingRoleId, setDeletingRoleId] = useState(null);
const [deleteError, setDeleteError] = useState(null);
const loadRoles = useCallback(async () => {
setIsLoading(true);
@@ -57,6 +60,33 @@ export default function RolesPanel() {
setSelectedRoleId(result.data.id);
}
async function handleDeleteRole(role) {
if (!window.confirm(`Rolle "${role.name}" wirklich löschen?`)) {
return;
}
setDeletingRoleId(role.id);
setDeleteError(null);
const result = await window.omsorg.roles.delete(role.id);
setDeletingRoleId(null);
if (!result.ok) {
setDeleteError(
result.status === 409
? typeof result.data === "string"
? result.data
: "Diese Rolle ist noch Benutzern zugewiesen und kann nicht gelöscht werden."
: "Rolle konnte nicht gelöscht werden."
);
return;
}
if (selectedRoleId === role.id) {
setSelectedRoleId(null);
}
await loadRoles();
}
const selectedRole = roles.find((role) => role.id === selectedRoleId);
return (
@@ -79,6 +109,7 @@ export default function RolesPanel() {
)}
</div>
{createError && <p className="login-error">{createError}</p>}
{deleteError && <p className="login-error">{deleteError}</p>}
{isLoading && <p>Lädt...</p>}
{error && <p className="login-error">{error}</p>}
@@ -88,7 +119,7 @@ export default function RolesPanel() {
<div className="settings-roles-list">
<ul>
{roles.map((role) => (
<li key={role.id}>
<li key={role.id} className="settings-role-item-row">
<button
type="button"
className={role.id === selectedRoleId ? "settings-role-item settings-role-item--active" : "settings-role-item"}
@@ -96,6 +127,15 @@ export default function RolesPanel() {
>
{role.name}
</button>
{canDelete && (
<OmsorgButton
variant="secondary"
icon={Trash2}
onClick={() => handleDeleteRole(role)}
disabled={deletingRoleId === role.id}
/>
)}
</li>
))}
</ul>
@@ -59,6 +59,14 @@ const TABS = [
restore: (id) => window.omsorg.trash.restoreFacilityQualificationRate(id),
displayName: (item) => item.qualification,
},
{
key: "employeeFacilityDistances",
label: "Entfernungen",
module: "Facilities",
list: (search) => window.omsorg.trash.listEmployeeFacilityDistances(search),
restore: (id) => window.omsorg.trash.restoreEmployeeFacilityDistance(id),
displayName: (item) => `${item.distanceKm} km`,
},
{
key: "absences",
label: "Abwesenheiten",
+25
View File
@@ -931,6 +931,16 @@ button.omsorg-button--danger {
gap: 12px;
}
.input-with-action {
display: flex;
align-items: center;
gap: 8px;
}
.input-with-action input {
flex: 1;
}
.form-error {
grid-column: 1 / -1;
}
@@ -1788,6 +1798,21 @@ button.omsorg-button--danger {
border-color: var(--omsorg-primary, currentColor);
}
.settings-role-item-row {
display: flex;
align-items: stretch;
gap: 6px;
}
.settings-role-item-row .settings-role-item {
flex: 1;
min-width: 0;
}
.settings-role-item-row .omsorg-button span:empty {
display: none;
}
.settings-new-role-form {
display: flex;
gap: 8px;