Skip to content

Nómina Individual de Novedad

Corrección Monetaria TipoXML: 102

La Nómina Individual de Novedad se utiliza para corregir valores monetarios de un documento de nómina previamente emitido. Este tipo de documento permite ajustar:

  • Montos de devengados incorrectos
  • Valores de deducciones erradas
  • Totales que no cuadran
  • Porcentajes mal calculados

Devengados Incorrectos

  • Sueldo mal liquidado
  • Horas extras calculadas erradamente
  • Bonificaciones con monto incorrecto
  • Auxilio de transporte errado

Deducciones Erróneas

  • Porcentaje de salud incorrecto
  • Deducción de pensión mal calculada
  • Libranzas con valor equivocado
  • Retención en la fuente errada

Totales Descuadrados

  • DevengadosTotal no cuadra
  • DeduccionesTotal incorrectas
  • ComprobanteTotal errado
  • Redondeos mal aplicados

Ajustes Posteriores

  • Reconocimientos adicionales
  • Ajustes por convenios
  • Correcciones contables
  • Pagos complementarios

Diferencias con Nómina Individual Estándar

Section titled “Diferencias con Nómina Individual Estándar”

El XML de Novedad es idéntico a la Nómina Individual, con 2 cambios clave:

  1. Nodo Novedad Activo

    <Novedad CUNENov="[CUNE_DEL_DOCUMENTO_A_CORREGIR]">true</Novedad>
  2. Valores Monetarios Corregidos

    • Solo se incluyen los campos que cambian
    • Los totales deben recalcularse
    • Todos los campos monetarios son modificables

Nómina de Novedad - Ejemplo
<?xml version="1.0" encoding="UTF-8"?>
<NominaIndividual
xmlns="dian:gov:co:facturaelectronica:NominaIndividual"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
SchemaLocation=""
xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd">
<ext:UBLExtensions/>
<!-- CLAVE: Novedad en TRUE con CUNE del documento a corregir -->
<Novedad CUNENov="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2">true</Novedad>
<Periodo
FechaIngreso="2024-01-01"
FechaRetiro=""
FechaLiquidacionInicio="2024-11-01"
FechaLiquidacionFin="2024-11-30"
TiempoLaborado="330"
FechaGen="2024-11-25"/>
<!-- Nuevo consecutivo para la novedad -->
<NumeroSecuenciaXML
CodigoTrabajador="001"
Prefijo="NOV"
Consecutivo="00001"
Numero="NOV00001"/>
<LugarGeneracionXML
Pais="CO"
DepartamentoEstado="68"
MunicipioCiudad="68001"
Idioma="es"/>
<InformacionGeneral
Version="V1.0: Documento Soporte de Pago de Nómina Electrónica"
Ambiente="2"
TipoXML="102"
CUNE=""
EncripCUNE=""
FechaGen="2024-11-25"
HoraGen="16:30:00-05:00"
PeriodoNomina="5"
TipoMoneda="COP"
TRM="1"/>
<Notas>Corrección de valores monetarios de la nómina NOM35921. Se ajusta el valor del sueldo trabajado y deducciones.</Notas>
<Empleador
RazonSocial="MI EMPRESA SAS"
NIT="901143311"
DV="8"
Pais="CO"
DepartamentoEstado="68"
MunicipioCiudad="68001"
Direccion="Calle 123 # 45-67"/>
<Trabajador
TipoTrabajador="01"
SubTipoTrabajador="00"
AltoRiesgoPension="false"
TipoDocumento="13"
NumeroDocumento="1234567890"
PrimerApellido="PEREZ"
SegundoApellido="GOMEZ"
PrimerNombre="JUAN"
OtrosNombres="CARLOS"
LugarTrabajoPais="CO"
LugarTrabajoDepartamentoEstado="68"
LugarTrabajoMunicipioCiudad="68001"
LugarTrabajoDireccion="Carrera 27 # 34-56"
SalarioIntegral="false"
TipoContrato="1"
Sueldo="1400000"
CodigoTrabajador="001"/>
<Pago
Forma="1"
Metodo="10"
Banco="BANCOLOMBIA"
TipoCuenta="AHORROS"
NumeroCuenta="12345678901"/>
<FechasPagos>
<FechaPago>2024-11-30</FechaPago>
</FechasPagos>
<!-- VALORES CORREGIDOS -->
<Devengados>
<!-- Sueldo corregido: era 1,300,000 ahora 1,400,000 -->
<Basico DiasTrabajados="30" SueldoTrabajado="1400000"/>
<Transporte AuxilioTransporte="162000"/>
</Devengados>
<Deducciones>
<!-- Deducciones recalculadas sobre nuevo total -->
<Salud Porcentaje="4.00" Deduccion="62480"/>
<FondoPension Porcentaje="4.00" Deduccion="62480"/>
</Deducciones>
<Redondeo>0.00</Redondeo>
<!-- TOTALES RECALCULADOS -->
<DevengadosTotal>1562000.00</DevengadosTotal>
<DeduccionesTotal>124960.00</DeduccionesTotal>
<ComprobanteTotal>1437040.00</ComprobanteTotal>
</NominaIndividual>

