Update changes
Dieser Commit ist enthalten in:
@ -11,6 +11,7 @@ import { FieldEncryption } from '../services/encryption'
|
||||
import { emailService } from '../services/emailService'
|
||||
import { logger } from '../utils/logger'
|
||||
import { createDepartmentResolver } from '../utils/department'
|
||||
import { decodeHtmlEntities } from '../utils/html'
|
||||
|
||||
|
||||
const router = Router()
|
||||
@ -205,6 +206,23 @@ router.get('/', authenticate, requirePermission('employees:read'), async (req: A
|
||||
primaryUnitId: emp.primary_unit_id,
|
||||
})
|
||||
|
||||
// Prefer freshly stored department path if it differs from resolver (e.g., after profile update but before assignment sync)
|
||||
const storedDeptRaw = (decodeHtmlEntities(emp.department) ?? emp.department ?? '').trim()
|
||||
const splitStored = (() => {
|
||||
const sep = ' -> '
|
||||
const idx = storedDeptRaw.lastIndexOf(sep)
|
||||
if (idx === -1) return { path: storedDeptRaw, task: undefined as string | undefined }
|
||||
return { path: storedDeptRaw.slice(0, idx) || storedDeptRaw, task: storedDeptRaw.slice(idx + sep.length) || undefined }
|
||||
})()
|
||||
const resolvedLabel = (departmentInfo.label || '').trim()
|
||||
const last = (s: string) => s.split(' -> ').map(p => p.trim()).filter(Boolean).pop() || ''
|
||||
const storedLast = last(splitStored.path)
|
||||
const resolvedLast = last(resolvedLabel)
|
||||
const finalLabel = (storedLast && resolvedLast && storedLast !== resolvedLast)
|
||||
? splitStored.path
|
||||
: (resolvedLabel || splitStored.path)
|
||||
const finalTasks = splitStored.task || departmentInfo.tasks
|
||||
|
||||
const employee: Employee = {
|
||||
id: emp.id,
|
||||
firstName: emp.first_name,
|
||||
@ -213,9 +231,9 @@ router.get('/', authenticate, requirePermission('employees:read'), async (req: A
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: departmentInfo.label || emp.department,
|
||||
department: finalLabel,
|
||||
departmentDescription: departmentInfo.description,
|
||||
departmentTasks: departmentInfo.tasks,
|
||||
departmentTasks: finalTasks,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
mobile: emp.mobile,
|
||||
@ -298,6 +316,23 @@ router.get('/public', authenticate, async (req: AuthRequest, res, next) => {
|
||||
primaryUnitId: emp.primary_unit_id,
|
||||
})
|
||||
|
||||
// Prefer freshly stored department path if it differs from resolver (e.g., after profile update but before assignment sync)
|
||||
const storedDeptRaw = (decodeHtmlEntities(emp.department) ?? emp.department ?? '').trim()
|
||||
const splitStored = (() => {
|
||||
const sep = ' -> '
|
||||
const idx = storedDeptRaw.lastIndexOf(sep)
|
||||
if (idx === -1) return { path: storedDeptRaw, task: undefined as string | undefined }
|
||||
return { path: storedDeptRaw.slice(0, idx) || storedDeptRaw, task: storedDeptRaw.slice(idx + sep.length) || undefined }
|
||||
})()
|
||||
const resolvedLabel = (departmentInfo.label || '').trim()
|
||||
const last = (s: string) => s.split(' -> ').map(p => p.trim()).filter(Boolean).pop() || ''
|
||||
const storedLast = last(splitStored.path)
|
||||
const resolvedLast = last(resolvedLabel)
|
||||
const finalLabel = (storedLast && resolvedLast && storedLast !== resolvedLast)
|
||||
? splitStored.path
|
||||
: (resolvedLabel || splitStored.path)
|
||||
const finalTasks = splitStored.task || departmentInfo.tasks
|
||||
|
||||
const employee: Employee = {
|
||||
id: emp.id,
|
||||
firstName: emp.first_name,
|
||||
@ -306,9 +341,9 @@ router.get('/public', authenticate, async (req: AuthRequest, res, next) => {
|
||||
photo: emp.photo,
|
||||
position: emp.position,
|
||||
officialTitle: emp.official_title || undefined,
|
||||
department: departmentInfo.label || emp.department,
|
||||
department: finalLabel,
|
||||
departmentDescription: departmentInfo.description,
|
||||
departmentTasks: departmentInfo.tasks,
|
||||
departmentTasks: finalTasks,
|
||||
email: emp.email,
|
||||
phone: emp.phone,
|
||||
mobile: emp.mobile,
|
||||
|
||||
@ -53,16 +53,21 @@ const splitPathAndTask = (value?: string | null): { path: string; task?: string
|
||||
const normalized = normalizeDepartment(value)
|
||||
if (!normalized) return { path: '' }
|
||||
const separator = ' -> '
|
||||
const lastIndex = normalized.lastIndexOf(separator)
|
||||
if (lastIndex === -1) {
|
||||
const segments = normalized.split(separator).map(s => s.trim()).filter(Boolean)
|
||||
if (segments.length <= 1) {
|
||||
return { path: normalized }
|
||||
}
|
||||
const path = normalized.slice(0, lastIndex)
|
||||
const task = normalized.slice(lastIndex + separator.length)
|
||||
return {
|
||||
path: path || normalized,
|
||||
task: task || undefined
|
||||
const lastSeg = segments[segments.length - 1]
|
||||
// Heuristik: Wenn das letzte Segment wie ein Organisationscode aussieht (z. B. "Abt 4", "Dez 41", "SG 41.1"),
|
||||
// ist es Teil der Hierarchie und KEIN Aufgaben-Text. In dem Fall nichts abtrennen.
|
||||
const CODE_LIKE_REGEX = /^(dir|lka\s*nrw|lstab|za(\s*\d+)?|abt\.?\s*\d+|abteilung\s*\d+|dez\.?\s*\d+[a-z]?|dezernat\s*\d+[a-z]?|sg\s*\d+(?:\.\d+)?|td\s*\d+(?:\.\d+)?)$/i
|
||||
if (CODE_LIKE_REGEX.test(lastSeg)) {
|
||||
return { path: normalized }
|
||||
}
|
||||
// Andernfalls letzte Komponente als Aufgaben-Text behandeln
|
||||
const path = segments.slice(0, -1).join(separator)
|
||||
const task = lastSeg
|
||||
return { path: path || normalized, task: task || undefined }
|
||||
}
|
||||
|
||||
export const formatDepartmentWithDescription = (
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren