# Flujos de Trabajo Comunes

## 1. Facturación Estándar (Ingreso)

### Flujo Completo

```
Usuario → Frontend → API → Controller → XMLUtils → Finkok → DB → Response
```

### Pasos Detallados

1. **Preparación de Datos**
   - Usuario captura datos en frontend
   - Sistema valida campos requeridos
   - Frontend construye objeto de factura

2. **Envío al Backend**
   ```javascript
   POST /api/facturar40
   {
       factura: {...},
       user: {id_proveedor: 123}
   }
   ```

3. **Procesamiento en Controller**
   - Validar certificado CSD activo
   - Obtener siguiente folio
   - Construir objeto $datosFactura
   - Calcular impuestos
   - Procesar complementos

4. **Generación XML**
   - Llamar a `XMLUtils::createXML40()`
   - Generar sello digital
   - Guardar XML temporal

5. **Timbrado**
   - Conectar a Finkok vía SOAP
   - Enviar XML para timbrado
   - Recibir TimbreFiscalDigital

6. **Persistencia**
   - Guardar Factura
   - Guardar IdDoc con UUID
   - Guardar Totales
   - Guardar Conceptos
   - Guardar Impuestos
   - Guardar Complementos

7. **Respuesta**
   - Retornar UUID y datos de factura
   - Frontend muestra confirmación
   - Generar PDF (opcional)

---

## 2. Nota de Crédito (Egreso)

### Diferencias con Ingreso

- `tipoDeComprobante: "E"`
- Total es negativo en la contabilidad
- Debe relacionarse con la factura original

### Pasos Específicos

1. **Seleccionar Factura Original**
   - Buscar factura a cancelar parcial/totalmente
   - Obtener UUID de la factura original

2. **Configurar Relación**
   ```javascript
   facturasRelacionadas: {
       tipoRelacion: "01",  // Nota de crédito
       uuids: [
           {uUID: "UUID-DE-FACTURA-ORIGINAL"}
       ]
   }
   ```

3. **Configurar Conceptos**
   - Mismos conceptos que factura original (o subset)
   - Cantidades negativas o positivas según especificación SAT

4. **Procesamiento Normal**
   - Genera XML con tipo "E"
   - Incluye CFDIs relacionados
   - Timbra y guarda

---

## 3. Recibo de Pago (Complemento Pagos 2.0)

### Flujo Específico

1. **Identificar Facturas PPD Pendientes**
   ```sql
   SELECT * FROM Factura f
   JOIN IdDoc i ON f.id_factura = i.id_factura
   WHERE i.metodoDePago = 'PPD'
   AND f.isPagado = 0
   ```

2. **Capturar Datos del Pago**
   ```javascript
   {
       tipoDocumento: "P",
       serie: "P",
       // SubTotal, Total = 0.00 para tipo P
       conceptos: [{
           clave: "84111506",
           descripcion: "Pago",
           cantidad: 1,
           valorUnitario: 0,
           objetoImp: "01"  // No objeto de impuesto
       }],
       pagos: [{
           FechaPago: "2024-01-15T10:30:00",
           FormaDePagoP: "03",
           MonedaP: "MXN",
           Monto: 1000.00,
           documentosRelacionado: [{
               IdDocumento: "UUID-FACTURA",
               MonedaDR: "MXN",
               MetodoDePagoDR: "PPD",
               NumParcialidad: 1,
               ImpSaldoAnt: 1160.00,
               ImpPagado: 1000.00,
               ImpSaldoInsoluto: 160.00
           }]
       }]
   }
   ```

3. **Cálculo de Impuestos por DR**
   - Los impuestos se calculan proporcionalmente al pago
   - Base DR = (ImpPagado / ImpSaldoAnt) * Base original
   - Importe DR = (ImpPagado / ImpSaldoAnt) * Importe original

4. **Generar Totales del Complemento**
   - Sumar todos los impuestos de todos los DRs
   - Agregar nodo `<pago20:Totales>`

5. **Actualizar Estado de Facturas**
   ```php
   if (ImpSaldoInsoluto == 0) {
       factura->isPagado = 1;
       factura->save();
   }
   ```

---

## 4. Nómina

### Flujo Específico

1. **Crear/Actualizar Empleado**
   - Datos personales (CURP, NSS)
   - Datos laborales (puesto, salario)
   - Datos contractuales (tipo contrato, régimen)

2. **Definir Periodo de Pago**
   - Fecha inicio y fin
   - Tipo de nómina (O=Ordinaria, E=Extraordinaria)
   - Periodicidad

3. **Capturar Percepciones**
   ```javascript
   percepciones: [
       {
           tipo: "001",  // Sueldo
           importeGravado: 8000.00,
           importeExento: 2000.00
       },
       {
           tipo: "019",  // Horas extra
           importeGravado: 500.00,
           importeExento: 0.00,
           dias: 2,
           tipoHoras: "01",
           horasExtra: 4
       }
   ]
   ```

4. **Capturar Deducciones**
   ```javascript
   deducciones: [
       {tipo: "002", importe: 1500.00},  // ISR
       {tipo: "001", importe: 500.00}     // IMSS
   ]
   ```

5. **Capturar Otros Pagos**
   ```javascript
   otrosPagos: [
       {tipo: "002", importe: 500.00}  // Subsidio al empleo
   ]
   ```

6. **Cálculos Automáticos**
   - Total percepciones = gravado + exento
   - Total deducciones
   - Neto = percepciones - deducciones + otros pagos
   - Antigüedad en formato ISO 8601

7. **Generar CFDI**
   - Tipo "N"
   - Total = neto a pagar
   - Incluye complemento Nomina 1.2

---

## 5. Carta Porte (Transporte)

### Flujo Específico

1. **Definir Tipo de Transporte**
   - Ingreso con complemento (venta con transporte)
   - Traslado puro (tipo "T")

2. **Configurar Transporte Internacional**
   ```javascript
   cartaPorte: {
       transpInternac: "Sí",
       entradaSalidaMerc: "Salida",
       paisOrigenDestino: "USA",
       viaEntradaSalida: "01"
   }
   ```

3. **Agregar Ubicaciones**
   - Mínimo 2 (origen y destino)
   - Calcular distancia entre ubicaciones
   
   ```javascript
   ubicaciones: [
       {
           tipoUbicacion: "Origen",
           fechaHoraSalidaLlegada: "2024-01-15T08:00:00",
           // ... domicilio
           totalDistRec: 0
       },
       {
           tipoUbicacion: "Destino",
           fechaHoraSalidaLlegada: "2024-01-15T14:00:00",
           // ... domicilio
           totalDistRec: 250.75
       }
   ]
   ```

4. **Agregar Mercancías**
   ```javascript
   mercancias: [
       {
           bienesTransp: "10101500",
           cantidad: 100,
           peso: 1000.50,
           descripcion: "Mercancía",
           valorMercancia: 10000.00
       }
   ]
   ```

5. **Configurar Autotransporte**
   ```javascript
   autotransporte: {
       tipoPermiso: "TPAF01",
       noPermiso: "PERM123456",
       configTransporte: "VL",
       placaVM: "ABC1234",
       // ... seguros
       remolques: [...]
   }
   ```

6. **Agregar Figuras de Transporte**
   ```javascript
   figurasTransporte: [
       {
           tipoFigura: "01",  // Operador
           rFCFigura: "OABC123456XYZ",
           numLicencia: "LIC123456",
           nombreFigura: "OPERADOR"
       }
   ]
   ```

7. **Generar IdCCP**
   - Sistema genera automáticamente
   - Formato: CCC + YYYYMMDD + Consecutivo

---

## 6. Comercio Exterior

### Flujo Específico

1. **Configurar Operación**
   ```javascript
   isComercio: 1,
   comercio: {
       incoterm: "CFR",
       pedimento: "A1",
       tipoOperacion: "2",  // Exportación definitiva
       rfcExtranjero: "XEXX010101000"
   }
   ```

2. **Configurar Domicilios**
   - Domicilio fiscal del emisor
   - Domicilio en el extranjero del receptor

3. **Agregar Datos de Mercancías**
   ```javascript
   detalles: [
       {
           // ... datos normales del concepto
           fracArancelaria: "12345678",
           // Para comercio:
           cantidadAduana: 100,
           unidadAduana: "01",
           valorUnitarioAduana: 10.00,
           valorDolares: 1000.00
       }
   ]
   ```

4. **Cálculos USD**
   - Si moneda = USD, usar directamente
   - Si moneda = MXN, calcular: total / tipoCambio

5. **Generar CFDI**
   - Incluye complemento ComercioExterior
   - Valida fracciones arancelarias

---

## 7. Cancelación de CFDI

### Flujo con Finkok

1. **Verificar Requisitos**
   - Factura debe estar timbrada
   - Dentro del plazo de cancelación (72 horas sin aceptación)
   - Tener motivo válido de cancelación

2. **Solicitar Cancelación**
   ```php
   $client = new SoapClient($urlCancelacion);
   $params = [
       'username' => $usuario,
       'password' => $password,
       'uuid' => $uuidACancelar,
       'motivo' => '02',  // Comprobante con errores
       'folioSustitucion' => ''  // UUID sustituto si aplica
   ];
   $resultado = $client->__soapCall('cancel', [$params]);
   ```

