Skip to main content

Overview

Technicians (referred to as Assignees in the codebase) are individuals who can be assigned to work orders and maintenance tasks. Unlike users, technicians are not necessarily system users and may include external contractors or third-party service providers.
Managing technicians requires assignees:full_access. Viewing technicians only requires assignees:read.

Assignee vs. User

AspectUserAssignee (Technician)
System loginYesOptional
Has permissionsYes (via role)No
Can be assigned to work ordersYes (if linked)Yes
Location assignmentYesNo (at work order level)
Typical useInternal staffTechnicians, contractors, vendors
Linking Users and Assignees: An assignee record can be linked to a user account via the user_id field. This allows system users to also function as assignees.

Assignee Data Model

FieldTypeDescription
idIntegerUnique assignee identifier
nameStringFirst name
last_nameStringLast name
sectionEnumAssignee category (see below)
emailStringOptional contact email
phoneStringOptional contact phone
user_idUUIDOptional link to a user account
is_activeBooleanWhether the assignee is available
created_atTimestampCreation date

Assignee Sections

Assignees are categorized into sections:
SectionDescription
SIN ASIGNARUnassigned (placeholder)
InternosInternal staff/employees
TERCEROSThird-party contractors/vendors
OTROSOther/miscellaneous
The section field is used for filtering and reporting. Choose the section that best represents the assignee’s relationship to your organization.

Technician Management Workflows

Creating a Technician

1

Navigate to Technicians

Go to Administration → Técnicos (or /admin/assignees).
2

Click 'Crear técnico'

Opens the technician creation form.
3

Fill in Required Fields

  • Name: First name (required)
  • Last Name: Surname (required)
  • Section: Select the appropriate category (required)
  • Email (optional): Contact email
  • Phone (optional): Contact phone
  • Link to User (optional): If the technician is also a system user, select their user account
4

Submit

Click “Crear”. The technician is created and can be assigned to work orders.

Editing a Technician

1

Locate the Technician

Use the search bar or section filter to find the technician.
2

Click 'Editar'

Opens the edit form with the technician’s current details.
3

Modify Fields

Update any of the following:
  • Name and last name
  • Section
  • Email and phone
  • User link
  • Active status
4

Save Changes

Click “Guardar”. Changes take effect immediately.

Activating/Deactivating a Technician

Deactivating a technician prevents them from being assigned to new work orders:
  1. Click the “Desactivar” or “Activar” button on the technician’s row
  2. Confirm the action if prompted
  3. The is_active flag is toggled
Requires assignees:cancel permission.
Effects of Deactivation:
  • Technician no longer appears in work order assignment dropdowns
  • Existing work order assignments remain unchanged
  • Historical data is preserved
  • Technician can be reactivated at any time

Deleting a Technician

Deletion is permanent and may affect work orders assigned to this technician. Consider deactivation instead.
1

Check Dependencies

Verify that the technician has no active work orders or critical assignments.
2

Initiate Deletion

Click the “Eliminar” button on the technician’s row.
3

Confirm

Confirm the deletion in the warning dialog.
Requires assignees:delete permission. The technician management interface supports:
  • Search: By name, last name, email, or phone (minimum 2 characters)
  • Section Filter: Show only technicians from a specific section (Internos, TERCEROS, OTROS, or TODOS)
  • Include Inactive: Toggle to include deactivated technicians

Pagination

Technicians are paginated with a configurable page size. Use the navigation buttons to browse pages.
Search results show all matching technicians without pagination.

Assigning Technicians to Work Orders

Technicians are assigned to work orders through the work order creation or edit interface:
  1. Open the work order form
  2. In the “Assignee” or “Técnico” dropdown, select the technician
  3. Save the work order
The work order’s assignee_id field is set to the selected technician’s ID.

Multiple Assignees

Some work order types support multiple assignees. Consult the work order module documentation for details.

Linking Technicians to Users

If a technician also has a system user account, link them by setting the user_id field:
1

Edit the Technician

Open the technician edit form.
2

Select User

In the “Link to User” dropdown, select the corresponding user account.
3

Save

The technician is now linked to the user. Work orders assigned to this technician can be viewed by the linked user.
Benefits of Linking:
  • Linked users can view “their” work orders using the work_orders:read_own permission
  • Contact information (email, phone) can be synced between user and assignee records
  • Reporting and analytics can associate work with specific users

Service Layer Reference

Technician operations are handled by assigneeService.ts:

Key Functions

// Paginated list with filters
getAssigneesPaginated({
  page: number,
  pageSize: number,
  search?: string,
  section?: AssigneeSection | 'TODOS',
  includeInactive?: boolean
}): Promise<{ data: Assignee[]; count: number }>

