- CartaPorte: Main CFDI entity with emisor/receptor, totals, XML/PDF - UbicacionCartaPorte: Origin/destination locations with SAT codes - MercanciaCartaPorte: Goods being transported with hazmat support - FiguraTransporte: Operator/owner/lessor figures - AutotransporteCartaPorte: Vehicle configuration and trailers - HosLog: Hours of Service compliance (NOM-087) - InspeccionPreViaje: Pre-trip inspection checklists Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import {
|
|
Entity,
|
|
PrimaryGeneratedColumn,
|
|
Column,
|
|
Index,
|
|
ManyToOne,
|
|
JoinColumn,
|
|
} from 'typeorm';
|
|
import { CartaPorte } from './carta-porte.entity';
|
|
|
|
/**
|
|
* Tipo de Ubicación
|
|
*/
|
|
export enum TipoUbicacionCartaPorte {
|
|
ORIGEN = 'Origen',
|
|
DESTINO = 'Destino',
|
|
}
|
|
|
|
@Entity({ schema: 'compliance', name: 'ubicaciones_carta_porte' })
|
|
@Index('idx_ubicacion_carta', ['cartaPorteId'])
|
|
export class UbicacionCartaPorte {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ name: 'tenant_id', type: 'uuid' })
|
|
tenantId: string;
|
|
|
|
@Column({ name: 'carta_porte_id', type: 'uuid' })
|
|
cartaPorteId: string;
|
|
|
|
@ManyToOne(() => CartaPorte, (cp) => cp.ubicaciones)
|
|
@JoinColumn({ name: 'carta_porte_id' })
|
|
cartaPorte: CartaPorte;
|
|
|
|
// Tipo
|
|
@Column({ name: 'tipo_ubicacion', type: 'varchar', length: 10 })
|
|
tipoUbicacion: string;
|
|
|
|
// ID Ubicación (catálogo SAT)
|
|
@Column({ name: 'id_ubicacion', type: 'varchar', length: 10, nullable: true })
|
|
idUbicacion: string | null;
|
|
|
|
// RFC
|
|
@Column({ name: 'rfc_remitente_destinatario', type: 'varchar', length: 13, nullable: true })
|
|
rfcRemitenteDestinatario: string | null;
|
|
|
|
@Column({ name: 'nombre_remitente_destinatario', type: 'varchar', length: 200, nullable: true })
|
|
nombreRemitenteDestinatario: string | null;
|
|
|
|
// Domicilio
|
|
@Column({ type: 'varchar', length: 3, default: 'MEX' })
|
|
pais: string;
|
|
|
|
@Column({ type: 'varchar', length: 10, nullable: true })
|
|
estado: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 10, nullable: true })
|
|
municipio: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 10, nullable: true })
|
|
localidad: string | null;
|
|
|
|
@Column({ name: 'codigo_postal', type: 'varchar', length: 10 })
|
|
codigoPostal: string;
|
|
|
|
@Column({ type: 'varchar', length: 10, nullable: true })
|
|
colonia: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 200, nullable: true })
|
|
calle: string | null;
|
|
|
|
@Column({ name: 'numero_exterior', type: 'varchar', length: 50, nullable: true })
|
|
numeroExterior: string | null;
|
|
|
|
@Column({ name: 'numero_interior', type: 'varchar', length: 50, nullable: true })
|
|
numeroInterior: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 500, nullable: true })
|
|
referencia: string | null;
|
|
|
|
// Fechas
|
|
@Column({ name: 'fecha_hora_salida_llegada', type: 'timestamptz', nullable: true })
|
|
fechaHoraSalidaLlegada: Date | null;
|
|
|
|
// Distancia
|
|
@Column({ name: 'distancia_recorrida', type: 'decimal', precision: 10, scale: 2, nullable: true })
|
|
distanciaRecorrida: number | null;
|
|
|
|
// Secuencia
|
|
@Column({ type: 'int' })
|
|
secuencia: number;
|
|
|
|
// Helpers
|
|
get esOrigen(): boolean {
|
|
return this.tipoUbicacion === TipoUbicacionCartaPorte.ORIGEN;
|
|
}
|
|
|
|
get esDestino(): boolean {
|
|
return this.tipoUbicacion === TipoUbicacionCartaPorte.DESTINO;
|
|
}
|
|
|
|
get direccionCompleta(): string {
|
|
const partes = [
|
|
this.calle,
|
|
this.numeroExterior ? `#${this.numeroExterior}` : null,
|
|
this.numeroInterior ? `Int. ${this.numeroInterior}` : null,
|
|
this.colonia,
|
|
`CP ${this.codigoPostal}`,
|
|
].filter(Boolean);
|
|
return partes.join(', ');
|
|
}
|
|
}
|