feat(sat): add database models for SAT sync
Phase 1 - Database models: - Add FielCredential model for encrypted FIEL storage - Add SatSyncJob model for sync job tracking - Add SAT-related enums (SatSyncType, SatSyncStatus, CfdiSyncType) - Add TypeScript types in shared package - Relations: Tenant -> FielCredential (1:1), Tenant -> SatSyncJobs (1:N) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,8 @@ model Tenant {
|
|||||||
expiresAt DateTime? @map("expires_at")
|
expiresAt DateTime? @map("expires_at")
|
||||||
|
|
||||||
users User[]
|
users User[]
|
||||||
|
fielCredential FielCredential?
|
||||||
|
satSyncJobs SatSyncJob[]
|
||||||
|
|
||||||
@@map("tenants")
|
@@map("tenants")
|
||||||
}
|
}
|
||||||
@@ -62,3 +64,75 @@ enum Role {
|
|||||||
contador
|
contador
|
||||||
visor
|
visor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// SAT Sync Models
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
model FielCredential {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
tenantId String @unique @map("tenant_id")
|
||||||
|
rfc String @db.VarChar(13)
|
||||||
|
cerData Bytes @map("cer_data")
|
||||||
|
keyData Bytes @map("key_data")
|
||||||
|
keyPasswordEncrypted Bytes @map("key_password_encrypted")
|
||||||
|
encryptionIv Bytes @map("encryption_iv")
|
||||||
|
encryptionTag Bytes @map("encryption_tag")
|
||||||
|
serialNumber String? @map("serial_number") @db.VarChar(50)
|
||||||
|
validFrom DateTime @map("valid_from")
|
||||||
|
validUntil DateTime @map("valid_until")
|
||||||
|
isActive Boolean @default(true) @map("is_active")
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
updatedAt DateTime @updatedAt @map("updated_at")
|
||||||
|
|
||||||
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@map("fiel_credentials")
|
||||||
|
}
|
||||||
|
|
||||||
|
model SatSyncJob {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
tenantId String @map("tenant_id")
|
||||||
|
type SatSyncType
|
||||||
|
status SatSyncStatus @default(pending)
|
||||||
|
dateFrom DateTime @map("date_from") @db.Date
|
||||||
|
dateTo DateTime @map("date_to") @db.Date
|
||||||
|
cfdiType CfdiSyncType? @map("cfdi_type")
|
||||||
|
satRequestId String? @map("sat_request_id") @db.VarChar(50)
|
||||||
|
satPackageIds String[] @map("sat_package_ids")
|
||||||
|
cfdisFound Int @default(0) @map("cfdis_found")
|
||||||
|
cfdisDownloaded Int @default(0) @map("cfdis_downloaded")
|
||||||
|
cfdisInserted Int @default(0) @map("cfdis_inserted")
|
||||||
|
cfdisUpdated Int @default(0) @map("cfdis_updated")
|
||||||
|
progressPercent Int @default(0) @map("progress_percent")
|
||||||
|
errorMessage String? @map("error_message")
|
||||||
|
startedAt DateTime? @map("started_at")
|
||||||
|
completedAt DateTime? @map("completed_at")
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
retryCount Int @default(0) @map("retry_count")
|
||||||
|
nextRetryAt DateTime? @map("next_retry_at")
|
||||||
|
|
||||||
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@index([tenantId])
|
||||||
|
@@index([status])
|
||||||
|
@@index([status, nextRetryAt])
|
||||||
|
@@map("sat_sync_jobs")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SatSyncType {
|
||||||
|
initial
|
||||||
|
daily
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SatSyncStatus {
|
||||||
|
pending
|
||||||
|
running
|
||||||
|
completed
|
||||||
|
failed
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CfdiSyncType {
|
||||||
|
emitidos
|
||||||
|
recibidos
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export * from './types/impuestos';
|
|||||||
export * from './types/alertas';
|
export * from './types/alertas';
|
||||||
export * from './types/reportes';
|
export * from './types/reportes';
|
||||||
export * from './types/calendario';
|
export * from './types/calendario';
|
||||||
|
export * from './types/sat';
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
export * from './constants/plans';
|
export * from './constants/plans';
|
||||||
|
|||||||
132
packages/shared/src/types/sat.ts
Normal file
132
packages/shared/src/types/sat.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// ============================================
|
||||||
|
// FIEL (e.firma) Types
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
export interface FielUploadRequest {
|
||||||
|
cerFile: string; // Base64
|
||||||
|
keyFile: string; // Base64
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FielStatus {
|
||||||
|
configured: boolean;
|
||||||
|
rfc?: string;
|
||||||
|
serialNumber?: string;
|
||||||
|
validFrom?: string;
|
||||||
|
validUntil?: string;
|
||||||
|
isExpired?: boolean;
|
||||||
|
daysUntilExpiration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// SAT Sync Types
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
export type SatSyncType = 'initial' | 'daily';
|
||||||
|
export type SatSyncStatus = 'pending' | 'running' | 'completed' | 'failed';
|
||||||
|
export type CfdiSyncType = 'emitidos' | 'recibidos';
|
||||||
|
|
||||||
|
export interface SatSyncJob {
|
||||||
|
id: string;
|
||||||
|
tenantId: string;
|
||||||
|
type: SatSyncType;
|
||||||
|
status: SatSyncStatus;
|
||||||
|
dateFrom: string;
|
||||||
|
dateTo: string;
|
||||||
|
cfdiType?: CfdiSyncType;
|
||||||
|
satRequestId?: string;
|
||||||
|
satPackageIds: string[];
|
||||||
|
cfdisFound: number;
|
||||||
|
cfdisDownloaded: number;
|
||||||
|
cfdisInserted: number;
|
||||||
|
cfdisUpdated: number;
|
||||||
|
progressPercent: number;
|
||||||
|
errorMessage?: string;
|
||||||
|
startedAt?: string;
|
||||||
|
completedAt?: string;
|
||||||
|
createdAt: string;
|
||||||
|
retryCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatSyncStatusResponse {
|
||||||
|
hasActiveSync: boolean;
|
||||||
|
currentJob?: SatSyncJob;
|
||||||
|
lastCompletedJob?: SatSyncJob;
|
||||||
|
totalCfdisSynced: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatSyncHistoryResponse {
|
||||||
|
jobs: SatSyncJob[];
|
||||||
|
total: number;
|
||||||
|
page: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartSyncRequest {
|
||||||
|
type?: SatSyncType;
|
||||||
|
dateFrom?: string;
|
||||||
|
dateTo?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartSyncResponse {
|
||||||
|
jobId: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// SAT Web Service Types
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
export interface SatAuthResponse {
|
||||||
|
token: string;
|
||||||
|
expiresAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatDownloadRequest {
|
||||||
|
rfcSolicitante: string;
|
||||||
|
fechaInicio: Date;
|
||||||
|
fechaFin: Date;
|
||||||
|
tipoSolicitud: 'CFDI' | 'Metadata';
|
||||||
|
tipoComprobante?: 'I' | 'E' | 'T' | 'N' | 'P';
|
||||||
|
rfcEmisor?: string;
|
||||||
|
rfcReceptor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatDownloadRequestResponse {
|
||||||
|
idSolicitud: string;
|
||||||
|
codEstatus: string;
|
||||||
|
mensaje: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatVerifyResponse {
|
||||||
|
codEstatus: string;
|
||||||
|
estadoSolicitud: number; // 1=Aceptada, 2=EnProceso, 3=Terminada, 4=Error, 5=Rechazada, 6=Vencida
|
||||||
|
codigoEstadoSolicitud: string;
|
||||||
|
numeroCfdis: number;
|
||||||
|
mensaje: string;
|
||||||
|
paquetes: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SatPackageResponse {
|
||||||
|
paquete: string; // Base64 ZIP
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// SAT Error Codes
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
export const SAT_STATUS_CODES: Record<string, string> = {
|
||||||
|
'5000': 'Solicitud recibida con éxito',
|
||||||
|
'5002': 'Se agotó el límite de solicitudes',
|
||||||
|
'5004': 'No se encontraron CFDIs',
|
||||||
|
'5005': 'Solicitud duplicada',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SAT_REQUEST_STATUS: Record<number, string> = {
|
||||||
|
1: 'Aceptada',
|
||||||
|
2: 'En proceso',
|
||||||
|
3: 'Terminada',
|
||||||
|
4: 'Error',
|
||||||
|
5: 'Rechazada',
|
||||||
|
6: 'Vencida',
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user