mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-11 12:57:59 +00:00
TSK-1236: trigger to remove members when deleting department. Fix for already broken departments (#3120)
Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
parent
239d4da6ce
commit
8d20a510d4
@ -13,8 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { Employee } from '@hcengineering/contact'
|
import contact, { Employee } from '@hcengineering/contact'
|
||||||
import { DOMAIN_TX, TxCollectionCUD, TxCreateDoc, TxOperations, TxUpdateDoc } from '@hcengineering/core'
|
import { DOMAIN_TX, Ref, toIdMap, TxCollectionCUD, TxCreateDoc, TxOperations, TxUpdateDoc } from '@hcengineering/core'
|
||||||
import { Department, Request, TzDate } from '@hcengineering/hr'
|
import { Department, Request, TzDate } from '@hcengineering/hr'
|
||||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model'
|
||||||
import core, { DOMAIN_SPACE } from '@hcengineering/model-core'
|
import core, { DOMAIN_SPACE } from '@hcengineering/model-core'
|
||||||
@ -42,6 +42,57 @@ async function createSpace (tx: TxOperations): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fixDuplicatesInDepartments (tx: TxOperations): Promise<void> {
|
||||||
|
const departments = await tx.findAll(hr.class.Department, {})
|
||||||
|
const departmentUpdate = departments.map((department) => {
|
||||||
|
const uniqueMembers = [...new Set(department.members)]
|
||||||
|
return tx.update(department, { members: uniqueMembers })
|
||||||
|
})
|
||||||
|
await Promise.all(departmentUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fixDepartmentsFromStaff (tx: TxOperations): Promise<void> {
|
||||||
|
const departments = await tx.findAll(hr.class.Department, {})
|
||||||
|
const parentsWithDepartmentMap: Map<Ref<Department>, Department[]> = new Map()
|
||||||
|
const departmentsMap = toIdMap(departments)
|
||||||
|
const ancestors: Map<Ref<Department>, Ref<Department>> = new Map()
|
||||||
|
for (const department of departments) {
|
||||||
|
if (department._id === hr.ids.Head) continue
|
||||||
|
ancestors.set(department._id, department.space)
|
||||||
|
}
|
||||||
|
for (const departmentTest of departments) {
|
||||||
|
const parents: Department[] = parentsWithDepartmentMap.get(departmentTest._id) ?? []
|
||||||
|
let _id = departmentTest._id
|
||||||
|
while (true) {
|
||||||
|
const department = departmentsMap.get(_id)
|
||||||
|
if (department === undefined) break
|
||||||
|
if (!parents.includes(department)) parents.push(department)
|
||||||
|
const next = ancestors.get(department._id)
|
||||||
|
if (next === undefined) break
|
||||||
|
_id = next
|
||||||
|
}
|
||||||
|
parentsWithDepartmentMap.set(departmentTest._id, parents)
|
||||||
|
}
|
||||||
|
const staff = await tx.findAll(hr.mixin.Staff, {})
|
||||||
|
const promises = []
|
||||||
|
const employeeAccountByEmployeeMap = new Map(
|
||||||
|
(await tx.findAll(contact.class.EmployeeAccount, {})).map((ea) => [ea.employee, ea])
|
||||||
|
)
|
||||||
|
for (const st of staff) {
|
||||||
|
if (st.department == null) continue
|
||||||
|
const correctDepartments: Department[] = parentsWithDepartmentMap.get(st.department) ?? []
|
||||||
|
promises.push(
|
||||||
|
...departments
|
||||||
|
.filter((department) => !correctDepartments.includes(department))
|
||||||
|
.map((dep) => {
|
||||||
|
const employeeAccount = employeeAccountByEmployeeMap.get(st._id)
|
||||||
|
if (employeeAccount == null) return []
|
||||||
|
return tx.update(dep, { $pull: { members: employeeAccount._id } })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
await Promise.all(promises)
|
||||||
|
}
|
||||||
function toTzDate (date: number): TzDate {
|
function toTzDate (date: number): TzDate {
|
||||||
const res = new Date(date)
|
const res = new Date(date)
|
||||||
return {
|
return {
|
||||||
@ -181,5 +232,7 @@ export const hrOperation: MigrateOperation = {
|
|||||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
||||||
const tx = new TxOperations(client, core.account.System)
|
const tx = new TxOperations(client, core.account.System)
|
||||||
await createSpace(tx)
|
await createSpace(tx)
|
||||||
|
await fixDuplicatesInDepartments(tx)
|
||||||
|
await fixDepartmentsFromStaff(tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,15 @@ export function createModel (builder: Builder): void {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
|
trigger: serverHr.trigger.OnDepartmentRemove,
|
||||||
|
txMatch: {
|
||||||
|
_class: core.class.TxCollectionCUD,
|
||||||
|
'tx.objectClass': hr.class.Department,
|
||||||
|
'tx._class': core.class.TxRemoveDoc
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
trigger: serverHr.trigger.OnRequestCreate,
|
trigger: serverHr.trigger.OnRequestCreate,
|
||||||
txMatch: {
|
txMatch: {
|
||||||
|
@ -24,6 +24,7 @@ import core, {
|
|||||||
TxFactory,
|
TxFactory,
|
||||||
TxMixin,
|
TxMixin,
|
||||||
TxProcessor,
|
TxProcessor,
|
||||||
|
TxRemoveDoc,
|
||||||
TxUpdateDoc
|
TxUpdateDoc
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import hr, {
|
import hr, {
|
||||||
@ -155,6 +156,40 @@ export async function OnDepartmentStaff (tx: Tx, control: TriggerControl): Promi
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export async function OnDepartmentRemove (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
||||||
|
const ctx = TxProcessor.extractTx(tx) as TxRemoveDoc<Department>
|
||||||
|
|
||||||
|
const department = (await control.findAll(hr.class.Department, { _id: ctx.objectSpace as Ref<Department> }))[0]
|
||||||
|
|
||||||
|
const targetAccounts = await control.modelDb.findAll(contact.class.EmployeeAccount, {
|
||||||
|
_id: { $in: department.members }
|
||||||
|
})
|
||||||
|
const employeeIds = targetAccounts.map((acc) => acc.employee as Ref<Staff>)
|
||||||
|
|
||||||
|
const employee = await control.findAll(contact.class.Employee, {
|
||||||
|
_id: { $in: employeeIds }
|
||||||
|
})
|
||||||
|
const removed = await buildHierarchy(department._id, control)
|
||||||
|
const res: Tx[] = []
|
||||||
|
employee.forEach((em) => {
|
||||||
|
res.push(control.txFactory.createTxMixin(em._id, em._class, em.space, hr.mixin.Staff, { department: undefined }))
|
||||||
|
})
|
||||||
|
targetAccounts.forEach((acc) => {
|
||||||
|
res.push(
|
||||||
|
...getTxes(
|
||||||
|
control.txFactory,
|
||||||
|
acc._id,
|
||||||
|
[],
|
||||||
|
removed.map((p) => p._id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -399,6 +434,7 @@ export default async () => ({
|
|||||||
OnRequestUpdate,
|
OnRequestUpdate,
|
||||||
OnRequestRemove,
|
OnRequestRemove,
|
||||||
OnDepartmentStaff,
|
OnDepartmentStaff,
|
||||||
|
OnDepartmentRemove,
|
||||||
OnEmployeeDeactivate,
|
OnEmployeeDeactivate,
|
||||||
OnPublicHolidayCreate
|
OnPublicHolidayCreate
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,7 @@ export const serverHrId = 'server-hr' as Plugin
|
|||||||
export default plugin(serverHrId, {
|
export default plugin(serverHrId, {
|
||||||
trigger: {
|
trigger: {
|
||||||
OnDepartmentStaff: '' as Resource<TriggerFunc>,
|
OnDepartmentStaff: '' as Resource<TriggerFunc>,
|
||||||
|
OnDepartmentRemove: '' as Resource<TriggerFunc>,
|
||||||
OnRequestCreate: '' as Resource<TriggerFunc>,
|
OnRequestCreate: '' as Resource<TriggerFunc>,
|
||||||
OnRequestUpdate: '' as Resource<TriggerFunc>,
|
OnRequestUpdate: '' as Resource<TriggerFunc>,
|
||||||
OnRequestRemove: '' as Resource<TriggerFunc>,
|
OnRequestRemove: '' as Resource<TriggerFunc>,
|
||||||
|
Loading…
Reference in New Issue
Block a user