// Get all assignees (for dropdowns)
getAllAssignees(): Promise<Assignee[]>

// Get only active assignees
getActiveAssignees(): Promise<Assignee[]>

// Group assignees by section
groupBySection(list: Assignee[]): Record<AssigneeSection, Assignee[]>

// Create an assignee
createAssignee(input: AssigneeInput): Promise<number>

// Update an assignee
updateAssignee(id: number, input: Partial<AssigneeInput>): Promise<void>

// Toggle active status
setAssigneeActive(id: number, isActive: boolean): Promise<void>
bulkSetAssigneeActive(ids: number[], isActive: boolean): Promise<void>

// Delete an assignee
deleteAssignee(id: number): Promise<void>

Example: Fetching Active Technicians for Dropdown

import { getActiveAssignees } from '../services/assigneeService';

const technicians = await getActiveAssignees();

const dropdown = technicians.map(t => ({
  value: t.id,
  label: `${t.name} ${t.last_name}`.trim(),
}));

Example: Creating a Technician

import { createAssignee } from '../services/assigneeService';

const newTechId = await createAssignee({
  name: 'Juan',
  last_name: 'Pérez',
  section: 'Internos',
  email: 'juan.perez@example.com',
  phone: '+1-809-555-1234',
  user_id: null, // Not linked to a user
  is_active: true,
});

console.log('Created technician ID:', newTechId);

Database Schema

assignees Table

CREATE TABLE assignees (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  last_name TEXT NOT NULL,
  section TEXT NOT NULL CHECK (section IN ('SIN ASIGNAR', 'Internos', 'TERCEROS', 'OTROS')),
  email TEXT,
  phone TEXT,
  user_id UUID REFERENCES auth.users(id),
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

RLS Policies

-- Users can view active assignees
CREATE POLICY "assignees_select_active" ON assignees
  FOR SELECT
  USING (is_active = TRUE OR current_user_has_permission('assignees:read'));

-- Full access users can insert/update/delete
CREATE POLICY "assignees_insert_rbac" ON assignees
  FOR INSERT
  WITH CHECK (current_user_has_permission('assignees:full_access'));

CREATE POLICY "assignees_update_rbac" ON assignees
  FOR UPDATE
  USING (current_user_has_permission('assignees:full_access'));

CREATE POLICY "assignees_delete_rbac" ON assignees
  FOR DELETE
  USING (current_user_has_permission('assignees:delete'));

Helper Functions

The assigneeService.ts includes utility functions:

Format Full Name

import { formatAssigneeFullName } from '../services/assigneeService';

const assignee = { id: 1, name: 'Juan', last_name: 'Pérez', ... };
console.log(formatAssigneeFullName(assignee)); // "Juan Pérez"

Get Initials

import { assigneeInitials } from '../services/assigneeService';

const assignee = { id: 1, name: 'Juan', last_name: 'Pérez', ... };
console.log(assigneeInitials(assignee)); // "JP"

Group by Section

import { getActiveAssignees, groupBySection } from '../services/assigneeService';

const assignees = await getActiveAssignees();
const grouped = groupBySection(assignees);

console.log(grouped['Internos']); // Array of internal technicians
console.log(grouped['TERCEROS']); // Array of third-party contractors

Best Practices

Use Sections Consistently

Adopt clear criteria for categorizing technicians (Internos vs. TERCEROS).

Link Users When Possible

If a technician has a system account, link the assignee record to the user for better tracking.

Deactivate Instead of Delete

Preserve historical work order assignments by deactivating unused technicians.

Maintain Contact Information

Keep email and phone fields up to date for communication purposes.

Review Assignees Regularly

Audit the technician list periodically to remove duplicates or outdated entries.

Use Descriptive Names

Ensure names are spelled correctly and include sufficient detail to identify the technician.

Permissions Required

ActionPermission Code
View techniciansassignees:read
Create/edit techniciansassignees:full_access
Activate/deactivateassignees:cancel
Delete techniciansassignees:delete

Troubleshooting

Technician Not Appearing in Dropdown

Cause: The technician is marked as is_active = false. Solution: Activate the technician or use the “Include inactive” filter. Possible causes:
  1. The user account does not exist → Create the user first
  2. The user is already linked to another technician → Unlink the existing assignee
Solution: Verify the user account and resolve conflicts.

Duplicate Technicians

Cause: Technicians were created multiple times with similar names. Solution:
  1. Review the technician list
  2. Deactivate or delete duplicate entries
  3. Reassign work orders to the correct technician

Section Filter Not Working

Cause: The section value in the database does not match the expected enum values. Solution: Verify that the section is one of: SIN ASIGNAR, Internos, TERCEROS, OTROS.