196 lines
5.7 KiB
Markdown
196 lines
5.7 KiB
Markdown
# System Fields - Quick Reference
|
|
|
|
## What Are System Fields?
|
|
|
|
Fields that are automatically managed by the system and should never require user input:
|
|
- `id` - Unique record identifier (UUID)
|
|
- `tenantId` - Tenant ownership
|
|
- `ownerId` - User who owns the record
|
|
- `created_at` - Record creation timestamp
|
|
- `updated_at` - Last modification timestamp
|
|
|
|
## Frontend Treatment
|
|
|
|
### Hidden from Edit Forms
|
|
System fields are automatically hidden from create/edit forms:
|
|
```
|
|
❌ Not visible to users
|
|
❌ Not validated
|
|
❌ Not submitted to API
|
|
```
|
|
|
|
### Visible on Detail/List Views (Read-Only)
|
|
System fields appear on detail and list views as read-only information:
|
|
```
|
|
✅ Visible to users (informational)
|
|
✅ Not editable
|
|
✅ Shows metadata about records
|
|
```
|
|
|
|
## Backend Treatment
|
|
|
|
### Auto-Set on Insert
|
|
When creating a record, Objection model hooks auto-set:
|
|
```javascript
|
|
{
|
|
$beforeInsert() {
|
|
if (!this.id) this.id = randomUUID();
|
|
if (!this.created_at) this.created_at = now();
|
|
if (!this.updated_at) this.updated_at = now();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Auto-Set on Update
|
|
When updating a record:
|
|
```javascript
|
|
{
|
|
$beforeUpdate() {
|
|
this.updated_at = now(); // Always update timestamp
|
|
}
|
|
}
|
|
```
|
|
|
|
### Protected from Updates
|
|
Backend filters out system fields in update requests:
|
|
```typescript
|
|
delete allowedData.ownerId; // Can't change owner
|
|
delete allowedData.id; // Can't change ID
|
|
delete allowedData.created_at; // Can't change creation time
|
|
delete allowedData.tenantId; // Can't change tenant
|
|
```
|
|
|
|
## Field Status Matrix
|
|
|
|
| Field | Value | Source | Immutable | User Editable |
|
|
|-------|-------|--------|-----------|---------------|
|
|
| id | UUID | System | ✓ Yes | ✗ No |
|
|
| tenantId | UUID | System | ✓ Yes | ✗ No |
|
|
| ownerId | UUID | Auth context | ✓ Yes* | ✗ No |
|
|
| created_at | Timestamp | Database | ✓ Yes | ✗ No |
|
|
| updated_at | Timestamp | Database | ✗ No** | ✗ No |
|
|
|
|
*ownerId: Set once on creation, immutable after
|
|
**updated_at: Changes on every update (automatic)
|
|
|
|
## How It Works
|
|
|
|
### Create Record
|
|
```
|
|
User form input:
|
|
┌─────────────────────┐
|
|
│ Name: "Acme Corp" │
|
|
│ Revenue: 1000000 │
|
|
└─────────────────────┘
|
|
↓
|
|
Backend Objection Model:
|
|
┌──────────────────────────────────────┐
|
|
│ INSERT INTO accounts ( │
|
|
│ id, ← Generated UUID │
|
|
│ name, ← User input │
|
|
│ revenue, ← User input │
|
|
│ ownerId, ← From auth │
|
|
│ created_at, ← Current timestamp │
|
|
│ updated_at, ← Current timestamp │
|
|
│ tenantId ← From context │
|
|
│ ) VALUES (...) │
|
|
└──────────────────────────────────────┘
|
|
```
|
|
|
|
### Update Record
|
|
```
|
|
User form input:
|
|
┌─────────────────────┐
|
|
│ Revenue: 1500000 │
|
|
└─────────────────────┘
|
|
↓
|
|
Backend filters:
|
|
┌──────────────────────────────────┐
|
|
│ UPDATE accounts SET │
|
|
│ revenue = 1500000, ← Allowed │
|
|
│ updated_at = now() ← Auto │
|
|
│ WHERE id = abc123 │
|
|
│ │
|
|
│ ownerId, created_at stay same │
|
|
└──────────────────────────────────┘
|
|
```
|
|
|
|
## Validation Errors - Solved
|
|
|
|
### Before Fix
|
|
```
|
|
"Owner is required"
|
|
"Created At is required"
|
|
"Updated At is required"
|
|
```
|
|
|
|
### After Fix
|
|
```
|
|
✓ No system field validation errors
|
|
✓ System fields hidden from forms
|
|
✓ System fields auto-managed by backend
|
|
```
|
|
|
|
## Field Detection Logic
|
|
|
|
Frontend identifies system fields by:
|
|
1. **Field name** - Known system field names
|
|
2. **isSystem flag** - Backend marker (`isSystem: true`)
|
|
|
|
Either condition causes field to be hidden from edit:
|
|
```typescript
|
|
const systemFieldNames = ['id', 'tenantId', 'ownerId', 'created_at', 'updated_at', ...]
|
|
const isSystemField = Boolean(fieldDef.isSystem)
|
|
const isAutoGeneratedField = systemFieldNames.includes(fieldDef.apiName)
|
|
|
|
if (isSystemField || isAutoGeneratedField) {
|
|
showOnEdit = false // Hide from edit form
|
|
}
|
|
```
|
|
|
|
## Backward Compatibility
|
|
|
|
✅ Works with:
|
|
- **New objects** - Created with proper flags
|
|
- **Old objects** - Flags added on-the-fly during retrieval
|
|
- **Mixed environments** - Both types work simultaneously
|
|
|
|
## Common Tasks
|
|
|
|
### Create a New Record
|
|
```
|
|
1. Click "Create [Object]"
|
|
2. See form with user-editable fields only
|
|
3. Fill in required fields
|
|
4. Click "Save"
|
|
5. System auto-sets: id, ownerId, created_at, updated_at ✓
|
|
```
|
|
|
|
### View Record Details
|
|
```
|
|
1. Click record name
|
|
2. See all fields including system fields
|
|
3. System fields shown read-only:
|
|
- Created: [date] (when created)
|
|
- Modified: [date] (when last updated)
|
|
- Owner: [user name] (who owns it) ✓
|
|
```
|
|
|
|
### Update Record
|
|
```
|
|
1. Click "Edit [Record]"
|
|
2. See form with user-editable fields only
|
|
3. Change values
|
|
4. Click "Save"
|
|
5. System auto-updates: updated_at ✓
|
|
6. ownerId and created_at unchanged ✓
|
|
```
|
|
|
|
## Related Files
|
|
|
|
- [SYSTEM_FIELDS_FIX.md](SYSTEM_FIELDS_FIX.md) - Detailed fix documentation
|
|
- [OWNER_FIELD_VALIDATION_FIX.md](OWNER_FIELD_VALIDATION_FIX.md) - Owner field specific fix
|
|
- [OBJECTION_MODEL_SYSTEM.md](OBJECTION_MODEL_SYSTEM.md) - Model system architecture
|
|
- [backend/src/object/object.service.ts](backend/src/object/object.service.ts#L278-L291) - Normalization code
|
|
- [frontend/composables/useFieldViews.ts](frontend/composables/useFieldViews.ts#L12-L20) - Frontend field detection
|