# peoplesoft

## Client

`import { ... } from "wcz-layout/data/client";`

- Employee:
  `searchEmployeesQueryOptions(SearchEmployeesSchema)` → `Employee[]` // free-text search
  `employeesQueryOptions()` → `Employee[]` // all employees, including terminated / leave of absence
  `activeEmployeesQueryOptions()` → `Employee[]` // only active employees
  `employeeByEmployeeIdQueryOptions(EmployeeIdSchema)` → `Employee` // single employee profile
  `previousEmployeeIdsQueryOptions()` → `Employee[]` // employees with `previousEmployeeIds`, use to resolve old IDs to current records
  `employeeSupervisorQueryOptions(EmployeeIdSchema)` → `Employee` // direct supervisor
  `employeeSubordinatesQueryOptions(EmployeeIdSchema)` → `Employee[]` // direct reports
  `employeeManagerQueryOptions(EmployeeIdSchema)` → `Employee` // manager in chain, may differ from supervisor in matrix orgs
  `employeeGeneralManagerQueryOptions(EmployeeIdSchema)` → `Employee` // top general manager of the employee's company
  `companyGeneralManagerQueryOptions(CompanyCodeSchema)` → `Employee` // general manager of the company
  `searchEmployees({ data: SearchEmployeesSchema })` → `Employee[]` // server fn (RPC), callable from client
  `getEmployees()` → `Employee[]` // server fn (RPC), all employees
  `getActiveEmployees()` → `Employee[]` // server fn (RPC), active employees
- Department:
  `departmentsQueryOptions()` → `Department[]` // all departments
  `departmentByIdQueryOptions(DepartmentIdSchema)` → `Department` // department details
  `departmentManagerQueryOptions(DepartmentIdSchema)` → `Employee` // department manager
  `departmentEmployeesQueryOptions(DepartmentIdSchema)` → `Employee[]` // employees in department
  `getDepartments()` → `Department[]` // server fn (RPC), all departments

## Server

`import { ... } from "wcz-layout/data/server";`

- Employee:
  `searchEmployees({ data: SearchEmployeesSchema })` → `Employee[]` // free-text search
  `getEmployees()` → `Employee[]` // all employees, including inactive
  `getActiveEmployees()` → `Employee[]` // only active employees
  `getEmployeeByEmployeeId({ data: EmployeeIdSchema })` → `Employee` // employee by ID
  `getPreviousEmployeeIds()` → `Employee[]` // employees with `previousEmployeeIds`
  `getEmployeeSupervisor({ data: EmployeeIdSchema })` → `Employee` // direct supervisor
  `getEmployeeSubordinates({ data: EmployeeIdSchema })` → `Employee[]` // direct reports
  `getEmployeeManager({ data: EmployeeIdSchema })` → `Employee` // manager in chain
  `getEmployeeGeneralManager({ data: EmployeeIdSchema })` → `Employee` // top general manager of lineage
  `getCompanyGeneralManager({ data: CompanyCodeSchema })` → `Employee` // company general manager
- Department:
  `getDepartments()` → `Department[]` // all departments
  `getDepartmentById({ data: DepartmentIdSchema })` → `Department` // department by ID
  `getDepartmentManager({ data: DepartmentIdSchema })` → `Employee` // department manager
  `getDepartmentEmployees({ data: DepartmentIdSchema })` → `Employee[]` // employees in department

## Schemas/Models

`import { EmployeeSchema, DepartmentSchema, type Employee, type Department, type EmployeeStatus, type EmployeeCategoryGroup } from "wcz-layout/models";`
`import { SearchEmployeesSchema, EmployeeIdSchema, DepartmentIdSchema, CompanyCodeSchema } from "wcz-layout/data/server";`

```ts
const EmployeeSchema = z.object({
  badgeId: z.string().trim(),
  category: z.string().trim(),
  categoryGroup: EmployeeCategoryGroup,
  companyCode: z.string().trim(),
  contactPhone: z.string().trim(),
  departmentId: z.string().trim(),
  departmentDescription: z.string().trim(),
  emailString: z.string().trim().nullable(),
  employeeId: z.string().trim(),
  extensionNumber: z.string().trim(),
  firstName: z.string().trim(),
  gender: z.string().trim(),
  hiredDate: z.string(),
  lastName: z.string().trim(),
  managerId: z.string().trim(),
  middleName: z.string().trim(),
  name: z.string().trim(),
  nameTitleCase: z.string().trim(),
  nfcSn: z.string().trim(),
  plantId: z.string().trim(),
  position: z.string().trim(),
  previousEmployeeIds: z.string().trim().nullable(),
  reHiredDate: z.string().nullable(),
  recordNumber: z.number(),
  status: EmployeeStatus,
  supervisorId: z.string().trim(),
  terminationDate: z.string().nullable(),
  terminationFutureDate: z.string().nullable(),
  type: z.string().trim(),
  upperDepartmentId: z.string().trim(),
  jobCode: z.string().trim(),
  jobDescription: z.string().trim(),
  terminationReason: z.string().trim().nullable(),
  supervisorRecordNumber: z.number(),
});

const DepartmentSchema = z.object({
  departmentId: z.string().trim(),
  description: z.string().trim(),
  managerId: z.string().trim(),
  managerRecordNumber: z.string().trim(),
  treeLevel: z.number(),
  upperDepartmentId: z.string().trim(),
  companyCode: z.string().trim(),
  location: z.string().trim(),
  salLocation: z.string().trim(),
  plantId: z.string().trim(),
  manager: EmployeeSchema,
});

const EmployeeCategoryGroup = z.enum(["IDL", "FD", "FI"]);
const EmployeeStatus = z.enum(["Active", "Terminated", "Leave of Absence"]);

const SearchEmployeesSchema = z.object({ searchTerm: z.string().min(1) });
const EmployeeIdSchema = z.object({ employeeId: z.string().min(1) });
const DepartmentIdSchema = z.object({ departmentId: z.string().min(1) });
const CompanyCodeSchema = z.object({ companyCode: z.string().min(1) });
```

## Examples

```ts
// client
import {
  activeEmployeesQueryOptions,
  employeeByEmployeeIdQueryOptions,
} from "wcz-layout/data/client";

const { data: employees = [] } = useQuery(activeEmployeesQueryOptions());
const { data: employee } = useQuery(employeeByEmployeeIdQueryOptions({ employeeId }));

// server
import { getEmployeeManager } from "wcz-layout/data/server";
const manager = await getEmployeeManager({ data: { employeeId } });
```