Logo de starlight
GenerarNominaDeNovedad.php
<?php
class Nomina_Service_NovedadGenerator
{
private $xmlGenerator;
private $db;
public function __construct()
{
$this->xmlGenerator = new Nomina_Service_XMLGenerator();
$this->db = Zend_Db_Table::getDefaultAdapter();
}
/**
* Genera XML de Novedad para corregir valores monetarios
*
* @param int $nominaOriginalId ID de la nómina a corregir
* @param array $valoresCorregidos Valores a corregir
* @return string XML de novedad
*/
public function generarNovedad($nominaOriginalId, $valoresCorregidos)
{
// 1. Obtener nómina original
$nominaOriginal = $this->obtenerNomina($nominaOriginalId);
if (!$nominaOriginal) {
throw new Exception("Nómina original no encontrada");
}
// 2. Verificar que tiene CUNE
if (empty($nominaOriginal['cune'])) {
throw new Exception("La nómina original no tiene CUNE. Debe estar autorizada.");
}
// 3. Crear datos de novedad
$datosNovedad = $this->prepararDatosNovedad(
$nominaOriginal,
$valoresCorregidos
);
// 4. Generar XML
$xml = $this->xmlGenerator->generarNominaIndividual($datosNovedad);
// 5. Activar nodo Novedad en XML
$xml = $this->activarNodoNovedad($xml, $nominaOriginal['cune']);
// 6. Validar XML
$validator = new Nomina_Service_XMLValidator();
if (!$validator->validar($xml)) {
throw new Exception(
'XML de novedad inválido: ' .
implode(', ', $validator->getErrores())
);
}
return $xml;
}
private function prepararDatosNovedad($original, $correciones)
{
$datos = $original; // Copiar datos originales
// Generar nuevo consecutivo para novedad
$datos['prefijo'] = 'NOV';
$datos['consecutivo'] = $this->obtenerSiguienteConsecutivo('NOV');
$datos['numero'] = $datos['prefijo'] . $datos['consecutivo'];
// Nueva fecha de generación
$datos['fecha_generacion'] = date('Y-m-d');
$datos['hora_generacion'] = date('H:i:s-05:00');
// Aplicar correcciones monetarias
if (isset($correciones['sueldo_trabajado'])) {
$datos['sueldo_trabajado'] = $correciones['sueldo_trabajado'];
}
if (isset($correciones['devengados'])) {
$datos['devengados'] = array_merge(
$datos['devengados'],
$correciones['devengados']
);
}
if (isset($correciones['deducciones'])) {
$datos['deducciones'] = array_merge(
$datos['deducciones'],
$correciones['deducciones']
);
}
// Recalcular totales
$datos = $this->recalcularTotales($datos);
// Agregar nota explicativa
$datos['notas'] = sprintf(
"Corrección de valores monetarios de la nómina %s. " .
"Se ajustan los siguientes conceptos: %s",
$original['numero'],
implode(', ', array_keys($correciones))
);
return $datos;
}
private function activarNodoNovedad($xmlString, $cuneOriginal)
{
$xml = new DOMDocument();
$xml->loadXML($xmlString);
// Buscar nodo Novedad
$novedad = $xml->getElementsByTagName('Novedad')->item(0);
if (!$novedad) {
throw new Exception('Nodo Novedad no encontrado en XML');
}
// Activar novedad
$novedad->setAttribute('CUNENov', $cuneOriginal);
$novedad->nodeValue = 'true';
return $xml->saveXML();
}
private function recalcularTotales($datos)
{
// Calcular DevengadosTotal
$devengadosTotal = 0;
// Sueldo básico
$devengadosTotal += (float)$datos['sueldo_trabajado'];
// Auxilio de transporte
if (isset($datos['devengados']['auxilio_transporte'])) {
$devengadosTotal += (float)$datos['devengados']['auxilio_transporte'];
}
// Horas extras, bonificaciones, etc.
foreach ($datos['devengados'] as $concepto => $valor) {
if (is_numeric($valor)) {
$devengadosTotal += (float)$valor;
}
}
// Calcular DeduccionesTotal
$deduccionesTotal = 0;
foreach ($datos['deducciones'] as $concepto => $deduccion) {
if (isset($deduccion['valor'])) {
$deduccionesTotal += (float)$deduccion['valor'];
}
}
// Calcular ComprobanteTotal
$comprobanteTotal = $devengadosTotal - $deduccionesTotal;
// Aplicar redondeo si es necesario
$redondeo = 0;
// Actualizar datos
$datos['devengados_total'] = round($devengadosTotal, 2);
$datos['deducciones_total'] = round($deduccionesTotal, 2);
$datos['comprobante_total'] = round($comprobanteTotal, 2);
$datos['redondeo'] = round($redondeo, 2);
return $datos;
}
private function obtenerSiguienteConsecutivo($prefijo)
{
$ultimo = $this->db->fetchOne("
SELECT MAX(CAST(consecutivo AS UNSIGNED))
FROM nomina_electronica
WHERE prefijo = ?
", [$prefijo]);
return str_pad((int)$ultimo + 1, 5, '0', STR_PAD_LEFT);
}
}

Antes de Generar

  • Nómina original está autorizada
  • CUNE original disponible
  • Solo se corrigen valores monetarios
  • Totales recalculados correctamente

Durante Generación

  • Nodo Novedad en true
  • CUNENov con CUNE correcto
  • Nuevo consecutivo (prefijo NOV)
  • Fecha de generación actualizada

Después de Enviar

  • Registrar relación con nómina original
  • Actualizar estado de original
  • Notificar al empleado
  • Documentar motivo de corrección