public function generaFacturaPdf($idFactura, $path = null) { include APPPATH . 'libraries/phpqrcode/qrlib.php'; $factura = $this->getDataFactura($idFactura); $xml = simplexml_load_string(str_replace(array('cfdi:', 'tfd:'), '', $factura['xml'])); // echo "<pre>"; // var_dump($factura, $xml); // echo "</pre>";exit; $this->load->library('mypdf'); // Creación del objeto de la clase heredada $pdf = new MYpdf('P', 'mm', 'Letter'); $pdf->show_head = false; $pdf->AliasNbPages(); $pdf->AddPage(); ////////// // Logo // ////////// $pdf->SetXY(0, 0); // $pdf->SetXY(30, 2); $logo = file_exists($factura['logo']) ? $factura['logo'] : 'application/images/logos/logodefault.jpg'; $pdf->Image($logo, 10, null, 0, 21); ////////////////////////// // Rfc y Regimen Fiscal // ////////////////////////// // 0, 171, 72 = verde $pdf->SetFont('helvetica', 'B', 9); // $pdf->SetFillColor(214, 214, 214); $pdf->SetTextColor(255, 255, 255); // $pdf->SetXY(0, 0); // $pdf->Cell(108, 15, "Factura Electrónica (CFDI)", 0, 0, 'C', 1); // $pdf->SetTextColor(0, 0, 0); // $pdf->SetXY(0, $pdf->GetY()); // $pdf->Cell(108, 4, "RFC: {$xml->Emisor[0]['rfc']}", 0, 0, 'C', 0); // $pdf->SetFont('helvetica','B', 12); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(0, $pdf->GetY() + 4); $pdf->Cell(108, 4, "Emisor:", 0, 0, 'L', 1); $pdf->SetFont('helvetica', '', 8); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(0, $pdf->GetY() + 4); $pdf->SetX(0); $pdf->SetAligns(array('L', 'L')); $pdf->SetWidths(array(19, 93)); $pdf->Row(array('RFC:', $xml->Emisor[0]['rfc']), false, false, null, 2, 1); $pdf->SetWidths(array(19, 196)); $pdf->SetX(0); $pdf->Row(array('NOMBRE:', $xml->Emisor[0]['nombre']), false, false, null, 2, 1); $pdf->SetX(0); $pdf->Row(array('DOMICILIO:', $xml->Emisor->DomicilioFiscal[0]['calle'] . ' No. ' . $xml->Emisor->DomicilioFiscal[0]['noExterior'] . (isset($xml->Emisor->DomicilioFiscal[0]['noInterior']) ? ' Int. ' . $xml->Emisor->DomicilioFiscal[0]['noInterior'] : '')), false, false, null, 2, 1); $pdf->SetWidths(array(19, 83, 19, 83)); $pdf->SetX(0); $pdf->Row(array('COLONIA:', $xml->Emisor->DomicilioFiscal[0]['colonia'], 'LOCALIDAD:', $xml->Emisor->DomicilioFiscal[0]['localidad']), false, false, null, 2, 1); $pdf->SetWidths(array(19, 65, 11, 65, 11, 40)); $pdf->SetX(0); $pdf->Row(array('ESTADO:', $xml->Emisor->DomicilioFiscal[0]['estado'], 'PAIS:', $xml->Emisor->DomicilioFiscal[0]['pais'], 'CP:', $xml->Emisor->DomicilioFiscal[0]['codigoPostal']), false, false, null, 2, 1); $end_y = $pdf->GetY(); ///////////////////////////////////// // Folio Fisca, CSD, Lugar y Fecha // ///////////////////////////////////// $pdf->SetFont('helvetica', 'B', 9); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, 0); $pdf->Cell(108, 4, "Folio Fiscal:", 0, 0, 'R', 1); $pdf->SetXY(109, 0); $pdf->Cell(50, 4, (!isset($factura['id_nc']) ? 'Factura' : 'Nota de Crédito') . ': ' . ($factura['serie'] . $factura['folio']), 0, 0, 'L', 1); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, 6); $pdf->Cell(108, 4, $xml->Complemento->TimbreFiscalDigital[0]['UUID'], 0, 0, 'C', 0); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pdf->Cell(108, 4, "No de Serie del Certificado del CSD:", 0, 0, 'R', 1); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pdf->Cell(108, 4, $xml->Complemento->TimbreFiscalDigital[0]['noCertificadoSAT'], 0, 0, 'C', 0); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pdf->Cell(108, 4, "Lugar. fecha y hora de emisión:", 0, 0, 'R', 1); $pdf->SetFont('helvetica', '', 9); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pais = strtoupper($xml->Emisor->DomicilioFiscal[0]['pais']); $estado = strtoupper($xml->Emisor->DomicilioFiscal[0]['estado']); $fecha = $xml[0]['fecha']; $pdf->Cell(108, 4, "{$pais} {$estado} {$fecha}", 0, 0, 'R', 0); $pdf->SetFont('helvetica', 'b', 9); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pdf->Cell(108, 4, "Régimen Fiscal:", 0, 0, 'R', 1); $pdf->SetFont('helvetica', '', 9); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(109, $pdf->GetY() + 4); $pdf->MultiCell(108, 4, $xml->Emisor->RegimenFiscal[0]['Regimen'], 0, 'C', 0); ////////////////// // domicilioEmisor // ////////////////// // $domicilioEmisor = ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['calle'])) ? $xml->Emisor->DomicilioFiscal[0]['calle'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['noExterior'])) ? ' #'.$xml->Emisor->DomicilioFiscal[0]['noExterior'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['noInterior'])) ? ' Int. '.$xml->Emisor->DomicilioFiscal[0]['noInterior'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['colonia'])) ? ', '.$xml->Emisor->DomicilioFiscal[0]['colonia'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['localidad'])) ? ', '.$xml->Emisor->DomicilioFiscal[0]['localidad'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['municipio'])) ? ', '.$xml->Emisor->DomicilioFiscal[0]['municipio'] : ''; // $domicilioEmisor .= (isset($xml->Emisor->DomicilioFiscal[0]['estado'])) ? ', '.$xml->Emisor->DomicilioFiscal[0]['estado'] : ''; // $pdf->SetFont('helvetica','B', 9); // $pdf->SetFillColor(140,140, 140); // $pdf->SetTextColor(255,255,255); // $pdf->SetXY(0, $pdf->GetY() + 4); // $pdf->Cell(216, 4, "Domicilio:", 0, 0, 'L', 1); // $pdf->SetFont('helvetica','', 9); // $pdf->SetTextColor(0, 0, 0); // $pdf->SetXY(0, $pdf->GetY() + 4); // $pdf->Cell(216, 4, $domicilioEmisor, 0, 0, 'C', 0); ////////////////// // Datos Receptor // ////////////////// $pdf->setY($end_y); $domicilioReceptor = ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['calle']) ? $xml->Receptor->Domicilio[0]['calle'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['noExterior']) ? ' #' . $xml->Receptor->Domicilio[0]['noExterior'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['noInterior']) ? ' Int. ' . $xml->Receptor->Domicilio[0]['noInterior'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['colonia']) ? ', ' . $xml->Receptor->Domicilio[0]['colonia'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['localidad']) ? ', ' . $xml->Receptor->Domicilio[0]['localidad'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['municipio']) ? ', ' . $xml->Receptor->Domicilio[0]['municipio'] : ''; $domicilioReceptor .= isset($xml->Receptor->Domicilio[0]['estado']) ? ', ' . $xml->Receptor->Domicilio[0]['estado'] : ''; $pdf->SetFillColor(214, 214, 214); $pdf->SetXY(0, $pdf->GetY() + 4); $pdf->Cell(216, 1, "", 0, 0, 'L', 1); $pdf->SetFont('helvetica', 'B', 9); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(255, 255, 255); $pdf->SetXY(0, $pdf->GetY() + 1); $pdf->Cell(216, 4, "Receptor:", 0, 0, 'L', 1); $pdf->SetFont('helvetica', '', 8); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(0, $pdf->GetY() + 4); $pdf->SetX(0); $pdf->SetAligns(array('L', 'L')); $pdf->SetWidths(array(19, 93)); $pdf->Row(array('RFC:', $xml->Receptor[0]['rfc']), false, false, null, 2, 1); $pdf->SetWidths(array(19, 196)); $pdf->SetX(0); $pdf->Row(array('NOMBRE:', $xml->Receptor[0]['nombre']), false, false, null, 2, 1); $pdf->SetX(0); $pdf->Row(array('DOMICILIO:', (isset($xml->Receptor->Domicilio[0]['calle']) ? $xml->Receptor->Domicilio[0]['calle'] : '') . ' No. ' . (isset($xml->Receptor->Domicilio[0]['noExterior']) ? $xml->Receptor->Domicilio[0]['noExterior'] : '') . (isset($xml->Receptor->Domicilio[0]['noInterior']) ? ' Int. ' . $xml->Receptor->Domicilio[0]['noInterior'] : '')), false, false, null, 2, 1); $pdf->SetWidths(array(19, 83, 19, 83)); $pdf->SetX(0); $pdf->Row(array('COLONIA:', isset($xml->Receptor->Domicilio[0]['colonia']) ? $xml->Receptor->Domicilio[0]['colonia'] : '', 'LOCALIDAD:', isset($xml->Receptor->Domicilio[0]['localidad']) ? $xml->Receptor->Domicilio[0]['localidad'] : ''), false, false, null, 2, 1); $pdf->SetWidths(array(19, 65, 11, 65, 11, 40)); $pdf->SetX(0); $pdf->Row(array('ESTADO:', isset($xml->Receptor->Domicilio[0]['estado']) ? $xml->Receptor->Domicilio[0]['estado'] : '', 'PAIS:', isset($xml->Receptor->Domicilio[0]['pais']) ? $xml->Receptor->Domicilio[0]['pais'] : '', 'CP:', isset($xml->Receptor->Domicilio[0]['codigoPostal']) ? $xml->Receptor->Domicilio[0]['codigoPostal'] : ''), false, false, null, 2, 1); // $pdf->Cell(216, 4, "Nombre: {$xml->Receptor[0]['nombre']} RFC: {$xml->Receptor[0]['rfc']}", 0, 0, 'L', 0); // $pdf->SetFont('helvetica','', 9); // $pdf->SetTextColor(0, 0, 0); // $pdf->SetXY(0, $pdf->GetY() + 4); // $pdf->Cell(216, 4, "Domicilio: {$domicilioReceptor}", 0, 0, 'L', 0); /////////////// // Productos // /////////////// $pdf->SetFillColor(214, 214, 214); $pdf->SetXY(0, $pdf->GetY() + 5); $pdf->Cell(216, 1, "", 0, 0, 'L', 1); $pdf->SetXY(0, $pdf->GetY()); $aligns = array('C', 'C', 'C', 'C', 'C'); $aligns2 = array('C', 'C', 'C', 'R', 'R'); $widths = array(30, 35, 91, 30, 30); $header = array('Cantidad', 'Unidad de Medida', 'Descripcion', 'Precio Unitario', 'Importe'); $conceptos = current($xml->Conceptos); // for ($i=0; $i < 30; $i++) // $conceptos[] = $conceptos[$i]; // echo "<pre>"; // var_dump($conceptos, is_array($conceptos)); // echo "</pre>";exit; if (!is_array($conceptos)) { $conceptos = array($conceptos); } $pdf->limiteY = 250; $pdf->setY($pdf->GetY() + 1); foreach ($conceptos as $key => $item) { $band_head = false; if ($pdf->GetY() >= $pdf->limiteY || $key === 0) { if ($key > 0) { $pdf->AddPage(); } $pdf->SetFont('Arial', 'B', 8); $pdf->SetTextColor(0, 0, 0); $pdf->SetFillColor(219, 219, 219); $pdf->SetX(0); $pdf->SetAligns($aligns); $pdf->SetWidths($widths); $pdf->Row($header, true, true, null, 2, 1); } $pdf->SetFont('Arial', '', 8); $pdf->SetTextColor(0, 0, 0); $pdf->SetX(0); $pdf->SetAligns($aligns2); $pdf->SetWidths($widths); $pdf->Row(array($item[0]['cantidad'], $item[0]['unidad'], $item[0]['descripcion'], String::formatoNumero($item[0]['valorUnitario'], 2, '$', false), String::formatoNumero($item[0]['importe'], 2, '$', false)), false, true, null, 2, 1); } ///////////// // Totales // ///////////// if ($pdf->GetY() + 30 >= $pdf->limiteY) { //salta de pagina si exede el max $pdf->AddPage(); } // Traslados | IVA $ivas = current($xml->Impuestos->Traslados); /*if ( ! is_array($ivas)) { $ivas = array($ivas); }*/ $traslado11 = 0; $traslado16 = 0; foreach ($ivas as $key => $iva) { if ($iva[0]['tasa'] == '11') { $traslado11 = $iva[0]['importe']; } elseif ($iva[0]['tasa'] == '16') { $traslado16 = $iva[0]['importe']; } } $pdf->SetFillColor(214, 214, 214); $pdf->SetXY(0, $pdf->GetY()); $pdf->Cell(216, 1, "", 0, 0, 'L', 1); $h = 25 - ($traslado11 == 0 ? 5 : 0); $h = $h - ($xml->Impuestos->Retenciones->Retencion[0]['importe'] == 0 ? 5 : 0); $pdf->SetFillColor(219, 219, 219); $pdf->SetXY(0, $pdf->GetY() + 1); $pdf->Cell(156, $h, "", 1, 0, 'L', 1); $pdf->SetFont('helvetica', 'B', 9); $pdf->SetXY(1, $pdf->GetY() + 1); $pdf->Cell(154, 4, "Total con letra:", 0, 0, 'L', 1); $pdf->SetFont('helvetica', '', 10); $pdf->SetXY(0, $pdf->GetY() + 4); $pdf->MultiCell(156, 6, $factura['total_letra'], 0, 'C', 0); $pdf->SetFont('helvetica', 'B', 9); $pdf->SetXY(1, $pdf->GetY()); $pdf->Cell(78, 4, $xml[0]['formaDePago'], 0, 0, 'L', 1); $pdf->SetFont('helvetica', 'B', 9); $pdf->SetXY(78, $pdf->GetY()); $pdf->Cell(78, 4, "Pago en {$xml[0]['metodoDePago']}", 0, 0, 'L', 1); $pdf->SetFont('helvetica', 'B', 10); $pdf->SetXY(156, $pdf->GetY() - 11); $pdf->Cell(30, 5, "Subtotal", 1, 0, 'C', 1); $pdf->SetXY(186, $pdf->GetY()); $pdf->Cell(30, 5, String::formatoNumero($xml[0]['subTotal'], 2, '$', false), 1, 0, 'R', 1); // Pinta traslados, retenciones if ($traslado11 != 0) { $pdf->SetXY(156, $pdf->GetY() + 5); $pdf->Cell(30, 5, "IVA(11%)", 1, 0, 'C', 1); $pdf->SetXY(186, $pdf->GetY()); $pdf->Cell(30, 5, String::formatoNumero($traslado11, 2, '$', false), 1, 0, 'R', 1); } $pdf->SetXY(156, $pdf->GetY() + 5); $pdf->Cell(30, 5, "IVA(16%)", 1, 0, 'C', 1); $pdf->SetXY(186, $pdf->GetY()); $pdf->Cell(30, 5, String::formatoNumero($traslado16, 2, '$', false), 1, 0, 'R', 1); if ($xml->Impuestos->Retenciones->Retencion[0]['importe'] != 0) { $pdf->SetXY(156, $pdf->GetY() + 5); $pdf->Cell(30, 5, "IVA Retenido", 1, 0, 'C', 1); $pdf->SetXY(186, $pdf->GetY()); $pdf->Cell(30, 5, String::formatoNumero($xml->Impuestos->Retenciones->Retencion[0]['importe'], 2, '$', false), 1, 0, 'R', 1); } $pdf->SetXY(156, $pdf->GetY() + 5); $pdf->Cell(30, 5, "TOTAL", 1, 0, 'C', 1); $pdf->SetXY(186, $pdf->GetY()); $pdf->Cell(30, 5, String::formatoNumero($xml[0]['total'], 2, '$', false), 1, 0, 'R', 1); /////////////////// // Observaciones // /////////////////// $pdf->SetXY(0, $pdf->GetY() + 5); $width = $pdf->GetStringWidth($factura['observaciones']) / 216 * 8 + 9; if ($pdf->GetY() + $width >= $pdf->limiteY) { //salta de pagina si exede el max $pdf->AddPage(); } if (!empty($factura['observaciones'])) { $pdf->SetX(0); $pdf->SetFont('helvetica', 'B', 10); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(216)); $pdf->Row(array('Observaciones'), true); $pdf->SetFont('helvetica', '', 9); $pdf->SetXY(0, $pdf->GetY()); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(216)); $pdf->Row(array($factura['observaciones']), true, 1); } //////////////////// // Timbrado Datos // //////////////////// if ($pdf->GetY() + 25 >= $pdf->limiteY) { //salta de pagina si exede el max $pdf->AddPage(); } $pdf->SetFont('helvetica', 'B', 8); $pdf->SetXY(10, $pdf->GetY() + 8); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(196)); $pdf->Row(array('Sello Digital del CFDI:'), false, 0); $pdf->SetFont('helvetica', '', 8); $pdf->SetY($pdf->GetY()); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(196)); $pdf->Row(array($xml->Complemento->TimbreFiscalDigital[0]['selloCFD']), false, 0); if ($pdf->GetY() + 25 >= $pdf->limiteY) { //salta de pagina si exede el max $pdf->AddPage(); } $pdf->SetFont('helvetica', 'B', 8); $pdf->SetXY(10, $pdf->GetY() + 5); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(196)); $pdf->Row(array('Sello Digital del SAT:'), false, 0); $pdf->SetFont('helvetica', '', 8); $pdf->SetY($pdf->GetY()); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(196)); $pdf->Row(array($xml->Complemento->TimbreFiscalDigital[0]['selloSAT']), false, 0); ///////////// // QR CODE // ///////////// // formato // ?re=XAXX010101000&rr=XAXX010101000&tt=1234567890.123456&id=ad662d33-6934-459c-a128-BDf0393f0f44 // 0000001213.520000 $total = explode('.', $xml[0]['total']); // Obtiene la diferencia de caracteres en la parte entera. $diff = 10 - strlen($total[0]); // Agrega los 0 faltantes a la parte entera. for ($i = 0; $i < $diff; $i++) { $total[0] = "0{$total[0]}"; } // Si el total no contiene decimales le asigna en la parte decimal 6 ceros. if (count($total) === 1) { $total[1] = '000000'; } else { // Obtiene la diferencia de caracteres en la parte decimal. $diff = 6 - strlen($total[1]); // Agregar los 0 restantes en la parte decimal. for ($i = 0; $i < $diff; $i++) { $total[1] = "{$total[1]}0"; } } $code = "?re={$xml->Emisor[0]['rfc']}"; $code .= "&rr={$xml->Receptor[0]['rfc']}"; $code .= "&tt={$total[0]}.{$total[1]}"; $code .= "&id={$xml->Complemento->TimbreFiscalDigital[0]['UUID']}"; // echo "<pre>"; // var_dump($code, $total, $diff); // echo "</pre>";exit; QRcode::png($code, APPPATH . 'media/qrtemp.png', 'H', 3); if ($pdf->GetY() + 50 >= $pdf->limiteY) { //salta de pagina si exede el max $pdf->AddPage(); } $pdf->SetXY(0, $pdf->GetY()); $pdf->Image(APPPATH . 'media/qrtemp.png', null, null, 40); // Elimina el QR generado temporalmente. unlink(APPPATH . 'media/qrtemp.png'); //////////////////// // Timbrado Datos // //////////////////// $pdf->SetFont('helvetica', 'B', 8); $pdf->SetXY(45, $pdf->GetY() - 39); $pdf->SetAligns(array('L')); $pdf->SetWidths(array(160)); $pdf->Row(array('Cadena Original del complemento de certificación digital del SAT:'), false, 0); $pdf->SetFont('helvetica', '', 8); $cadenaOriginalSAT = "||{$xml->Complemento->TimbreFiscalDigital[0]['version']}|{$xml->Complemento->TimbreFiscalDigital[0]['UUID']}|{$xml->Complemento->TimbreFiscalDigital[0]['FechaTimbrado']}|{$xml->Complemento->TimbreFiscalDigital[0]['selloCFD']}|{$xml->Complemento->TimbreFiscalDigital[0]['noCertificadoSAT']}||"; $pdf->SetXY(45, $pdf->GetY()); $pdf->Row(array($cadenaOriginalSAT), false, 0); $pdf->SetFont('helvetica', 'B', 10); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(45, $pdf->GetY() + 1); $pdf->Cell(80, 6, "No de Serie del Certificado del SAT:", 0, 0, 'R', 1); $pdf->SetXY(125, $pdf->GetY()); $pdf->SetTextColor(0, 0, 0); $pdf->Cell(65, 6, $xml->Complemento->TimbreFiscalDigital[0]['noCertificadoSAT'], 0, 0, 'C', 0); $pdf->SetFont('helvetica', 'B', 10); $pdf->SetFillColor(219, 219, 219); $pdf->SetTextColor(0, 0, 0); $pdf->SetXY(45, $pdf->GetY() + 10); $pdf->Cell(80, 6, "Fecha y hora de certificación:", 0, 0, 'R', 1); $pdf->SetXY(125, $pdf->GetY()); $pdf->SetTextColor(0, 0, 0); $pdf->Cell(65, 6, $xml->Complemento->TimbreFiscalDigital[0]['FechaTimbrado'], 0, 0, 'C', 0); //------------ IMAGEN CANDELADO -------------------- if ($factura['status'] === 'ca') { $pdf->Image(APPPATH . '/images/cancelado.png', 20, 40, 190, 190, "PNG"); } if ($path) { $pdf->Output($path . 'Factura.pdf', 'F'); } else { $pdf->Output('Factura', 'I'); } }