Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion models/hr/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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'

Expand Down Expand Up @@ -103,6 +105,52 @@ async function migrateDepartmentMembersToEmployee (client: MigrationClient): Pro
}
}

async function rebuildDepartmentMembersFromStaff (client: MigrationClient): Promise<void> {
const departments = await client.find<Department>(DOMAIN_HR, { _class: hr.class.Department })
const departmentById = new Map(departments.map((department) => [department._id, department]))
const membersByDepartment = new Map<Ref<Department>, Set<Ref<Employee>>>(
departments.map((department) => [department._id, new Set<Ref<Employee>>()])
)

const getHierarchy = (department: Ref<Department>): Ref<Department>[] => {
const result: Ref<Department>[] = []
let current: Ref<Department> | 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<Person>(DOMAIN_CONTACT, { _class: contact.class.Person })
for (const person of persons) {
const staff = client.hierarchy.asIf<Person, Staff>(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<Employee>)
}
}

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<void> {
await tryMigrate(mode, client, hrId, [
Expand All @@ -120,6 +168,10 @@ export const hrOperation: MigrateOperation = {
{
state: 'migrateDepartmentMembersToEmployee',
func: migrateDepartmentMembersToEmployee
},
{
state: 'rebuildDepartmentMembersFromStaff',
func: rebuildDepartmentMembersFromStaff
}
])
},
Expand Down
8 changes: 8 additions & 0 deletions models/server-hr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
3 changes: 2 additions & 1 deletion plugins/hr-resources/src/components/DepartmentCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@

$: dragPersonId = dragPerson?._id

$: values = allEmployees.filter((it) => it.department === value._id && it._id !== dragPersonId)
$: members = new Set<Ref<Staff>>(value.members as Ref<Staff>[])
$: values = allEmployees.filter((it) => members.has(it._id) && it._id !== dragPersonId)

$: dragging = value._id === dragOver?._id && dragPersonId !== undefined

Expand Down
22 changes: 9 additions & 13 deletions plugins/hr-resources/src/components/DepartmentStaff.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
// limitations under the License.
-->
<script lang="ts">
import contact from '@hcengineering/contact'
import contact, { Employee } from '@hcengineering/contact'
import { UsersPopup } from '@hcengineering/contact-resources'
import { Ref, WithLookup } from '@hcengineering/core'
import { Department, Staff } from '@hcengineering/hr'
import { Department } from '@hcengineering/hr'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, IconAdd, Label, Scroller, Section, eventToHTMLElement, showPopup } from '@hcengineering/ui'
import { Viewlet, ViewletPreference } from '@hcengineering/view'
Expand All @@ -42,27 +42,23 @@
}
)

