Skip to main content
Version: Latest
Technical Manual

Staff

The Staff module keeps one record for every person who works for the business: an employee, a contractor or a crew member, with or without a user account. Other modules build on it instead of keeping their own people records. Workforce schedules staff members, Contact Center agents and Point of Sale cashiers are staff members, Dispatch sends staff members to jobs, Scheduling books them, and Accounts names the staff who look after each account. Each of those modules adds its own card to the staff editor and its own capability to the record.

Feature IDNameDepends on
CrestApps.OrchardCore.StaffStaffCrestApps Users, Roles
CrestApps.OrchardCore.Staff.CompensationStaff CompensationStaff
CrestApps.OrchardCore.Staff.BadgesStaff BadgesStaff
CrestApps.OrchardCore.Staff.OrgChartStaff Organization ChartStaff, CrestApps Resources

Projects: CrestApps.OrchardCore.Staff.Abstractions (the StaffMember model and the contracts other modules use), CrestApps.OrchardCore.Staff.Core (the store, indexes and services), CrestApps.OrchardCore.Staff (the module).

Users and staff members​

A user is a sign-in account: a user name, a password and roles. Customers, partners and administrators are users too. A staff member is the employment record of someone who works for the business: job title, manager, teams, dates, pay and capabilities. A staff member can be linked to one user account, or to none at all, for people who are scheduled, sent to jobs or paid but never sign in.

The name and email have a single owner. For a linked staff member the user account owns them. The staff editor shows them as text with a Change them on the user account link instead of boxes, and the staff record keeps only a copy that stays in step with the account. Picking a user on a new staff record swaps the boxes for the account's name at once. A team member is something else: a staff member's dated row in a team.

A user account belongs to one staff member at most. The editor's user picker offers only accounts that aren't linked yet (the StaffUnlinked user audience), and saving refuses an account another staff member has. Once saved, the link is fixed: the editor shows the account as text, and changing or removing it is refused however the record is saved (editor, recipe or code), so pay, history and badges never move from one person to another. A staff member saved without an account can be linked once later. For another account, add a new staff member.

The staff member​

FieldNotes
UserIdThe linked Orchard user, optional and unique. Kiosk-only and seasonal people have none.
DisplayName, EmailFor a linked person, taken from the user (its display name, else its user name) every time the record is saved, and when the user changes. Other modules read them here and never copy them.
Phone, EmployeeNumber, ExternalIdThe employee number is unique and doubles as the badge number. ExternalId is the id in an HR or payroll system.
JobTitle, EmploymentType, StatusEmploymentType is FullTime, PartTime, Seasonal, Temporary, Contractor or Subcontractor; Status is Active, OnLeave, Suspended or Terminated.
HireDate, SeniorityDate, TerminationDate, DateOfBirthPure dates. The date of birth is sensitive: only people with View sensitive staff data see it. A person whose last working day has passed is terminated by the hourly upkeep task.
ManagerIdThe staff member the person reports to. A manager that doesn't exist, the person themselves, or a manager who reports to the person is refused.
PrimaryTeamId, TeamMembershipsDated memberships (TeamId, Role of Member/Lead/Scheduler/Manager, EffectiveFrom, EffectiveTo) in the shared Teams. The first membership is the main team.
TimeZoneId, HomeBase, WorkLocationThe home base is geocoded through Geo when it is on.
ContractedHoursPerWeekThe hours of the person's contract.
CapabilitiesThe kinds of work the person does, as registered by other modules (see Extension points).
PropertiesOther modules' data on the person, such as Workforce's scheduling hours (WorkforceStaffSettings), pay rates (StaffPayRates) and the badge PIN (StaffBadge).

Each staff member is a YesSql document in the Staff collection, with StaffMemberIndex, StaffTeamMembershipIndex (one row per membership, dates as yyyyMMdd numbers) and StaffCapabilityIndex. Every change to the job title, status, employment type, manager, teams, work location or last day adds a StaffHistoryEntry (who, when, from, to) to an append-only log, shown on the staff editor and in the Staff reports.

Admin screens​

Staff > All Staff lists staff members on Orchard Core's admin list, with a search and filters for team (while Teams is on), status and capability. People who may see all staff see everyone; a manager, including one who manages staff through another module (a Workforce team manager with Manage workers), sees the staff of the teams they manage, else their reports. Workforce has no worker list of its own: workers are staff members. The editor is built by display drivers, one shape per card, so modules and themes can add, move, replace or hide any of them:

