====== wtNomina ======

La librería wtNomina encapsula todos los procesos de serialización y extracción de datos de nómina.

===== Dependencias =====
genesisEmpleado


===== Objetos =====
==== wtNomina ====
Objeto creado sobre el controles desde el que es cargada la librería wtNomina.\\ Debe ser accesado mediante la sintaxis controller->wtNomina
  * abreNomina\\ Crea un objeto wtXMLNomina con el filtro especificado\\ Sintaxis: wtNomina->abreNomina($idPersona, $idPeriodo, $filtros=null, $callBack=null); \\ejemplo <code php>
$nomina = $this->controller->wtNomina->abreNomina([$objEmpleado->id, $objEmpleado2->id], [9], ['sucursal' => '"001"']);
</code>
<code php>
//Todos los filtros aplicados son equivalentes en sus diferentes formas
//Cuando se manda un arreglo en filtros como valor de la propiedad para generar una consulta in, debe ir doblemente encomillado y escapado, ej: 'posicion_departamento' => ["'\"1\"'", "'\"2\"'"], al igual que en las sentencias de filtros del callback. Esto es porque internamente el valor es grabado dentro del JSON de esa manera: ej: "posicion_departamento": "\"1\"". En el caso de solo enviar en el array de filtros un solo valor para la propiedad, se deberá enviar con encomillado sencillo sin escapara, debido a que la plataforma ya lo hace. ej: 'sucursal' => '"001"'.
//En el callBack, si se desea agregar un filtro, se recomienda utilizar el operador ->> que a diferencia de -> el primero quita los escapes de comillas, por lo que es mucho mas sencillo especificar el valor.
$nomina           = $this->controller->wtNomina->abreNomina([1], [10,11,14,15], ['posicion_departamento' => ["'\"1\"'", "'\"2\"'"], 'posicion_departamento' => "\"1\""], function($nomina){
   $this->controller->db->where('id', 2088);
   $this->controller->db->where('nomina->>"$.propiedadesNomina.posicion_departamento" = \'"1"\'', '', false);
   $this->controller->db->where('nomina->>"$.propiedadesNomina.posicion_departamento" =', '\'"1"\'', false);
   $this->controller->db->where_in('nomina->>"$.propiedadesNomina.posicion_departamento"', "'\"1\"'", false);
   $this->controller->db->where_in('nomina->>"$.propiedadesNomina.posicion_departamento"', ["'\"1\"'"], false);
   $this->controller->db->where_in('nomina->>"$.propiedadesNomina.posicion_departamento"', ["'\"1\"'", "'\"2\"'"], false);

            
   $this->controller->db->where("json_unquote(JSON_EXTRACT(nomina, '\$.propiedadesNomina.posicion_departamento')) = '\"1\"'", '', false);
   $this->controller->db->where("json_unquote(JSON_EXTRACT(nomina, '\$.propiedadesNomina.posicion_departamento')) = ", "'\"1\"'", false);
   $this->controller->db->where_in("json_unquote(JSON_EXTRACT(nomina, '\$.propiedadesNomina.posicion_departamento'))", "'\"1\"'", false);            
   $this->controller->db->where_in("json_unquote(JSON_EXTRACT(nomina, '\$.propiedadesNomina.posicion_departamento'))", ["'\"1\"'"], false);
   $this->controller->db->where_in("json_unquote(JSON_EXTRACT(nomina, '\$.propiedadesNomina.posicion_departamento'))", ["'\"1\"'", "'\"2\"'"], false);
        });
</code>
  * cierraNomina\\ Cierra y serializa si se requiere el objeto de nomina enviado. $nomina es el objeto devuelto por abreNomina\\ Sintaxis: wtNomina->cierraNomina($nomina);
==== wtXMLNomina ====
  * clonar\\ Permite clonar el XML
  * XMLToStr\\ Representación del XML en string
  * traeEstado\\ Trae el estado de la última acción ejecutada (ok, error)\\ sintaxis: traeEstado();\\ ejemplo: <code php>
if ($nomina->traeEstado() == 'ok')
{
} //Entra a la condición si el estado está en ok.</code>
  * generaTotales()\\ Genera el nodo de totales para los registros de nómina cargados con abreNomina(), genera el atributo total además de totalizar las propiedades indicadas.\\ sintaxis: generaTotales($propiedadesAtotalizar = [])\\ ejemplo: <code php>
$nomina = $this->controller->wtNomina->abreNomina([$objEmpleado->id, $objEmpleado2->id], [9], ['sucursal' => '"001"']);
$nomina->generaTotales(['pgra'])
</code>
  * totalRegistrosNomina\\ Trae el número de registros incluidos en el objeto de nómina.\\ sintaxis: totalRegistrosNomina(); \\ ejemplo: <code php> $nomina->totalRegistrosNomina();</code>
  * timbrar() (EN DESARROLLO)\\ Timbra los registros de nómina cargados con abreNomina(). Ver formato de la estructura enviada.\\ sintaxis: timbrar($callBack)\\ ejemplo: <code php>
$nomina = $this->controller->wtNomina->abreNomina([$objEmpleado->id, $objEmpleado2->id], [9], ['sucursal' => '"001"']);
$nomina->timbrar(function(&$datos){});
</code>
  * digiboxTimbra($xml, $produccion = false)\\Timbra un XML en digibox
  * digiboxCancela($xml, &$error, $produccion = false)\\Cancela un XML en digibox
  * creaNuevoPeriodo() (EN DESARROLLO)\\ Crea el xml para el nuevo periodo en base al actual de los registros de nómina cargados con abreNomina().\\ sintaxis: creaNuevoPeriodo($callBack)\\ ejemplo: <code php>
$nomina = $this->controller->wtNomina->abreNomina([$objEmpleado->id, $objEmpleado2->id], [9], ['sucursal' => '"001"']);
$nomina->creaNuevoPeriodo(function(&$datos){});
</code>
=== Manejo de conceptos ===
  * agregaConcepto\\ Captura un nuevo concepto dentro del objeto de nómina actual, regresando el objeto de tipo concepto. El método valida si el concepto está vigente y permite capturas múltiples.\\ sintaxis: agregaConcepto($clave)
  * eliminaConcepto\\ Elimina el concepto desde el cual la llamada es invocada.\\ sintaxis: eliminaConcepto()
  * traeConcepto\\ Trae el concepto con la clave solicitada del objeto nómina desde donde es invocado el método.\\ sintaxis: traeConcepto($clave)
  * primerConcepto\\ En el caso de un concepto múltiple, trae la la primera captura, en caso de no existir mas regresará null. Es equivalente a traeConcepto.\\ sintaxis: primerConcepto($clave)
  * siguienteConcepto\\ En el caso de un concepto múltiple, trae la la siguiente captura, en caso de no existir mas regresará null.\\ sintaxis: siguienteConcepto()
  * conceptosCapturados\\ Regresa un arreglo de conceptos capturados según el filtro enviado.\\ sintaxis: conceptosCapturados($filtro)\\ ejemplo: <code php>
$nomina->conceptosCapturados(["@clave='12'", "propiedad[@nombre='captura1'] = '50'"]) //Regresa todos los conceptos capturados de clave 12 que en captura1 tengan un valor de 50.</code>
  * totalizaConceptos\\ Regresa la suma del total de los conceptos capturados según el filtro enviado.\\ sintaxis: totalizaConceptos($filtro)\\ ejemplo: <code php>$nomina->totalizaConceptos(["@clave='12'"]) //Regresa el total de todos los conceptos clave 12.</code>
  * totalizaPropiedad\\ Regresa el total de la propiedad de conceptos capturados según el filtro enviado.\\ sintaxis: totalizaConceptos($filtro)\\ ejemplo: <code php>
$nomina-> totalizaPropiedad("captura1", ["@clave='12'"]) // Regresa la suma de captura1 de todos los conceptos clave 12.
</code>
  * recorreConceptos\\ Recorre los conceptos capturados en base al filtro seleccionado.\\ sintaxis: recorreConceptos ($filtros, $callBack)\\ ejemplo: <code php>
$total= 0; 
$this->recorreConceptos (wtXMLNomina::filtroConceptoTipoPercepcion, function ($concepto) use (&$total)
        {
            $total = $total + $concepto->totalConcepto();
        });
 </code>


=== Propiedades de conceptos ===
  * agregaPropiedad\\ Le agrega una propiedad a un concepto desde el cual es invocado, el valor puede ser un escalar, string o arreglo de elementos.\\ sintaxis: agregaPropiedad($nombrePropiedad, $valor)
  * eliminaPropiedadConcepto\\ Elimina la propiedad indicada sobre el concepto desde el cual es invocado el metodo.\\ sintaxis: eliminaPropiedadConcepto($nombrePropiedad)
  * propiedadConcepto\\ Trae el valor de la propiedad indicada sobre el concepto desde el cual es invocado el metodo, en caso de no existir regresa null.\\ sintaxis: propiedadConcepto($nombrePropiedad)
  * ponTotalConcepto\\ Pone el total del concepto sobre el concepto desde el cual es invocado el metodo.\\ sintaxis: ponTotalConcepto($total)
  * totalConcepto\\ Trae el total del concepto sobre el concepto desde el cual es invocado el metodo.\\ sintaxis: totalConcepto()
  * traeDefinicionConcepto()\\ Trae un arreglo con las propiedades definidas en el catálogo de conceptos sobre el concepto desde el cual es invocado el metodo.\\ sintaxis: traeDefinicionConcepto()\\ ejemplo:<code php> $this->resAjax->insertaAccionDebug($nomina->traeConcepto('12')->traeDefinicionConcepto['descripcion']);</code>
=== Propiedades de nomina ===
  * agregaPropiedadNomina\\ Le agrega una propiedad al objeto de nómina desde el cual es invocado, el valor puede ser un escalar, string o arreglo de elementos.\\ sintaxis: agregaPropiedadNomina($nombrePropiedad, $valor)
  * eliminaPropiedadNomina\\ Elimina la propiedad del objeto de nómina desde el cual es invocado el metodo.\\ sintaxis: eliminaPropiedadNomina($nombrePropiedad)
  * propiedadNomina\\ Trae el valor de la propiedad de nómina indicada sobre el objeto desde el cual es invocado el metodo, en caso de no existir regresa null.\\ sintaxis: propiedadNomina($nombrePropiedad)
=== Registros de nómina ===
  * primerRegistro\\ Trae el primer registro de nómina en base al filtro seleccionado con abreNomina. Regresa true en caso de éxito y false si ya no existen registros disponibles.\\ sintaxis: primerRegistro()\\ ejemplo: <code php>
$nomina->primerRegistro();
 </code>
  * siguienteRegistro\\ Trae el siguiente registro de nómina en base al filtro seleccionado con abreNomina. Regresa true en caso de éxito y false si ya no existen registros disponibles.\\ sintaxis: primerRegistro()\\ ejemplo: <code php>
$nomina->primerRegistro();
While ($nomina->siguienteRegistro())
{
}
 </code>
  * traeRegistroActualId\\ Trae el número de registro actualmente cargado en el objeto de nómina.\\ sintaxis: traeRegistroActualId()\\ ejemplo: <code php>
$id = $nomina-> traeRegistroActualId();
 </code>
  * traeIdNomina\\ Trae el id de uno de los registros cargados en el objeto de nómina.\\ sintaxis: traeIdNomina($numRegistro)\\ ejemplo: <code php>
$id = $nomina->traeIdNomina($nomina->traeRegistroActualId());
 </code>
  * eliminaNomina\\ Elimina el registro de nómina actual. Nota: No se actualizan los sub-totales que se pudieron generar con anterioridad. Además ejecuta primerRegistro de manera automática regresando el valor devuelto por esta función.\\ sintaxis: eliminaNomina()\\ ejemplo: <code php>
$nomina->eliminaNomina();
 </code>

=== Constantes ===
  * const filtroConceptoTipoPercepcion = "defConcepto/@pdc='1'"; Filtro que regresa conceptos de tipo percepción.
  * const filtroConceptoTipoDeduccion = "defConcepto/@pdc='2'"; Filtro que regresa conceptos de tipo deducción.
  * const filtroConceptoTipoConcepto = "defConcepto/@pdc='3'"; Filtro que regresa conceptos de tipo concepto.
  * const filtroConceptoTipoMultiple = "defConcepto/@multiple='2'"; Filtro que regresa conceptos de tipo múltiple.
  * const filtroConceptoActivo = "defConcepto/@activo='2'"; Filtro que regresa conceptos vigentes.

