El día de hoy les compartimos nuestro desarrollo para la integración de vTiger con el Timbrado de CFDI.

Paso 1:

Crear los campos adicionales solicitados por el SAT para el timbrado de facturas.

1.1 – Pantalla Contactos:

Integración de vTiger con el Timbrado de CFDI

1.2 – Pantalla Invoice:

Integración de vTiger con el Timbrado de CFDI

Integración de vTiger con el Timbrado de CFDI

Paso 2:

El timbrado de la factura se realizará por medio de un flujo de trabajo, para lograr esto, es necesario crear un Handler y su clase asociada que ejecuta la acción, recibiendo la entidad Invoice como parámetro. 

2.1 – Crear el archivo include/InvoiceHandler.php

<? php
function handleInvoice($entity) {
	require_once("include/utils/InventoryUtils.php");
	createCFDI($entity);
}
?>

2.2 – Modificar el archivo InventoryUtils.php:

<? php
function createCFDI($entity) {
    global $log, $adb;
    $entity_id = vtws_getIdComponents($entity->getId());
    $entity_id = $entity_id[1];
    $query="select contactid, subtotal, total from vtiger_invoice where invoiceid=?";
    $resultInvoice=$adb->pquery($query, array($entity_id));
    $contactid=$adb->query_result($resultInvoice,0,'contactid');
    $subTotal = $adb->query_result($resultInvoice,0,'subtotal');
    $total = $adb->query_result($resultInvoice,0,'total');
    $rfc = 'RFC DE LA EMPRESA A TIMBRAR';
    $folio = $entity_id;
    $serie = 'A';
    $lugarExpedicion =CP DE LA EMPRESA  A TIMBRAR;
    $fecha = time();
    $fechaOperacion =  date("Y-m-d", $fecha);
    //Modificar los campos por los identificadores de los campos creados en la nueva instalación de vTiger 
    $query = "select cf_1262, cf_1264, cf_1266, cf_1260, cf_1268 from vtiger_invoicecf where invoiceid=?";
    $resultInvoiceDetail = $adb->pquery($query, array($entity_id));
    $formaPago = substr($adb->query_result($resultInvoiceDetail, 0, 'cf_1262'), 0, 2)  ;
    $metodoPago =  substr($adb->query_result($resultInvoiceDetail, 0, 'cf_1264'),0,3);     
    $moneda =  $adb->query_result($resultInvoiceDetail, 0, 'cf_1260');
    $tipoCambio = $adb->query_result($resultInvoiceDetail, 0, 'cf_1268');
    $tipoDeComprobante = $adb->query_result($resultInvoiceDetail, 0, 'cf_1266');
    //El ejemplo actual solo timbra comprobantes de ingreso
    if ($tipoDeComprobante == 'Ingreso') {
        $tipoDeComprobante ='I';
         //Modificar los campos por los identificadores de los campos creados en la nueva instalación de vTiger 
        $query = "select cf_1284,cf_894  from vtiger_contactscf where contactid=?";
        $resultContact = $adb->pquery($query, array($contactid));
        $receptorNombre =  $adb->query_result($resultContact, 0, 'cf_1284');
        $receptorRFC =  $adb->query_result($resultContact, 0, 'cf_894');
        $usoCFDI = "G03"; //En caso de no querer tener un tipo de gasto por default, agregarlo a los datos del contacto
        $query = "select productid,quantity,listprice, tax1 from vtiger_inventoryproductrel where id=?";
        $resultProduct = $adb->pquery($query, array($entity_id));
        $params = array (
                    'EmpresaRfc' => $rfc,
                    'CondicionesDePago' => $condicionsPago,
                    'Folio' => $folio,
                    'Serie' => $serie,
                    'FormaPago' => $formaPago,
                    'LugarExpedicion' => $lugarExpedicion,
                    'MetodoPago' => $metodoPago,
                    'Moneda' => $moneda,
                    'TipoDeComprobante' => $tipoDeComprobante,
                    'TipoCambio' => $tipoCambio,
                    'FechaOperacion' => $fechaOperacion,
                    'SubTotal' => $subTotal,
                    'Total' => $total,
                    'Receptor' => json_encode(array(array(
                        'Nombre' => $receptorNombre,
                        'Rfc' => $receptorRFC,
                        'UsoCFDI' => $usoCFDI
                        ))),
                    'Comentario' => 'FACTURA DE VTIGER'
                    );
$conceptos = array();
        if ($adb->num_rows($resultProduct) > 0) {
            for($j=0; $j<$adb->num_rows($resultProduct); $j++){
                $productId =  $adb->query_result($resultProduct,0,'productid');
                $cantidad =  $adb->query_result($resultProduct,0,'quantity');
                $listprice =  $adb->query_result($resultProduct,0,'listprice');
                $noIdentificacion = $productId;
                $valorUnitario = $listprice;
                $tax1 =  $adb->query_result($resultProduct,0,'tax1');
                $importe = $cantidad * $listprice;
                $query = "select product_no,productname,productcode, productsheet from vtiger_products where productid=?";
                $resultProductDesc = $adb->pquery($query, array($productId));
                $product_no =  $adb->query_result($resultProductDesc,0,'product_no');
                $descripcion =  $adb->query_result($resultProductDesc,0,'productname');
                $claveProdServ =  $adb->query_result($resultProductDesc,0,'productcode');
                $claveUnidad =  $adb->query_result($resultProductDesc,0,'productsheet');
                $impuestosBase = $importe;
                $impuestosImporte = $importe * ($tax1/100);
                $tipoFactor = "Tasa";
                $tasaOCuota = $tax1;
                $impuestoId = "002";
                $concepto = array(
                    "Cantidad" => $cantidad,
                    "ClaveProdServ"=>$claveProdServ,
                    "Descripcion" => $descripcion,
                    "Importe" =>$importe,
                    "ClaveUnidad" => $claveUnidad,
                    "Unidad" => $claveUnidad,
                    "ValorUnitario" => $valorUnitario,
                    "NoIdentificacion" => $noIdentificacion,
                    "Impuestos" => array(
                        "Base" =>  $impuestosBase,
                        "Importe" => $impuestosImporte,
                        "TipoFactor" => $tipoFactor,
                        "TasaOCuota" => $tasaOCuota,
                        "Impuesto" => $impuestoId,
                        )
                    );
                    array_push($conceptos,$concepto);
            }
            $params['Conceptos'] = json_encode($conceptos);
        }
        $contrasena = CONTRASEÑA DEL CLIENTE
        $defaults = array(
            CURLOPT_URL => 'https://app.gestioncorporativa.net/service/timbradoComprobante.php/timbradocomprobante/USUARIO/'.$contrasena,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $params,
            CURLOPT_VERBOSE => 0,
            CURLOPT_RETURNTRANSFER => 1
        );

  $curl = curl_init();
        curl_setopt_array($curl,$defaults);
        $contenido = curl_exec($curl);
        curl_close($curl);
        $response = json_decode($contenido, true);

        $result = $response['result'];
        if ($result == 'OK') {

            $idComprobante = $response['idComprobante'];
            $message = $response['message'];
            $UUID = $response['documentos']['UUID'];
            $XML = $response['documentos']['XML'];
            $PDF = $response['documentos']['PDF'];
            $files = array(
                    "name" => $UUID.'.PDF',
                    "type" => "application/pdf",
                    "error" => 0,
                    "size" => strlen(base64_decode($PDF)),
                    "original_name" => $UUID.'.PDF');
                    uploadAndSaveFile($entity_id,"Documents",$files,"PDF",$PDF);
            $files = array(
                    "name" => $UUID.'.XML',
                    "type" => "application/xml",
                    "error" => 0,
                    "size" => strlen(base64_decode($PDF)),
                    "original_name" => $UUID.'.XML');
                    uploadAndSaveFile($entity_id,"Documents",$files,"XML",$XML);
        }
        else {
            print_R($response);
        }

    }
}
function uploadAndSaveFile($id,$module,$file_details,$description,$filebase64) {
    global $log, $adb;

    $log->debug("Entering into uploadAndSaveFile($id,$module,$file_details) method.");

    global $current_user;
    global $upload_badext;

    $date_var = date('Y-m-d H:i:s');

    //to get the owner id
    $ownerid = $current_user->id;
    $save_file = 'true';

    $file = $file_details['name'];

    $binFile = sanitizeUploadFileName($file, $upload_badext);

    $filename = ltrim(basename(" ".$binFile)); //allowed filename like UTF-8 characters
    $filetype= $file_details['type'];
    $filesize = $file_details['size'];

    $current_id = $adb->getUniqueID("vtiger_crmentity");

    //get the file path inwhich folder we want to upload the file
    $upload_file_path = decideFilePath();
    //upload the file in server
    file_put_contents($upload_file_path.$current_id."_".$binFile, base64_decode($filebase64));


    if($save_file == 'true') {

        $sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,createdtime,modifiedtime) values(?,?,?,?,?,?,?)";
        $params1 = array($current_id, $current_user->id, $ownerid, $module, $description, $adb->formatString("vtiger_crmentity","createdtime",$date_var), $adb->formatDate($date_var, true));
        $adb->pquery($sql1, $params1);

        $query = "INSERT INTO vtiger_notes (notesid, title, filename,folderid,filetype,filelocationtype,filedownloadcount,filestatus,filesize,notecontent) values(?,?,?,?,?,?,?,?,?,?)";
                $re=$adb->pquery($query,array($current_id,$filename,$filesize,$upload_file_path.$current_id."_".$binFile,1,$filetype,'',0,1,$filesize,$upload_file_path.$current_id."_".$binFile));

        $query = "INSERT INTO vtiger_senotesrel (crmid, notesid) values(?,?)";
                $re=$adb->pquery($query,array($id,$current_id));
    }
    else {
        $log->debug("Skip the save attachment process.");
    }
    $log->debug("Exiting from uploadAndSaveFile($id,$module,$file_details) method.");
    return;
}