CardShapeComes from
Person, Employment, PlaceStaffMemberFields_EditStaff
TeamsStaffTeams_EditTeams, while it is on
CapabilitiesStaffMemberCapabilities_EditStaff, listing what other modules register
Pay, BadgeStaffMemberPay_Edit, StaffMemberBadge_Editthe Staff Compensation and Staff Badges features
SkillsStaffMemberSkills_EditSkills
PhonePhoneStaff_EditTelephony (the person's extension)
AgentAgentStaff_EditContact Center
Workforce shiftsWorkforceStaffFields_EditWorkforce (hours, availability and shift rules)
Preferred technicians, fleet driverWorkOrderTechnicians_Edit, AssetFleetDriver_EditWork Orders and Assets, on their own editors

Staff > My Profile shows a person their own record and a My work list that other modules fill through IStaffHomeLinkProvider. Staff > Organization Chart (Staff Organization Chart feature) draws the reporting line as a chart you can zoom, pan, expand and collapse, with each person's picture (from the User Avatars feature, else their initials), job title and main team, using d3-org-chart. Settings > Staff turns on Offer only staff where people are assigned work.

Capabilities​

Capabilities put people in pools: who the dispatch board offers, who can take calls, who can be booked, who runs a register. Staff > Capabilities (people with Manage staff) lists them on an admin list:

  • Built in ones are seeded by the modules whose code relies on them. Admins change their label, description and order, or turn them off (Offered); Reset to defaults drops those changes. They can't be deleted or renamed.
  • Custom ones are added by admins with a key (letters, digits, dots, dashes, underscores; fixed once saved), a name, a description and a position, and can be deleted. Staff members who had a deleted one keep it until they are saved again.

A capability that is turned off isn't offered in the editor, filters, pickers or settings; staff members who have it keep it. IStaffCapabilityService lists the capabilities as they apply (ListAsync, FindAsync), saves (SaveAsync) and deletes or resets (DeleteAsync); the admin's records are kept in one document, StaffCapabilitiesDocument, and travel in the Staff recipe and deployment steps (Capabilities). StaffQuery.Capabilities finds staff with any of several, and the staff picker's capability argument takes several, comma-separated.

How good someone is at something belongs in Skills, which Dispatch and scheduling match on; capabilities only decide the pools.

The staff profile​

Choosing a person in the list opens their profile (Staff > All Staff > a name, staff/profile/{id}), the hub of everything about them, like an account's page. A header shows their picture or initials, name, job title, main team, status and user account, with Edit Staff Member for those who manage them. Down the side are the sections modules add; the selected one is kept in the address's hash (#staff-teams).

SectionFrom
Overview (employment, reporting line)Staff
TeamsTeams
Skills (skills and certificates, with Add a certificate)Staff's Skills integration
Work (shift rules, Time clock, Timesheets, Time off)Workforce
PayStaff Compensation (later Payroll)
Employment historyStaff

A module adds to the profile with a display driver on StaffMember for the StaffProfileSections.DisplayType (DetailAdmin) display type, placed with StaffProfileSections.Location(section, position), and registers a section of its own with services.AddPageSection(StaffProfileSections.PageName, name, title, icon, position). The page uses the shared page sections of the Resources module (PageSectionsOptions, the PageSections shape), the same as the account page.

The profile opens for people who may see all staff, for those who manage the person, and for the person themselves. The user editor's Staff card only makes a user a staff member, or links to their profile: the employment details live on the profile.

Teams are optional​

Staff doesn't need the Teams module. When Teams is on, it sets StaffOptions.UsesTeams and adds the Teams card, and Staff then uses team memberships for manager scoping (managers and schedulers of a team manage its members), the main team's time zone, the team filter, report columns and recipes. While Teams is off, Staff leaves team data alone.

The user editor gets a Staff card that makes the person a staff member, or edits their record in place, for anyone who may manage them.

Services​

ContractWhat it does
IStaffMemberManagerICatalogManager<StaffMember> plus FindByUserIdAsync, FindByEmployeeNumberAsync, GetByUserIdsAsync, SearchAsync(StaffQuery, skip, take) (text, team with its sub-teams, teams, status, has a user, capability, manager, ids), ListByTeamAsync, ListByTeamInRangeAsync and ListDirectReportsAsync.
IStaffDirectoryThe read side other modules use: IsStaffAsync(userId), FindByUserIdAsync, GetAsync(ids), GetNamesAsync(ids), GetNamesByUserIdAsync(userIds), SearchAsync(text, capability, requireUser, take) for pickers (working staff only), and GetCapabilities(). Answers are cached for the request.
IStaffHierarchyGetManagerChainAsync, GetReportsAsync(includeIndirect) and ManagesAsync, from one index read per request.
IStaffScopeServiceWhich staff a signed-in person may manage: everyone with Manage staff (or a module permission registered with AddStaffScopePermissions, such as Manage the whole workforce); with Manage the staff you manage (or Manage workers), their direct and indirect reports and the members of the teams where they are a Manager or Scheduler, with sub-teams.
IStaffTimeZoneResolverA person's zone: their own, else their main team's or its parents', else the site's (GetTimeZoneIdAsync); FindTimeZoneIdAsync stops before the site's, for modules with a fallback of their own, as Dispatch has.
IStaffAccountServiceEnsureAsync(userId, name, capabilities, defaults): makes sure the person doing a module's work is a staff member, as Contact Center does for agents, Point of Sale for cashiers and Scheduling for bookable people.
IStaffBadgeServiceSets, clears and checks the PIN used with the employee number at kiosks and registers (PBKDF2, a badge locks for 15 minutes after five wrong PINs). The Workforce time clock signs people in through it.
IStaffHistoryServiceLists a person's employment history, newest first.

Register the services with services.AddStaffCore(); it is safe to repeat. AddStaffSkillLinks() makes a staff member and their user one skill holder when Skills is on.

Extension points​

Contract or helperUse it for
DisplayDriver<StaffMember>Adding a card to the staff editor (Workforce scheduling, Contact Center agent, Telephony phone, Skills, Pay, Badge).
AddStaffCapability(name, displayName, description, position)Seeding a built-in capability a module's code relies on: Contact Center seeds Agent, Dispatch Technician, Scheduling Bookable, Point of Sale Cashier. Admins can relabel, reorder or turn it off under Staff > Capabilities, but not delete or rename it. Screens read capabilities through IStaffCapabilityService, never the code registrations.
IStaffLifecycleObserver (AddStaffLifecycleObserver)Reacting after a person is saved: StaffChangedContext tells whether they were just created, Activated, Terminated, whether the manager, user or teams changed. On termination, Workforce removes their future shifts, Dispatch unassigns their future visits, Contact Center signs them out and Telephony frees their extension.
IStaffHomeLinkProvider (AddStaffHomeLinkProvider)Adding links to the My work list of My Profile. Register it in the startup of the feature that owns the pages, so a link never points at a page that is off: the Workforce Portal feature adds My Work and the schedule, Time Tracker adds My time.
AddStaffScopePermissions(manageEveryone, manageOwn)Letting holders of another module's permissions manage staff.
ICatalogEntryHandler<StaffMember>The manager's lifecycle, such as Workforce writing its settings back before a save.
Index providers on StaffMemberQuerying a module's own data on staff, in the Staff collection.

People pickers​

The StaffPicker view component picks working staff (capability narrows to a kind of work, valueType = "userId" stores user ids, multiple picks several). Work orders pick their preferred and excluded technicians with it, fleet vehicles their default driver, Scheduling the person behind a staff resource, and accounts their account team.

Pickers that store users ask Users for the Staff audience (UserSearchQuery.Audience, the audience argument of the UserPicker view component and the user search endpoint): activity assignees, lead and opportunity owners, bulk assignment, phone extensions and lines, time entries and certificates. Until Offer only staff where people are assigned work is on, the audience isn't limited, so a site keeps offering every user while its staff are set up.

The Staff role​

Working staff with a user account are put in a role named Staff (created with no permissions) through IRoleGrantService, and taken out when they stop working or the account is unlinked. The role gets View one's own staff profile; give it only what every member of staff needs. The hourly upkeep task puts in the role anyone who was saved before the role existed.

Other modules on Staff​

  • Workforce schedules staff members. Its hours and availability live in WorkforceStaffSettings on the staff member (staff.MaxHoursPerWeek and the like are C# extension properties), the Workers list is a scheduling view of staff, and payroll export reads StaffPayRates.
  • Contact Center makes every new agent a staff member with the Agent capability (after the request, off the sign-in path), shows an agent card on the staff editor and signs out people who leave. Workforce for Contact Center gives agents their staff record through IStaffAccountService.
  • Dispatch reads technicians, home bases and time zones from Staff, adds a Technician name and Labor cost (hours at each person's cost of an hour) to the Visits report data set, and unassigns the future visits of people who leave.
  • Scheduling picks the person behind a staff resource among staff and fills an empty name or time zone from their record.
  • Point of Sale makes the person who opens a register a staff member with the Cashier capability.
  • Accounts adds the Account Team feature: an owner and an account team picked from staff, shown on the account page.
  • Skills reads the old Worker subject kind as Staff; a staff member and their user hold skills together.
  • Teams gets its members from Staff, people without a user account included (TeamMember.StaffMemberId).

Reports, workflows and AI​

With Data Pipelines on, the Staff report data source offers Staff members (one row per person: job, main team, manager, employment, status, capabilities, dates) and Staff history (one row per change), for headcount, hires, departures and turnover. With Workflows on, Staff Member Hired, Staff Member Left and Staff Manager Changed start workflows with the person's id, user, name, job, manager and team. With AI on, the Find staff (staffFind) and Reporting line (staffReportingLine) tools answer people who may view staff.

Recipes and deployment​

The Staff recipe step creates or updates staff members, matched by id, then employee number, then user (by userName); teams are given by name and the manager by id or managerEmployeeNumber, in any order. The Staff deployment step exports every staff member with their teams by name and their user by user name, and leaves out the date of birth unless Include sensitive data is ticked. The StaffSettings site settings travel in Orchard Core's Settings step.

Upgrading from Workforce workers​

Workforce used to keep its own WorkerProfile records. The Workforce migration moves each worker into the Staff collection as a staff member with the same id, so every stored worker id (punches, timesheets, shifts, time off, visits, territories, skills) still points at the same person. Workforce's hours and availability move to WorkforceStaffSettings, pay rates to StaffPayRates, the kiosk PIN to StaffBadge, and the manager worker id becomes the manager. A site that ran Workforce before Staff existed gets the Staff feature turned on first; the move runs at the next start. The old worker index tables are left in place, empty.