From 5e4913cbcd0bcc54c0f1c9f6f88979c210b8a971 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Tue, 14 Jul 2026 14:23:42 +0700 Subject: [PATCH] fix: proper hr members update Signed-off-by: Alexander Onnikov --- models/hr/src/migration.ts | 54 +++++++++- models/server-hr/src/index.ts | 8 ++ .../src/components/DepartmentCard.svelte | 3 +- .../src/components/DepartmentStaff.svelte | 22 ++-- .../src/components/ScheduleView.svelte | 61 ++++------- .../components/schedule/StaffPresenter.svelte | 3 +- server-plugins/hr-resources/src/index.ts | 101 +++++++++++++++--- server-plugins/hr/src/index.ts | 1 + 8 files changed, 187 insertions(+), 66 deletions(-) diff --git a/models/hr/src/migration.ts b/models/hr/src/migration.ts index a0fa8fe9e8a..366bd38a7a7 100644 --- a/models/hr/src/migration.ts +++ b/models/hr/src/migration.ts @@ -22,7 +22,8 @@ import { DOMAIN_MODEL_TX, type TxCUD } from '@hcengineering/core' -import { type Department } from '@hcengineering/hr' +import contact, { type Employee, type Person } from '@hcengineering/contact' +import { type Department, type Staff } from '@hcengineering/hr' import { migrateSpace, tryMigrate, @@ -32,6 +33,7 @@ import { type MigrationUpgradeClient } from '@hcengineering/model' import core, { DOMAIN_SPACE, getAccountsFromTxes } from '@hcengineering/model-core' +import { DOMAIN_CONTACT } from '@hcengineering/model-contact' import hr, { DOMAIN_HR, hrId } from './index' @@ -103,6 +105,52 @@ async function migrateDepartmentMembersToEmployee (client: MigrationClient): Pro } } +async function rebuildDepartmentMembersFromStaff (client: MigrationClient): Promise { + const departments = await client.find(DOMAIN_HR, { _class: hr.class.Department }) + const departmentById = new Map(departments.map((department) => [department._id, department])) + const membersByDepartment = new Map, Set>>( + departments.map((department) => [department._id, new Set>()]) + ) + + const getHierarchy = (department: Ref): Ref[] => { + const result: Ref[] = [] + let current: Ref | undefined = department + + while (current !== undefined) { + if (result.includes(current)) { + break + } + + const currentDepartment = departmentById.get(current) + if (currentDepartment === undefined) { + break + } + + result.push(currentDepartment._id) + current = currentDepartment.parent ?? (currentDepartment._id !== hr.ids.Head ? hr.ids.Head : undefined) + } + + return result + } + + const persons = await client.find(DOMAIN_CONTACT, { _class: contact.class.Person }) + for (const person of persons) { + const staff = client.hierarchy.asIf(person, hr.mixin.Staff) + if (staff?.department === undefined || !staff.active) { + continue + } + + for (const department of getHierarchy(staff.department)) { + membersByDepartment.get(department)?.add(person._id as Ref) + } + } + + for (const department of departments) { + const members = Array.from(membersByDepartment.get(department._id) ?? []) + await client.update(DOMAIN_HR, { _id: department._id }, { members }) + } +} + export const hrOperation: MigrateOperation = { async migrate (client: MigrationClient, mode): Promise { await tryMigrate(mode, client, hrId, [ @@ -120,6 +168,10 @@ export const hrOperation: MigrateOperation = { { state: 'migrateDepartmentMembersToEmployee', func: migrateDepartmentMembersToEmployee + }, + { + state: 'rebuildDepartmentMembersFromStaff', + func: rebuildDepartmentMembersFromStaff } ]) }, diff --git a/models/server-hr/src/index.ts b/models/server-hr/src/index.ts index 5370433f12b..d936356bdf7 100644 --- a/models/server-hr/src/index.ts +++ b/models/server-hr/src/index.ts @@ -41,6 +41,14 @@ export function createModel (builder: Builder): void { } }) + builder.createDoc(serverCore.class.Trigger, core.space.Model, { + trigger: serverHr.trigger.OnDepartmentUpdate, + txMatch: { + objectClass: hr.class.Department, + _class: core.class.TxUpdateDoc + } + }) + builder.createDoc(serverCore.class.Trigger, core.space.Model, { trigger: serverHr.trigger.OnRequestCreate, txMatch: { diff --git a/plugins/hr-resources/src/components/DepartmentCard.svelte b/plugins/hr-resources/src/components/DepartmentCard.svelte index a23c2c6d3fe..611e8774100 100644 --- a/plugins/hr-resources/src/components/DepartmentCard.svelte +++ b/plugins/hr-resources/src/components/DepartmentCard.svelte @@ -77,7 +77,8 @@ $: dragPersonId = dragPerson?._id - $: values = allEmployees.filter((it) => it.department === value._id && it._id !== dragPersonId) + $: members = new Set>(value.members as Ref[]) + $: values = allEmployees.filter((it) => members.has(it._id) && it._id !== dragPersonId) $: dragging = value._id === dragOver?._id && dragPersonId !== undefined diff --git a/plugins/hr-resources/src/components/DepartmentStaff.svelte b/plugins/hr-resources/src/components/DepartmentStaff.svelte index a7f5979792c..ba809b73fa1 100644 --- a/plugins/hr-resources/src/components/DepartmentStaff.svelte +++ b/plugins/hr-resources/src/components/DepartmentStaff.svelte @@ -13,10 +13,10 @@ // limitations under the License. --> diff --git a/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte b/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte index c5870bdad90..7c9d662f6fe 100644 --- a/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte +++ b/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte @@ -14,7 +14,8 @@ -->