From 77e7eba71180402e2033f6a98c023fe4642a1e9d Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sat, 28 Mar 2026 18:13:18 +0100
Subject: [PATCH] BREAKING CHANGE API and persisted records use PowerOnModel
system fields: - sysCreatedAt, sysCreatedBy, sysModifiedAt, sysModifiedBy
Removed legacy JSON/DB field names: - _createdAt, _createdBy, _modifiedAt,
_modifiedBy Frontend (frontend_nyla) and gateway call sites were updated
accordingly. Database: - Bootstrap runs idempotent backfill
(_migrateSystemFieldColumns) from old underscore columns and selected
business duplicates into sys* where sys* IS NULL. - Re-run app bootstrap
against each PostgreSQL database after deploy. - Optional: DROP INDEX IF
EXISTS "idx_invitation_createdby" if an old index remains; new index:
idx_invitation_syscreatedby on Invitation(sysCreatedBy). Tests: - RBAC
integration tests aligned with current GROUP mandate filter and
UserMandate-based UserConnection GROUP clause; buildRbacWhereClause(...,
mandateId=...) must be passed explicitly (same as production request
context).
---
src/api/automation2Api.ts | 2 +-
src/api/automationApi.ts | 12 ++---
src/api/promptApi.ts | 2 +-
src/api/realEstateApi.ts | 8 +--
src/api/trusteeApi.ts | 52 +++++++++----------
src/hooks/useAdminMandates.ts | 4 +-
src/hooks/useAdminRbacRoles.ts | 4 +-
src/hooks/useAdminRbacRules.ts | 4 +-
src/hooks/useAutomations.ts | 2 +-
src/hooks/useInstancePermissions.tsx | 12 ++---
src/hooks/usePrompts.ts | 6 +--
src/hooks/useRealEstate.ts | 4 +-
src/hooks/useTrustee.ts | 4 +-
src/hooks/useTrusteeAccess.ts | 2 +-
src/hooks/useTrusteeContracts.ts | 2 +-
src/hooks/useTrusteeDocuments.ts | 2 +-
src/hooks/useTrusteeOrganisations.ts | 2 +-
src/hooks/useTrusteePositionDocuments.ts | 2 +-
src/hooks/useTrusteePositions.ts | 2 +-
src/hooks/useTrusteeRoles.ts | 2 +-
src/hooks/useUsers.ts | 4 +-
src/hooks/useWorkflows.ts | 2 +-
src/pages/basedata/ConnectionsPage.tsx | 2 +-
src/pages/basedata/FilesPage.tsx | 4 +-
src/pages/basedata/PromptsPage.tsx | 8 +--
.../automation/AutomationDefinitionsView.tsx | 6 +--
.../automation/AutomationTemplatesView.tsx | 2 +-
.../realestate/RealEstateParcelsView.tsx | 2 +-
.../realestate/RealEstateProjectsView.tsx | 2 +-
.../views/trustee/TrusteeDocumentsView.tsx | 2 +-
.../trustee/TrusteePositionDocumentsView.tsx | 4 +-
.../views/trustee/TrusteePositionsView.tsx | 4 +-
.../views/workspace/NeutralizationPanel.tsx | 2 +-
src/types/mandate.ts | 4 +-
34 files changed, 89 insertions(+), 89 deletions(-)
diff --git a/src/api/automation2Api.ts b/src/api/automation2Api.ts
index f215f7e..86c530c 100644
--- a/src/api/automation2Api.ts
+++ b/src/api/automation2Api.ts
@@ -258,7 +258,7 @@ export interface Automation2Task {
result?: Record;
/** Workflow label (enriched by API) */
workflowLabel?: string;
- /** Unix timestamp ms (from _createdAt) */
+ /** Unix timestamp ms (from sysCreatedAt) */
createdAt?: number;
/** Optional due date - configurable in future */
dueAt?: number;
diff --git a/src/api/automationApi.ts b/src/api/automationApi.ts
index 80d44cd..955ada7 100644
--- a/src/api/automationApi.ts
+++ b/src/api/automationApi.ts
@@ -18,9 +18,9 @@ export interface Automation {
nextExecution?: number;
executionLogs?: AutomationLog[];
allowedProviders?: string[];
- _createdAt?: number;
+ sysCreatedAt?: number;
_updatedAt?: number;
- _createdByUserName?: string;
+ sysCreatedByUserName?: string;
mandateName?: string;
featureInstanceName?: string;
[key: string]: any;
@@ -48,9 +48,9 @@ export interface AutomationTemplate {
label: TextMultilingual;
overview?: TextMultilingual;
template: string; // JSON string with {{KEY:...}} placeholders
- _createdAt?: number;
- _createdBy?: string;
- _createdByUserName?: string;
+ sysCreatedAt?: number;
+ sysCreatedBy?: string;
+ sysCreatedByUserName?: string;
}
// Workflow action definition from backend
@@ -301,7 +301,7 @@ export async function fetchAutomationTemplateById(
*/
export async function createAutomationTemplateApi(
request: ApiRequestFunction,
- templateData: Omit
+ templateData: Omit
): Promise {
return await request({
url: '/api/automation-templates',
diff --git a/src/api/promptApi.ts b/src/api/promptApi.ts
index 3b5a000..094dcdc 100644
--- a/src/api/promptApi.ts
+++ b/src/api/promptApi.ts
@@ -9,7 +9,7 @@ export interface Prompt {
mandateId: string;
content: string;
name: string;
- _createdBy?: string;
+ sysCreatedBy?: string;
_hideDelete?: boolean;
[key: string]: any; // Allow additional properties
}
diff --git a/src/api/realEstateApi.ts b/src/api/realEstateApi.ts
index 08d8ecc..c043485 100644
--- a/src/api/realEstateApi.ts
+++ b/src/api/realEstateApi.ts
@@ -23,8 +23,8 @@ export interface RealEstateProject {
featureInstanceId?: string;
perimeter?: any;
parzellen?: RealEstateParcel[];
- _createdAt?: number;
- _modifiedAt?: number;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
[key: string]: any;
}
@@ -38,8 +38,8 @@ export interface RealEstateParcel {
plz?: string;
perimeter?: any;
bauzone?: string;
- _createdAt?: number;
- _modifiedAt?: number;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
[key: string]: any;
}
diff --git a/src/api/trusteeApi.ts b/src/api/trusteeApi.ts
index 4230612..cc8920b 100644
--- a/src/api/trusteeApi.ts
+++ b/src/api/trusteeApi.ts
@@ -18,10 +18,10 @@ export interface TrusteeOrganisation {
label: string;
enabled: boolean;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -29,10 +29,10 @@ export interface TrusteeRole {
id: string;
desc: string;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -43,10 +43,10 @@ export interface TrusteeAccess {
userId: string;
contractId?: string | null;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -56,10 +56,10 @@ export interface TrusteeContract {
label: string;
enabled: boolean;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -71,10 +71,10 @@ export interface TrusteeDocument {
documentMimeType: string;
documentData?: any;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -98,10 +98,10 @@ export interface TrusteePosition {
costCenter?: string;
bookingReference?: string;
mandateId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
- _createdBy?: string;
- _modifiedBy?: string;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
+ sysCreatedBy?: string;
+ sysModifiedBy?: string;
[key: string]: any;
}
@@ -696,8 +696,8 @@ export interface TrusteePositionDocument {
documentId: string;
mandateId?: string;
featureInstanceId?: string;
- _createdAt?: number;
- _modifiedAt?: number;
+ sysCreatedAt?: number;
+ sysModifiedAt?: number;
[key: string]: any;
}
diff --git a/src/hooks/useAdminMandates.ts b/src/hooks/useAdminMandates.ts
index 010de50..dcf66a4 100644
--- a/src/hooks/useAdminMandates.ts
+++ b/src/hooks/useAdminMandates.ts
@@ -165,7 +165,7 @@ export function useMandates() {
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -305,7 +305,7 @@ export function useMandates() {
return false;
}
// Filter out ID fields and other auto-generated fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useAdminRbacRoles.ts b/src/hooks/useAdminRbacRoles.ts
index 7260f6b..9134eb7 100644
--- a/src/hooks/useAdminRbacRoles.ts
+++ b/src/hooks/useAdminRbacRoles.ts
@@ -206,7 +206,7 @@ export function useRbacRoles() {
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'roleId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'roleId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -346,7 +346,7 @@ export function useRbacRoles() {
return false;
}
// Filter out ID fields and other auto-generated fields
- const nonEditableFields = ['id', 'roleId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'roleId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useAdminRbacRules.ts b/src/hooks/useAdminRbacRules.ts
index 12ca79b..4daab54 100644
--- a/src/hooks/useAdminRbacRules.ts
+++ b/src/hooks/useAdminRbacRules.ts
@@ -182,7 +182,7 @@ export function useRbacRules() {
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'ruleId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'ruleId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -322,7 +322,7 @@ export function useRbacRules() {
return false;
}
// Filter out ID fields and other auto-generated fields
- const nonEditableFields = ['id', 'ruleId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'ruleId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useAutomations.ts b/src/hooks/useAutomations.ts
index 28897ac..80cf737 100644
--- a/src/hooks/useAutomations.ts
+++ b/src/hooks/useAutomations.ts
@@ -536,7 +536,7 @@ export function useAutomationTemplates() {
return await fetchAutomationTemplateById(request, templateId);
}, [request]);
- const createTemplate = useCallback(async (data: Omit) => {
+ const createTemplate = useCallback(async (data: Omit) => {
return await createAutomationTemplateApi(request, data);
}, [request]);
diff --git a/src/hooks/useInstancePermissions.tsx b/src/hooks/useInstancePermissions.tsx
index 3d13ca7..048c27c 100644
--- a/src/hooks/useInstancePermissions.tsx
+++ b/src/hooks/useInstancePermissions.tsx
@@ -83,11 +83,11 @@ export function useTablePermission(tableName: string) {
canDelete: hasAccess(permission.delete),
// Record-basierte Prüfungen
- canReadRecord: (record: { _createdBy?: string }) =>
+ canReadRecord: (record: { sysCreatedBy?: string }) =>
canAccessRecord(permission.read, record, userId),
- canUpdateRecord: (record: { _createdBy?: string }) =>
+ canUpdateRecord: (record: { sysCreatedBy?: string }) =>
canAccessRecord(permission.update, record, userId),
- canDeleteRecord: (record: { _createdBy?: string }) =>
+ canDeleteRecord: (record: { sysCreatedBy?: string }) =>
canAccessRecord(permission.delete, record, userId),
};
}
@@ -296,7 +296,7 @@ export function useInstancePermissions(): InstancePermissions | undefined {
*/
export function useCanEditRecord(
tableName: string,
- record: { _createdBy?: string } | undefined,
+ record: { sysCreatedBy?: string } | undefined,
userId: string
): boolean {
const { update } = useTablePermission(tableName);
@@ -311,7 +311,7 @@ export function useCanEditRecord(
*/
export function useCanDeleteRecord(
tableName: string,
- record: { _createdBy?: string } | undefined,
+ record: { sysCreatedBy?: string } | undefined,
userId: string
): boolean {
const { delete: deleteLevel } = useTablePermission(tableName);
@@ -329,7 +329,7 @@ interface PermissionGateProps {
table?: string;
view?: string;
action?: 'view' | 'read' | 'create' | 'update' | 'delete';
- record?: { _createdBy?: string };
+ record?: { sysCreatedBy?: string };
children: React.ReactNode;
fallback?: React.ReactNode;
}
diff --git a/src/hooks/usePrompts.ts b/src/hooks/usePrompts.ts
index bc5c3a5..0454e37 100644
--- a/src/hooks/usePrompts.ts
+++ b/src/hooks/usePrompts.ts
@@ -157,7 +157,7 @@ export function usePrompts() {
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -367,7 +367,7 @@ export function usePrompts() {
return false;
}
// Filter out ID fields and other auto-generated fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -530,7 +530,7 @@ export function usePromptOperations() {
try {
// Pass all provided fields (supports partial inline updates like isSystem toggle)
- const { id, mandateId, _createdBy, _createdAt, _modifiedAt, _permissions, ...requestBody } = updateData;
+ const { id, mandateId, sysCreatedBy, sysCreatedAt, sysModifiedAt, _permissions, ...requestBody } = updateData;
const updatedPrompt = await updatePromptApi(request, promptId, requestBody as UpdatePromptData);
diff --git a/src/hooks/useRealEstate.ts b/src/hooks/useRealEstate.ts
index c710d74..35e320c 100644
--- a/src/hooks/useRealEstate.ts
+++ b/src/hooks/useRealEstate.ts
@@ -165,7 +165,7 @@ function _createRealEstateEntityHook(config: RealEstat
.filter(attr => {
if (attr.readonly === true || attr.editable === false) return false;
if (attr.name === 'id') return false;
- const nonEditable = ['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt'];
+ const nonEditable = ['sysCreatedBy', 'sysCreatedAt', 'sysModifiedBy', 'sysModifiedAt'];
return !nonEditable.includes(attr.name);
})
.map(attr => {
@@ -210,7 +210,7 @@ function _createRealEstateEntityHook(config: RealEstat
const generateCreateFieldsFromAttributes = useCallback(() => {
if (!attributes || attributes.length === 0) return [];
return attributes
- .filter(attr => !['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt', 'mandateId', 'featureInstanceId'].includes(attr.name))
+ .filter(attr => !['sysCreatedBy', 'sysCreatedAt', 'sysModifiedBy', 'sysModifiedAt', 'mandateId', 'featureInstanceId'].includes(attr.name))
.map(attr => {
let fieldType: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' | 'number' = 'string';
let options: Array<{ value: string | number; label: string }> | undefined;
diff --git a/src/hooks/useTrustee.ts b/src/hooks/useTrustee.ts
index 244a45e..08ba6d6 100644
--- a/src/hooks/useTrustee.ts
+++ b/src/hooks/useTrustee.ts
@@ -218,7 +218,7 @@ function _createTrusteeEntityHook(config: TrusteeEntit
if (attr.name === 'id') {
return false;
}
- const nonEditableFields = ['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt'];
+ const nonEditableFields = ['sysCreatedBy', 'sysCreatedAt', 'sysModifiedBy', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -284,7 +284,7 @@ function _createTrusteeEntityHook(config: TrusteeEntit
return attributes
.filter(attr => {
- const systemFields = ['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt', 'mandateId'];
+ const systemFields = ['sysCreatedBy', 'sysCreatedAt', 'sysModifiedBy', 'sysModifiedAt', 'mandateId'];
return !systemFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteeAccess.ts b/src/hooks/useTrusteeAccess.ts
index 3208aef..6e1db73 100644
--- a/src/hooks/useTrusteeAccess.ts
+++ b/src/hooks/useTrusteeAccess.ts
@@ -175,7 +175,7 @@ export function useTrusteeAccess() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['id', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['id', 'mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteeContracts.ts b/src/hooks/useTrusteeContracts.ts
index 8aa9f0c..0b628c1 100644
--- a/src/hooks/useTrusteeContracts.ts
+++ b/src/hooks/useTrusteeContracts.ts
@@ -175,7 +175,7 @@ export function useTrusteeContracts() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['id', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['id', 'mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteeDocuments.ts b/src/hooks/useTrusteeDocuments.ts
index 9dcb79b..2453b0d 100644
--- a/src/hooks/useTrusteeDocuments.ts
+++ b/src/hooks/useTrusteeDocuments.ts
@@ -176,7 +176,7 @@ export function useTrusteeDocuments() {
return false;
}
// documentData is handled separately (binary upload)
- const nonEditableFields = ['id', 'documentData', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['id', 'documentData', 'mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteeOrganisations.ts b/src/hooks/useTrusteeOrganisations.ts
index 8f94f6a..11eb9d1 100644
--- a/src/hooks/useTrusteeOrganisations.ts
+++ b/src/hooks/useTrusteeOrganisations.ts
@@ -174,7 +174,7 @@ export function useTrusteeOrganisations() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteePositionDocuments.ts b/src/hooks/useTrusteePositionDocuments.ts
index 7661d06..e55d053 100644
--- a/src/hooks/useTrusteePositionDocuments.ts
+++ b/src/hooks/useTrusteePositionDocuments.ts
@@ -163,7 +163,7 @@ export function useTrusteePositionDocuments() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['id', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['id', 'mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteePositions.ts b/src/hooks/useTrusteePositions.ts
index d73a700..c2a51c2 100644
--- a/src/hooks/useTrusteePositions.ts
+++ b/src/hooks/useTrusteePositions.ts
@@ -178,7 +178,7 @@ export function useTrusteePositions() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['id', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['id', 'mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useTrusteeRoles.ts b/src/hooks/useTrusteeRoles.ts
index 4e9e617..5be6605 100644
--- a/src/hooks/useTrusteeRoles.ts
+++ b/src/hooks/useTrusteeRoles.ts
@@ -176,7 +176,7 @@ export function useTrusteeRoles() {
if (attr.readonly === true || attr.editable === false) {
return false;
}
- const nonEditableFields = ['mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
+ const nonEditableFields = ['mandate', 'sysCreatedBy', 'sysModifiedBy', 'sysCreatedAt', 'sysModifiedAt'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useUsers.ts b/src/hooks/useUsers.ts
index 49f1a44..130c285 100644
--- a/src/hooks/useUsers.ts
+++ b/src/hooks/useUsers.ts
@@ -412,7 +412,7 @@ export function useOrgUsers() {
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
@@ -560,7 +560,7 @@ export function useOrgUsers() {
return false;
}
// Filter out ID fields and other auto-generated fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete', 'authenticationAuthority'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete', 'authenticationAuthority'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/hooks/useWorkflows.ts b/src/hooks/useWorkflows.ts
index 512ee41..9a45caf 100644
--- a/src/hooks/useWorkflows.ts
+++ b/src/hooks/useWorkflows.ts
@@ -224,7 +224,7 @@ export function useUserWorkflows(options?: { instanceId?: string; featureCode?:
return false; // Don't show readonly fields in edit form
}
// Also filter out common non-editable fields
- const nonEditableFields = ['id', 'mandateId', '_createdBy', '_hideDelete'];
+ const nonEditableFields = ['id', 'mandateId', 'sysCreatedBy', '_hideDelete'];
return !nonEditableFields.includes(attr.name);
})
.map(attr => {
diff --git a/src/pages/basedata/ConnectionsPage.tsx b/src/pages/basedata/ConnectionsPage.tsx
index 0a027b8..bcef411 100644
--- a/src/pages/basedata/ConnectionsPage.tsx
+++ b/src/pages/basedata/ConnectionsPage.tsx
@@ -204,7 +204,7 @@ export const ConnectionsPage: React.FC = () => {
// Form attributes for edit modal
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'userId', '_createdBy', '_createdAt', '_modifiedAt', 'connectedAt', 'lastChecked'];
+ const excludedFields = ['id', 'mandateId', 'userId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'connectedAt', 'lastChecked'];
return (attributes || [])
.filter(attr => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/basedata/FilesPage.tsx b/src/pages/basedata/FilesPage.tsx
index 57eb64e..baa530e 100644
--- a/src/pages/basedata/FilesPage.tsx
+++ b/src/pages/basedata/FilesPage.tsx
@@ -142,7 +142,7 @@ export const FilesPage: React.FC = () => {
}));
cols.push({
- key: '_createdBy',
+ key: 'sysCreatedBy',
label: 'Created By',
type: 'text' as any,
sortable: true,
@@ -289,7 +289,7 @@ export const FilesPage: React.FC = () => {
}, [selectedFolderId, _tableRefetch]);
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'fileHash', '_createdBy', '_createdAt', '_modifiedAt', 'creationDate', 'source'];
+ const excludedFields = ['id', 'mandateId', 'fileHash', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'creationDate', 'source'];
return (attributes || []).filter(attr => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/basedata/PromptsPage.tsx b/src/pages/basedata/PromptsPage.tsx
index f4835e9..edeca0c 100644
--- a/src/pages/basedata/PromptsPage.tsx
+++ b/src/pages/basedata/PromptsPage.tsx
@@ -53,7 +53,7 @@ export const PromptsPage: React.FC = () => {
// Generate columns from attributes - exclude ID fields from display
const columns = useMemo(() => {
// Fields to hide in table view
- const hiddenColumns = ['id', 'mandateId', '_createdAt', '_modifiedAt', '_hideDelete', '_permissions'];
+ const hiddenColumns = ['id', 'mandateId', 'sysCreatedAt', 'sysModifiedAt', '_hideDelete', '_permissions'];
const cols = (attributes || [])
.filter(attr => !hiddenColumns.includes(attr.name))
@@ -71,9 +71,9 @@ export const PromptsPage: React.FC = () => {
fkDisplayField: (attr as any).fkDisplayField,
}));
- // Add _createdBy column with FK resolution to show username
+ // Add sysCreatedBy column with FK resolution to show username
cols.push({
- key: '_createdBy',
+ key: 'sysCreatedBy',
label: 'Created By',
type: 'text' as any,
sortable: true,
@@ -148,7 +148,7 @@ export const PromptsPage: React.FC = () => {
// Form attributes for create/edit modal
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'isSystem', '_createdBy', '_createdAt', '_modifiedAt', '_hideDelete', '_permissions'];
+ const excludedFields = ['id', 'mandateId', 'isSystem', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', '_hideDelete', '_permissions'];
return (attributes || [])
.filter(attr => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/automation/AutomationDefinitionsView.tsx b/src/pages/views/automation/AutomationDefinitionsView.tsx
index de2a064..ea5fd93 100644
--- a/src/pages/views/automation/AutomationDefinitionsView.tsx
+++ b/src/pages/views/automation/AutomationDefinitionsView.tsx
@@ -110,9 +110,9 @@ export const AutomationDefinitionsView: React.FC = () => {
const columns = useMemo(() => {
const hiddenColumns = [
- 'id', 'mandateId', 'featureInstanceId', '_createdBy', '_createdAt', '_modifiedAt',
+ 'id', 'mandateId', 'featureInstanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt',
'template', 'executionLogs', 'placeholders',
- '_createdByUserName', 'mandateName', 'featureInstanceName',
+ 'sysCreatedByUserName', 'mandateName', 'featureInstanceName',
];
const attrColumns = (attributes || [])
.filter(attr => !hiddenColumns.includes(attr.name))
@@ -130,7 +130,7 @@ export const AutomationDefinitionsView: React.FC = () => {
const enrichedColumns = [
{ key: 'mandateName', label: 'Mandant', type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 150, minWidth: 100, maxWidth: 250 },
{ key: 'featureInstanceName', label: 'Feature-Instanz', type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 160, minWidth: 100, maxWidth: 250 },
- { key: '_createdByUserName', label: 'Erstellt von', type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 150, minWidth: 100, maxWidth: 250 },
+ { key: 'sysCreatedByUserName', label: 'Erstellt von', type: 'text' as any, sortable: true, filterable: true, searchable: true, width: 150, minWidth: 100, maxWidth: 250 },
];
return [...attrColumns, ...enrichedColumns];
}, [attributes]);
diff --git a/src/pages/views/automation/AutomationTemplatesView.tsx b/src/pages/views/automation/AutomationTemplatesView.tsx
index 849a83f..a0bae0c 100644
--- a/src/pages/views/automation/AutomationTemplatesView.tsx
+++ b/src/pages/views/automation/AutomationTemplatesView.tsx
@@ -52,7 +52,7 @@ export const AutomationTemplatesView: React.FC = () => {
value ? System
: Instanz
},
- { key: '_createdByUserName', label: 'Erstellt von', type: 'string' as const, width: 150 },
+ { key: 'sysCreatedByUserName', label: 'Erstellt von', type: 'string' as const, width: 150 },
], []);
const handleEditClick = async (template: AutomationTemplate) => {
diff --git a/src/pages/views/realestate/RealEstateParcelsView.tsx b/src/pages/views/realestate/RealEstateParcelsView.tsx
index 939af4f..d93c472 100644
--- a/src/pages/views/realestate/RealEstateParcelsView.tsx
+++ b/src/pages/views/realestate/RealEstateParcelsView.tsx
@@ -110,7 +110,7 @@ export const RealEstateParcelsView: React.FC = () => {
};
const formAttributes = useMemo(() => {
- const excluded = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excluded = ['id', 'mandateId', 'instanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return (attributes || []).filter(attr => !excluded.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/realestate/RealEstateProjectsView.tsx b/src/pages/views/realestate/RealEstateProjectsView.tsx
index 63ac061..25085e2 100644
--- a/src/pages/views/realestate/RealEstateProjectsView.tsx
+++ b/src/pages/views/realestate/RealEstateProjectsView.tsx
@@ -106,7 +106,7 @@ export const RealEstateProjectsView: React.FC = () => {
};
const formAttributes = useMemo(() => {
- const excluded = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excluded = ['id', 'mandateId', 'instanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return (attributes || []).filter(attr => !excluded.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/trustee/TrusteeDocumentsView.tsx b/src/pages/views/trustee/TrusteeDocumentsView.tsx
index 6cac4db..7def6c7 100644
--- a/src/pages/views/trustee/TrusteeDocumentsView.tsx
+++ b/src/pages/views/trustee/TrusteeDocumentsView.tsx
@@ -150,7 +150,7 @@ export const TrusteeDocumentsView: React.FC = () => {
// Form attributes (exclude system fields)
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excludedFields = ['id', 'mandateId', 'instanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return (attributes || []).filter(attr => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/trustee/TrusteePositionDocumentsView.tsx b/src/pages/views/trustee/TrusteePositionDocumentsView.tsx
index b514d48..5aaecfa 100644
--- a/src/pages/views/trustee/TrusteePositionDocumentsView.tsx
+++ b/src/pages/views/trustee/TrusteePositionDocumentsView.tsx
@@ -52,7 +52,7 @@ export const TrusteePositionDocumentsView: React.FC = () => {
if (!attributes || attributes.length === 0) return [];
// Exclude system fields from table columns
- const excludedFields = ['id', 'mandateId', 'featureInstanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excludedFields = ['id', 'mandateId', 'featureInstanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return attributes
.filter((attr: any) => !excludedFields.includes(attr.name))
@@ -127,7 +127,7 @@ export const TrusteePositionDocumentsView: React.FC = () => {
// Form attributes (exclude system fields)
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'featureInstanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excludedFields = ['id', 'mandateId', 'featureInstanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return (attributes || []).filter((attr: any) => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/trustee/TrusteePositionsView.tsx b/src/pages/views/trustee/TrusteePositionsView.tsx
index 7cf9e43..e60b9b6 100644
--- a/src/pages/views/trustee/TrusteePositionsView.tsx
+++ b/src/pages/views/trustee/TrusteePositionsView.tsx
@@ -257,7 +257,7 @@ export const TrusteePositionsView: React.FC = () => {
const positionColumnOrder = [
'_documentRefs', // Belege (download icons)
'_syncStatus', // Sync-Status
- '_createdAt', // Erstellt am
+ 'sysCreatedAt', // Erstellt am
'valuta', // Valuta date
'tags',
'company',
@@ -372,7 +372,7 @@ export const TrusteePositionsView: React.FC = () => {
// Form attributes (exclude system fields)
const formAttributes = useMemo(() => {
- const excludedFields = ['id', 'mandateId', 'instanceId', '_createdBy', '_createdAt', '_modifiedAt', '_modifiedBy'];
+ const excludedFields = ['id', 'mandateId', 'instanceId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'sysModifiedBy'];
return (attributes || []).filter(attr => !excludedFields.includes(attr.name));
}, [attributes]);
diff --git a/src/pages/views/workspace/NeutralizationPanel.tsx b/src/pages/views/workspace/NeutralizationPanel.tsx
index a13d52d..bcb0231 100644
--- a/src/pages/views/workspace/NeutralizationPanel.tsx
+++ b/src/pages/views/workspace/NeutralizationPanel.tsx
@@ -60,7 +60,7 @@ const NeutralizationPanel: React.FC = ({ instanceId })
patternType: m.patternType || 'unknown',
fileId: m.fileId,
fileName: m.fileName,
- createdAt: m.createdAt || m._createdAt,
+ createdAt: m.createdAt || m.sysCreatedAt,
})));
} catch (err) {
console.error('Failed to load mappings:', err);
diff --git a/src/types/mandate.ts b/src/types/mandate.ts
index 0d695b7..5430a3a 100644
--- a/src/types/mandate.ts
+++ b/src/types/mandate.ts
@@ -322,14 +322,14 @@ export function hasAccess(level: AccessLevel): boolean {
*/
export function canAccessRecord(
level: AccessLevel,
- record: { _createdBy?: string },
+ record: { sysCreatedBy?: string },
userId: string
): boolean {
switch (level) {
case 'n':
return false;
case 'm':
- return record._createdBy === userId;
+ return record.sysCreatedBy === userId;
case 'g':
case 'a':
return true;