=== Estructuras ===
  * Arreglo enviado a función timbrar: <code php>
        $datos = array ("idEmpresa" => "",
                        "Comprobante" => array(
                            "Version" => "3.3",
                            "Serie" => "NOM",
                            "Folio" => "1", //Indicar un folio interno
                            "Fecha" => date ("Y-m-d\Th:i:s"),
                            "Sello" => "", //Calculado por la librería, no modificar
                            "FormaPago" => "99",
                            "NoCertificado" => "", //Internamente se especifica, no modificar
                            "Certificado" => "", //Internamente se especifica, no modificarl
                            "SubTotal" => "", //TODO: Se calcula
                            "Descuento" => "", //TODO: Se calcula
                            "Moneda" => "MXN",
                            "Total" => "", //TODO: Se calcula
                            "TipoDeComprobante" => "N",
                            "MetodoPago" => "PUE",
                            "LugarExpedicion" => "", //Indicar CP
                        ),
                        "Emisor" => array(
                            "Rfc" => "", //Indicar
                            "Nombre" => "", //Indicar
                            "RegimenFiscal" => "" //Indicar
                        ),
                        "Receptor" => array(
                            "Rfc" => "", //Indicar
                            "Nombre" => "", //Indicar
                            "UsoCFDI" => "P01" 
                        ),
                        "Concepto" => array(
                            "ClaveProdServ" => "84111505",
                            "Cantidad" => "1",
                            "ClaveUnidad" => "Act",
                            "Descripcion" => "Pago de nómina",
                            "ValorUnitario" => "", //TODO: Se calcula
                            "Importe" => "", //TODO: Se calcula
                            "Descuento" => "", //TODO: Se calcula
                        ),
                        "Complemento" => array(
                            "Version" => "1.2",
                            "TipoNomina" => "O", // Indicar O/E
                            "FechaPago" => date ("Y-m-d"), //Indicar en formato enviado
                            "FechaInicialPago" => date ("Y-m-d"), //Indicar en formato enviado
                            "FechaFinalPago" => date ("Y-m-d"), //Indicar en formato enviado
                            "NumDiasPagados" => "",
                            "TotalPercepciones" => "",
                            "TotalDeducciones" => "",
                            "TotalOtrosPagos" => "",
                            "Emisor" => array (
                                "Curp" => "", //Indicar
                                "RegistroPatronal" => "" //Indicar para no asimilados
                            ),
                            "Receptor" => array (
                                "Curp" => "", //Indicar
                                "esAsimilado" => "0", // Indicar 0/1
                                "FechaInicioRelLaboral" => date ("Y-m-d"), //Indicar en formato enviado
                                "Sindicalizado" => "No", // Indicar No/Si
                                "NumSeguridadSocial" => "", //Indicar para no asimilado
                                "Antigüedad" => "",  //Indicar para no asimilado, cambiar a pedir ingreso.
                                "TipoJornada" => "", //Indicar para no asimilado, EmpPrin['TIPO_JORNADA']
                                "TipoContrato" => "", //Indicar para no asimilado
                                "TipoRegimen" => "", //Indicar para no asimilado
                                "NumEmpleado" => "", //Indicar
                                "Departamento" => "", //Indicar
                                "Puesto" => "", //Indicar
                                "RiesgoPuesto" => "", //Indicar para no asimilado
                                "PeriodicidadPago" => "", //Indicar en caso de TipoNomina=O
                                "Banco" => "", //Indicar en caso de indicar cuenta y no CLABE
                                "CuentaBancaria" => "", //Indicar CLABE o cuenta
                                "SalarioBaseCotApor" => "", //Indicar para no asimilado
                                "SalarioDiarioIntegrado" => "", //Indicar para no asimilado
                                "ClaveEntFed" => "", //Indicar
                                "RfcLabora" => "", //Indicar en caso de outSourcing
                                "PorcentajeTiempo" => "100", //Indicar en caso de outSourcing
                            )
                        )
                    );

</code>


===== Ejemplos =====
  * [[ejemploWtNomina|Ejemplo de uso de métodos de objeto wtNomina]]
  * [[ejemploWtNominaXML|Ejemplo de XML de nómina]]