function add (e: MouseEvent) {
function add (e: MouseEvent): void {
showPopup(
UsersPopup,
{
_class: contact.mixin.Employee,
docQuery: {
active: true
},
ignoreUsers: memberItems.map((it) => it._id)
ignoreUsers: members
},
eventToHTMLElement(e),
(res) => addMember(client, res, value)
)
}

let memberItems: Staff[] = []

const membersQuery = createQuery()
$: membersQuery.query(hr.mixin.Staff, { department: objectId }, (result) => {
memberItems = result
})
let members: Array<Ref<Employee>> = []
$: members = value?.members ?? []

let preference: ViewletPreference | undefined
let loading = false
Expand All @@ -85,14 +81,14 @@
</svelte:fragment>

<svelte:fragment slot="content">
{#if (value?.members.length ?? 0) > 0}
{#if members.length > 0}
<Scroller>
<Table
_class={hr.mixin.Staff}
config={preference?.config ?? viewlet?.config ?? []}
options={viewlet?.options}
query={{ department: objectId }}
loadingProps={{ length: value?.members.length ?? 0 }}
query={{ _id: { $in: members } }}
loadingProps={{ length: members.length }}
/>
</Scroller>
{:else}
Expand Down
61 changes: 23 additions & 38 deletions plugins/hr-resources/src/components/ScheduleView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
? getEndDate(currentDate.getFullYear(), 11)
: getEndDate(currentDate.getFullYear(), currentDate.getMonth())

$: departments = [department, ...getDescendants(department, descendants, new Set())]
$: staffIdsForOpenedDepartments = staff.filter((p) => departments.includes(p.department)).map((p) => p._id)
$: departmentMembers = new Set<Ref<Staff>>((departmentById.get(department)?.members ?? []) as Ref<Staff>[])
$: staffIdsForOpenedDepartments = staff.filter((p) => departmentMembers.has(p._id)).map((p) => p._id)

const lq = createQuery()
const typeQuery = createQuery()
Expand Down Expand Up @@ -81,23 +81,7 @@

let employeeRequests = new Map<Ref<Staff>, Request[]>()

function getDescendants (
department: Ref<Department>,
descendants: Map<Ref<Department>, Department[]>,
visited: Set<string>
): Ref<Department>[] {
const res = (descendants.get(department) ?? []).map((p) => p._id)
for (const department of res) {
const has = visited.has(department)
if (!has) {
visited.add(department)
res.push(...getDescendants(department, descendants, visited))
}
}
return res
}

let departmentStaff: Staff[]
let departmentStaff: Staff[] = []
let editableList: Ref<Employee>[] = []

function update (staffIdsForOpenedDepartments: Ref<Staff>[], startDate: Date, endDate: Date) {
Expand Down Expand Up @@ -136,14 +120,11 @@
function pushChilds (
department: Ref<Department>,
departmentStaff: Staff[],
descendants: Map<Ref<Department>, Department[]>
departmentById: Map<Ref<Department>, Department>
): void {
const staff = departmentStaff.filter((p) => p.department === department)
const members = new Set<Ref<Staff>>((departmentById.get(department)?.members ?? []) as Ref<Staff>[])
const staff = departmentStaff.filter((p) => members.has(p._id))
editableList.push(...staff.filter((p) => !editableList.includes(p._id)).map((p) => p._id))
const desc = descendants.get(department) ?? []
for (const des of desc) {
pushChilds(des._id, departmentStaff, descendants)
}
}

function isEditable (department: Department): boolean {
Expand All @@ -155,17 +136,17 @@
department: Ref<Department>,
departmentStaff: Staff[],
descendants: Map<Ref<Department>, Department[]>
) {
): void {
const dep = departmentById.get(department)
if (dep === undefined) return
if (isEditable(dep)) {
pushChilds(dep._id, departmentStaff, descendants)
pushChilds(dep._id, departmentStaff, departmentById)
} else {
const descendantDepartments = descendants.get(dep._id)
if (descendantDepartments !== undefined) {
for (const department of descendantDepartments) {
if (isEditable(department)) {
pushChilds(department._id, departmentStaff, descendants)
pushChilds(department._id, departmentStaff, departmentById)
} else {
checkDepartmentEditable(departmentById, department._id, departmentStaff, descendants)
}
Expand All @@ -178,23 +159,24 @@
departmentById: Map<Ref<Department>, Department>,
departmentStaff: Staff[],
descendants: Map<Ref<Department>, Department[]>
) {
): void {
editableList = [currentEmployee]
checkDepartmentEditable(departmentById, hr.ids.Head, departmentStaff, descendants)
editableList = editableList
}

function updateStaff (
staff: Staff[],
departments: Ref<Department>[],
staffIdsForOpenedDepartments: Ref<Staff>[],
descendants: Map<Ref<Department>, Department[]>,
departmentById: Map<Ref<Department>, Department>
) {
departmentStaff = staff.filter((p) => departments.includes(p.department))
): void {
const departmentMembers = new Set(staffIdsForOpenedDepartments)
departmentStaff = staff.filter((p) => departmentMembers.has(p._id))
updateEditableList(departmentById, departmentStaff, descendants)
}

$: updateStaff(staff, departments, descendants, departmentById)
$: updateStaff(staff, staffIdsForOpenedDepartments, descendants, departmentById)

const reportQuery = createQuery()

Expand Down Expand Up @@ -287,26 +269,29 @@
}
return map
}
let staffDepartmentMap = new Map()
let staffDepartmentMap = new Map<Ref<Staff>, Department[]>()
$: void getDepartmentsForEmployee(departmentStaff).then((res) => {
staffDepartmentMap = res
})

function getDepartmentHolidays (department: Ref<Department>): Date[] {
const parents = ancestors.get(department) ?? []

const result = []
const result = new Map<string, Date>()
const addHoliday = (holiday: Date): void => {
result.set(`${holiday.getFullYear()}-${holiday.getMonth()}-${holiday.getDate()}`, holiday)
}

// get own holidays
const holidays = holidaysMap.get(department) ?? []
result.push(...holidays)
holidays.forEach(addHoliday)

// get ancestor holidays
for (const parent of parents) {
const parentHolidays = holidaysMap.get(parent) ?? []
result.push(...parentHolidays)
parentHolidays.forEach(addHoliday)
}
return result
return [...result.values()]
}
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
-->
<script lang="ts">
import { getName } from '@hcengineering/contact'
import contact, { Avatar } from '@hcengineering/contact-resources'
import { Avatar } from '@hcengineering/contact-resources'
import contact from '@hcengineering/contact-resources/src/plugin'
import hr, { Department, Staff } from '@hcengineering/hr'
import { getClient } from '@hcengineering/presentation'
import { Label } from '@hcengineering/ui'
Expand Down
Loading