?>

Paso 3:

Ingresar a Valores de lista de selección en la Configuración de vTiger para crear el Estatus de Invoice CFDI que disparará la factura.

Integración de vTiger con el Timbrado de CFDI

3.1 – Creación del Estatus CFDI

Integración de vTiger con el Timbrado de CFDI

Paso 4:

Registrar el Procedimiento custom de flujo de trabajo en la base de datos.

Código:

INSERT INTO `com_vtiger_workflowtasks_entitymethod` (`workflowtasks_entitymethod_id`, `module_name`, `method_name`, `function_path`, `function_name`)
VALUES
	(11, 'Invoice', 'InvoiceCFDI', 'include/InvoiceHandler.php', 'handleInvoice');

Incrementar la secuencia:

UPDATE com_vtiger_workflowtasks_entitymethod_seq SET id = id + 1 

Paso 5:

Para la creación del flujo de trabajo, se debe ingresar en la sección de flujo de trabajo y crear uno nuevo para Invoice o Facturas.

Integración de vTiger con el Timbrado de CFDI

Integración de vTiger con el Timbrado de CFDI

Integración de vTiger con el Timbrado de CFDI

Integración de vTiger con el Timbrado de CFDI

Finalmente, la factura aparecerá como parte de los documentos visibles del Invoice.

Integración de vTiger con el Timbrado de CFDI

Open chat
Envíanos un Whatsapp