feat(construccion): Add HR module entities

- Add Employee entity
- Add EmployeeFraccionamiento relationship entity
- Add Puesto (position) entity
- Add entities index export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rckrdmrd 2025-12-08 10:46:47 -06:00
parent 94371c0e75
commit d30fe4d644
4 changed files with 277 additions and 0 deletions

View File

@ -0,0 +1,65 @@
/**
* EmployeeFraccionamiento Entity
* Asignación de empleados a obras/fraccionamientos
*
* @module HR
* @table hr.employee_fraccionamientos
* @ddl schemas/02-hr-schema-ddl.sql
*/
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
JoinColumn,
Index,
} from 'typeorm';
import { Tenant } from '../../core/entities/tenant.entity';
import { Employee } from './employee.entity';
import { Fraccionamiento } from '../../construction/entities/fraccionamiento.entity';
@Entity({ schema: 'hr', name: 'employee_fraccionamientos' })
@Index(['employeeId', 'fraccionamientoId', 'fechaInicio'], { unique: true })
export class EmployeeFraccionamiento {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
tenantId: string;
@Column({ name: 'employee_id', type: 'uuid' })
employeeId: string;
@Column({ name: 'fraccionamiento_id', type: 'uuid' })
fraccionamientoId: string;
@Column({ name: 'fecha_inicio', type: 'date' })
fechaInicio: Date;
@Column({ name: 'fecha_fin', type: 'date', nullable: true })
fechaFin: Date;
@Column({ type: 'varchar', length: 50, nullable: true })
rol: string;
@Column({ type: 'boolean', default: true })
activo: boolean;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt: Date;
// Relations
@ManyToOne(() => Tenant)
@JoinColumn({ name: 'tenant_id' })
tenant: Tenant;
@ManyToOne(() => Employee, (e) => e.asignaciones)
@JoinColumn({ name: 'employee_id' })
employee: Employee;
@ManyToOne(() => Fraccionamiento)
@JoinColumn({ name: 'fraccionamiento_id' })
fraccionamiento: Fraccionamiento;
}

View File

@ -0,0 +1,136 @@
/**
* Employee Entity
* Empleados de la empresa
*
* @module HR
* @table hr.employees
* @ddl schemas/02-hr-schema-ddl.sql
*/
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
ManyToOne,
OneToMany,
JoinColumn,
Index,
} from 'typeorm';
import { Tenant } from '../../core/entities/tenant.entity';
import { User } from '../../core/entities/user.entity';
import { Puesto } from './puesto.entity';
import { EmployeeFraccionamiento } from './employee-fraccionamiento.entity';
export type EstadoEmpleado = 'activo' | 'inactivo' | 'baja';
export type Genero = 'M' | 'F';
@Entity({ schema: 'hr', name: 'employees' })
@Index(['tenantId', 'codigo'], { unique: true })
@Index(['tenantId', 'curp'], { unique: true })
export class Employee {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
tenantId: string;
@Column({ type: 'varchar', length: 20 })
codigo: string;
@Column({ type: 'varchar', length: 100 })
nombre: string;
@Column({ name: 'apellido_paterno', type: 'varchar', length: 100 })
apellidoPaterno: string;
@Column({ name: 'apellido_materno', type: 'varchar', length: 100, nullable: true })
apellidoMaterno: string;
@Column({ type: 'varchar', length: 18, nullable: true })
curp: string;
@Column({ type: 'varchar', length: 13, nullable: true })
rfc: string;
@Column({ type: 'varchar', length: 11, nullable: true })
nss: string;
@Column({ name: 'fecha_nacimiento', type: 'date', nullable: true })
fechaNacimiento: Date;
@Column({ type: 'varchar', length: 1, nullable: true })
genero: Genero;
@Column({ type: 'varchar', length: 255, nullable: true })
email: string;
@Column({ type: 'varchar', length: 20, nullable: true })
telefono: string;
@Column({ type: 'text', nullable: true })
direccion: string;
@Column({ name: 'fecha_ingreso', type: 'date' })
fechaIngreso: Date;
@Column({ name: 'fecha_baja', type: 'date', nullable: true })
fechaBaja: Date;
@Column({ name: 'puesto_id', type: 'uuid', nullable: true })
puestoId: string;
@Column({ type: 'varchar', length: 100, nullable: true })
departamento: string;
@Column({ name: 'tipo_contrato', type: 'varchar', length: 50, nullable: true })
tipoContrato: string;
@Column({
name: 'salario_diario',
type: 'decimal',
precision: 10,
scale: 2,
nullable: true
})
salarioDiario: number;
@Column({ type: 'varchar', length: 20, default: 'activo' })
estado: EstadoEmpleado;
@Column({ name: 'foto_url', type: 'varchar', length: 500, nullable: true })
fotoUrl: string;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
updatedAt: Date;
@Column({ name: 'created_by', type: 'uuid', nullable: true })
createdById: string;
// Relations
@ManyToOne(() => Tenant)
@JoinColumn({ name: 'tenant_id' })
tenant: Tenant;
@ManyToOne(() => Puesto, (p) => p.empleados)
@JoinColumn({ name: 'puesto_id' })
puesto: Puesto;
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
createdBy: User;
@OneToMany(() => EmployeeFraccionamiento, (ef) => ef.employee)
asignaciones: EmployeeFraccionamiento[];
// Computed property
get nombreCompleto(): string {
return [this.nombre, this.apellidoPaterno, this.apellidoMaterno]
.filter(Boolean)
.join(' ');
}
}

View File

@ -0,0 +1,8 @@
/**
* HR Entities Index
* @module HR
*/
export * from './puesto.entity';
export * from './employee.entity';
export * from './employee-fraccionamiento.entity';

View File

@ -0,0 +1,68 @@
/**
* Puesto Entity
* Catálogo de puestos de trabajo
*
* @module HR
* @table hr.puestos
* @ddl schemas/02-hr-schema-ddl.sql
*/
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
ManyToOne,
OneToMany,
JoinColumn,
Index,
} from 'typeorm';
import { Tenant } from '../../core/entities/tenant.entity';
import { Employee } from './employee.entity';
@Entity({ schema: 'hr', name: 'puestos' })
@Index(['tenantId', 'codigo'], { unique: true })
export class Puesto {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
tenantId: string;
@Column({ type: 'varchar', length: 20 })
codigo: string;
@Column({ type: 'varchar', length: 100 })
nombre: string;
@Column({ type: 'text', nullable: true })
descripcion: string;
@Column({ name: 'nivel_riesgo', type: 'varchar', length: 20, nullable: true })
nivelRiesgo: string;
@Column({
name: 'requiere_capacitacion_especial',
type: 'boolean',
default: false
})
requiereCapacitacionEspecial: boolean;
@Column({ type: 'boolean', default: true })
activo: boolean;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
updatedAt: Date;
// Relations
@ManyToOne(() => Tenant)
@JoinColumn({ name: 'tenant_id' })
tenant: Tenant;
@OneToMany(() => Employee, (e) => e.puesto)
empleados: Employee[];
}