3. **Procesar Respuesta**
   - Si aceptación automática: actualizar status
   - Si requiere aceptación receptor: esperar respuesta

4. **Actualizar Base de Datos**
   ```php
   Factura::where('id_factura', $id)->update(['status' => 0]);
   AdicionalesCancelacion::create([
       'id_factura' => $id,
       'motivoCancelacion' => '02',
       'fechaCancelacion' => now(),
       'folioSustitucion' => ''
   ]);
   ```

---

## 8. Reimpresión de CFDI

### Flujo

1. **Obtener Datos de Factura**
   ```php
   $datosFactura = Utils::obtenerDatosFactura($id_factura, $id_proveedor);
   ```

2. **Regenerar XML**
   ```php
   $xml = XMLUtils::createXML40($datosFactura, $proveedor);
   ```

3. **Generar PDF**
   - Usar librería DOMPDF
   - Incluir código QR con UUID
   - Incluir cadena original
   - Incluir sellos digitales

4. **Enviar al Usuario**
   - Descargar PDF
   - Enviar por correo
   - Guardar en sistema

---

## 9. Facturación Global (Público en General)

### Flujo Específico

1. **Configurar Receptor**
   ```javascript
   id_cliente: {
       rFCRecep: "XAXX010101000",
       nmbRecep: "PUBLICO EN GENERAL",
       usoCFDI: "S01",  // Sin efectos fiscales
       regimenFiscalReceptor: "616",  // Sin obligaciones fiscales
       codigoPostal: "00000"
   }
   ```

2. **Agregar Información Global**
   ```javascript
   publico: {
       periodicidad: "01",  // Diario
       meses: "01",         // Enero
       anio: 2024
   }
   ```

3. **Sistema Auto-detecta**
   - Si RFC = XAXX010101000
   - Y nombre = "PUBLICO EN GENERAL"
   - Entonces agrega InformacionGlobal automáticamente

4. **Generar CFDI**
   - Un CFDI por periodo (día, semana, mes)
   - Agrupa todas las ventas del periodo
   - Incluye nodo `<cfdi:InformacionGlobal>`

---

## 10. Facturación a Extranjeros

### Flujo Específico

1. **Configurar Receptor Extranjero**
   ```javascript
   id_cliente: {
       rFCRecep: "XEXX010101000",
       nmbRecep: "CLIENTE EXTRANJERO",
       numRegIdTrib: "123456789",  // Tax ID del país
       regimenFiscalReceptor: "616",
       codigoPostal: "00000"
   }
   ```

2. **Configurar Exportación**
   ```javascript
   exportacion: "01"  // No aplica o definitiva
   ```

3. **Configurar Residencia Fiscal**
   ```javascript
   pais: "USA"  // Código del país
   ```

4. **Si es Comercio Exterior**
   - Agregar complemento de comercio exterior
   - Configurar domicilios en el extranjero
   - Agregar datos aduanales

---

## Errores Comunes y Soluciones

### Error 1: "Certificado no configurado"
**Solución**: Verificar que existe un CertificadoProveedor activo (status=1)

### Error 2: "UUID duplicado"
**Solución**: Error de Finkok, verificar que no se esté reenviando la misma factura

### Error 3: "Sello inválido"
**Solución**: Regenerar sello, verificar que certificado y llave coincidan

### Error 4: "Totales no cuadran"
**Solución**: Revisar cálculo de impuestos, usar formatNumber correctamente

### Error 5: "ObjetoImp requerido" (4.0)
**Solución**: Agregar campo objetoImp a cada concepto

### Error 6: "RegimenFiscalReceptor requerido" (4.0)
**Solución**: Agregar régimen fiscal del receptor

### Error 7: "Complemento Pagos inválido"
**Solución**: Verificar cálculo de impuestos por DR, validar totales

### Error 8: "Carta Porte incompleta"
**Solución**: Verificar ubicaciones, mercancías, autotransporte, figuras

---

## Mejores Prácticas

1. **Validar antes de enviar**: Revisar todos los campos requeridos
2. **Usar catálogos SAT**: Siempre validar contra catálogos actualizados
3. **Logs detallados**: Registrar cada paso del proceso
4. **Manejo de errores**: Capturar y mostrar errores específicos
5. **Reintentos inteligentes**: No reenviar si ya está timbrado
6. **Backup de XMLs**: Guardar XMLs originales y timbrados
7. **Validación de certificados**: Verificar vigencia antes de facturar
8. **Testing**: Usar ambiente demo de Finkok para pruebas
