· 5 years ago · Mar 05, 2020, 09:54 PM
1<?php
2
3if ( ! defined( '_PS_VERSION_' ) ) {
4 exit;
5}
6
7require_once dirname( __FILE__ ) . '/classes/Customer.php';
8require_once dirname( __FILE__ ) . '/classes/Invoice.php';
9require_once dirname( __FILE__ ) . '/classes/NubeFact.php';
10
11class Vex_Nubefact extends Module {
12 protected $checkoutProcess;
13
14 // config
15 const CONFIG_LIVEMODE = 'VEX_NUBEFACT_LIVEMODE';
16 const CONFIG_LICENSE = 'VEX_NUBEFACT_LICENSE';
17 const CONFIG_TEST_URL = 'VEX_NUBEFACT_TEST_URL';
18 const CONFIG_TEST_TOKEN = 'VEX_NUBEFACT_TEST_TOKEN';
19 const CONFIG_LIVE_URL = 'VEX_NUBEFACT_LIVE_URL';
20 const CONFIG_LIVE_TOKEN = 'VEX_NUBEFACT_LIVE_TOKEN';
21 const CONFIG_BUSINESS_RUC = 'VEX_NUBEFACT_BUSINESS_RUC';
22 const CONFIG_BUSINESS_NAME = 'VEX_NUBEFACT_BUSINESS_NAME';
23 const CONFIG_BUSINESS_ADDRESS = 'VEX_NUBEFACT_BUSINESS_ADDRESS';
24 const CONFIG_RECEIPT_SERIE = 'VEX_NUBEFACT_RECEIPT_SERIE';
25 const CONFIG_RECEIPT_NUM = 'VEX_NUBEFACT_RECEIPT_NUM';
26 const CONFIG_INVOICE_SERIE = 'VEX_NUBEFACT_INVOICE_SERIE';
27 const CONFIG_INVOICE_NUM = 'VEX_NUBEFACT_INVOICE_NUM';
28 const CONFIG_INVOICE_STATE = 'VEX_NUBEFACT_INVOICE_STATE';
29 const CONFIG_INVOICE_SUNAT_CODE = 'VEX_NUBEFACT_INVOICE_SUNAT_CODE';
30 const CONFIG_API_APPNAME = 'VEX_API_APPNAME';
31 const CONFIG_API_FE_BILLING_NAME = 'VEX_API_FE_BILLING_NAME';
32 const CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE = 'VEX_FE_TOKEN_AUTO_INCREMENT_INVOICE';
33 const CONFIG_FE_URL_AUTO_INCREMENT_INVOICE = 'VEX_FE_URL_AUTO_INCREMENT_INVOICE';
34
35 const TIPOCOMPROBANTE_FACTURA = 1;
36 const TIPODOCUMENTO_RUC = 6;
37
38 public function __construct(){
39 $this->name = 'vex_nubefact';
40 // $this->tab = 'administration';
41 $this->tab = 'billing_invoicing';
42 $this->version = '1.1.0';
43 $this->ps_versions_compliancy = array('min' => '1.7', 'max' => _PS_VERSION_);
44 $this->author = 'Vex Soluciones - Modified by Alekuoshu';
45 // $this->controllers = array('validation', 'payment', 'transaction', 'error');
46 $this->bootstrap = true;
47
48 parent::__construct();
49
50 $this->displayName = 'NubeFact';
51 $this->description = $this->l('Electronic invoicing management module for Peru');
52 $this->confirmUninstall = $this->l('Are you sure about removing NubeFact?');
53 }
54
55 public function install(){
56 return ( parent::install()
57 && $this->createTabs()
58 && $this->registerHook( 'header' )
59 && $this->registerHook( 'displayPaymentTop' )
60 // && $this->registerHook( 'displayCustomerAccount' )
61 && $this->registerHook( 'termsAndConditions' )
62 && $this->registerHook( 'backOfficeHeader' )
63 && $this->registerHook( 'actionOrderStatusPostUpdate' )
64 && $this->registerHook( 'displayOrderDetail' )
65 // && $this->registerHook( 'moduleRoutes' )
66 && $this->installDb() );
67 }
68
69 public function uninstall(){
70 return (
71 parent::uninstall()
72 );
73 }
74
75 public function installDb(){
76 return (
77 Db::getInstance()->Execute( 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'vex_nubefact_customer` (
78 `id` int(11) NOT NULL AUTO_INCREMENT,
79 `customer_id` int(11) NOT NULL,
80 `cart_id` int(11) NOT NULL,
81 `tipo_de_comprobante` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
82 `cliente_tipo_de_documento` varchar(6) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
83 `cliente_numero_de_documento` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
84 `cliente_denominacion` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
85 `cliente_direccion` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
86 `date_add` DATETIME NOT NULL,
87 PRIMARY KEY (`id`)
88 ) ENGINE='._MYSQL_ENGINE_.' AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;' )
89
90 && Db::getInstance()->Execute( 'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'vex_nubefact_invoice` (
91 `comprobante_id` int(11) NOT NULL AUTO_INCREMENT,
92 `id_customer` int(11) NOT NULL,
93 `id_order` int(11) NOT NULL,
94 `url_pdf` text COLLATE utf8mb4_unicode_ci,
95 `tipo_de_comprobante` char(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
96 `serie` char(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
97 `numero` int(11) DEFAULT NULL,
98 `cliente_tipo_de_documento` varchar(6) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
99 `cliente_numero_de_documento` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
100 `cliente_denominacion` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
101 `cliente_direccion` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
102 `cliente_email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
103 `fecha_de_emision` date DEFAULT NULL,
104 `porcentaje_de_igv` double DEFAULT NULL,
105 `descuento_global` double DEFAULT NULL,
106 `total_descuento` double DEFAULT NULL,
107 `total_gravada` double DEFAULT NULL,
108 `total_igv` double DEFAULT NULL,
109 `total_gratuita` double DEFAULT NULL,
110 `total` double DEFAULT NULL,
111 `wp_data` text COLLATE utf8mb4_unicode_ci,
112 `sunat_estado` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT "",
113 `sunat_respuesta_envio` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
114 `sunat_fecha_envio` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
115 `sys_estado` smallint(6) DEFAULT "1",
116 `date_add` DATETIME NOT NULL,
117 PRIMARY KEY (`comprobante_id`,`sunat_estado`)
118 ) ENGINE='._MYSQL_ENGINE_.' AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;' )
119 );
120 }
121
122 private function createTabs(){
123 $tab = new Tab();
124 $tab->active = 1;
125 $tab->class_name = "AdminNubeFact";
126 $tab->id_parent = Tab::getIdFromClassName('AdminParentOrders');
127 $tab->module = $this->name;
128 $tab->name = array();
129
130 foreach (Language::getLanguages() as $lang){
131 $tab->name[$lang['id_lang']] = "NubeFact";
132 }
133
134 return $tab->add();
135 }
136
137 private function canBeUsed( $params ){
138 if ( ! $this->active ) {
139 return false;
140 }
141
142 return true;
143 }
144
145 /**
146 * Add the CSS & JavaScript files in the module's backoffice.
147 *
148 * @return void
149 */
150 public function hookBackOfficeHeader( $params ){
151 if ( ! $this->canBeUsed( $params ) ) {
152 return false;
153 }
154
155 if (Tools::getValue('configure') == $this->name) {
156 $this->context->controller->addCSS($this->_path . 'views/css/backend.css');
157 // if (version_compare(_PS_VERSION_, '1.6', '<') == true) {
158 // $this->context->controller->addCSS($this->_path.'views/css/bootstrap.min.css');
159 // $this->context->controller->addCSS($this->_path.'views/css/configure-ps-15.css');
160 // } else {
161 // $this->context->controller->addCSS($this->_path.'views/css/configure-ps-16.css');
162 // }
163 }
164 }
165
166
167 /**
168 * Add the CSS & JavaScript files on the frontoffice.
169 *
170 * @return void
171 */
172 public function hookHeader( $params ){
173 if ( ! $this->canBeUsed( $params ) ) {
174 return false;
175 }
176
177 // print_r( [$params, $this->context]);
178 $this->context->controller->addJS($this->_path . '/views/js/front.js');
179 // $this->context->controller->addCSS($this->_path.'/views/css/front.css');
180 }
181
182 public function hookDisplayPaymentTop( $params ){
183 if ( ! $this->canBeUsed( $params ) ) {
184 return false;
185 }
186
187 // load saved values
188 $values = array();
189 if( $nubeFactCustomer = Vex_Nubefact_Customer::getByCustomerId( $this->context->customer->id ) ) {
190 $values = $nubeFactCustomer;
191 unset( $values['date_add'], $values['cart_id'], $values['customer_id'], $values['id'] );
192 }
193
194 $data = array(
195 'tiposDeComprobantes' => array(
196 '1' => 'Factura',
197 '2' => 'Boleta'
198 ),
199 'tiposDeDocumentosCliente' => array(
200 '1' => 'DNI',
201 '4' => 'Carnet de extranjeria',
202 '7' => 'Pasaporte'
203 ),
204 'tipo_de_comprobante' => '',
205 'cliente_tipo_de_documento' => '',
206 'cliente_numero_de_documento' => '',
207 'cliente_denominacion' => '',
208 'cliente_direccion' => ''
209 );
210
211 $data = array_merge( $data, $values );
212 $this->context->smarty->assign( $data );
213
214 return $this->display(__FILE__, 'vex_facturacion.tpl');
215 }
216
217 /*
218 Hook que se acciona al pasar estado depende del valor de la variable CONFIG_INVOICE_STATE
219 */
220 public function hookActionOrderStatusPostUpdate( $params ){
221 if ( ! $this->canBeUsed( $params ) ) {
222 return false;
223 }
224
225 $stateID = trim(Configuration::get( self::CONFIG_INVOICE_STATE ));
226
227 // value if state changed is equal to (CONFIG_INVOICE_STATE)
228 if($params['newOrderStatus']->id == $stateID) {
229
230 $order = new Order($params['id_order'] );
231 $customer_id = $order->id_customer;
232 $id_cart = $order->id_cart;
233
234 // evalua si es gratuita o no
235 if($order->total_paid_tax_incl == 0){
236 $incluido_impuestos = 0; // total incluido impuesto
237 $sin_impuestos = 0; // total sin impuesto
238 }else{
239 $incluido_impuestos = $order->total_paid_tax_incl; // total incluido impuesto
240 $sin_impuestos = $order->total_paid_tax_excl; // total sin impuesto
241 }
242
243 $impuestos = $incluido_impuestos - $sin_impuestos;
244 $totalGratis = 0;
245 $sumaDescuentoItems = 0;
246 // load saved values
247 // $nubeFactValues = array();
248 if( $nubeFactCustomer = Vex_Nubefact_Customer::getByCustomerId( $customer_id ) ) {
249 // $nubeFactValues = $nubeFactCustomer;
250 // unset( $nubeFactValues['date_add'], $nubeFactValues['cart_id'] );
251 // unset( $nubeFactValues['customer_id'], $nubeFactValues['id'] );
252 $customer = new Customer($customer_id);
253
254 $url = $this->get_url();
255 $token = $this->get_token();
256
257 $nubeFact = new Vex_PrestaShop_NubeFact( $url, $token );
258
259 if( $nubeFactCustomer['tipo_de_comprobante'] == self::TIPOCOMPROBANTE_FACTURA ){
260 require_once dirname( __FILE__ ) . '/classes/NubeFact/FacturaElectronica.php';
261 $document = new Vex_FacturaElectronica();
262
263 $serie = 'F' . Configuration::get( self::CONFIG_INVOICE_SERIE );
264 // $numero = Configuration::get( self::CONFIG_INVOICE_NUM );
265
266 // consulta consecutivo en api
267 $AutoIncrementInvoice = new stdClass();
268 $AutoIncrementInvoice->aplicationName = Configuration::get(self::CONFIG_API_APPNAME);
269 $AutoIncrementInvoice->billingName = Configuration::get(self::CONFIG_API_FE_BILLING_NAME);
270 $AutoIncrementInvoice->idCart = $id_cart;
271 $AutoIncrementInvoice->idOrder = $params['id_order'];
272 $AutoIncrementInvoice->token = Configuration::get(self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE);
273 $AutoIncrementInvoice->suffix = 'pefactura';
274 $AutoIncrementInvoice->production = true;
275
276 $data_string = json_encode($AutoIncrementInvoice);
277
278 $ch = curl_init(Configuration::get(self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE));
279 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
280 curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
281 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
282 curl_setopt($ch, CURLOPT_HTTPHEADER, array(
283 'Content-Type: application/json',
284 'Content-Length: ' . strlen($data_string)
285 ));
286
287 $response = curl_exec($ch);
288
289 $responseArray = json_decode($response, true);
290 $numero = $responseArray['invoiceNumber'];
291
292 } else {
293 require_once dirname( __FILE__ ) . '/classes/NubeFact/BoletaElectronica.php';
294 $document = new Vex_BoletaElectronica();
295
296 $serie = 'B' . Configuration::get( self::CONFIG_RECEIPT_SERIE );
297 // $numero = Configuration::get( self::CONFIG_RECEIPT_NUM );
298
299 // consulta consecutivo en api
300 $AutoIncrementInvoice = new stdClass();
301 $AutoIncrementInvoice->aplicationName = Configuration::get(self::CONFIG_API_APPNAME);
302 $AutoIncrementInvoice->billingName = Configuration::get(self::CONFIG_API_FE_BILLING_NAME);
303 $AutoIncrementInvoice->idCart = $id_cart;
304 $AutoIncrementInvoice->idOrder = $params['id_order'];
305 $AutoIncrementInvoice->token = Configuration::get(self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE);
306 $AutoIncrementInvoice->suffix = 'peboleta';
307 $AutoIncrementInvoice->production = true;
308
309 $data_string = json_encode($AutoIncrementInvoice);
310
311 $ch = curl_init(Configuration::get(self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE));
312 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
313 curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
314 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
315 curl_setopt($ch, CURLOPT_HTTPHEADER, array(
316 'Content-Type: application/json',
317 'Content-Length: ' . strlen($data_string)
318 ));
319
320 $response = curl_exec($ch);
321
322 $responseArray = json_decode($response, true);
323 $numero = $responseArray['invoiceNumber'];
324 }
325
326 $document->setSunatEnvioAutomatico( true );
327 $document->setSerie( $serie );
328 $document->setNumero( $numero );
329
330 $document->setCliente( array(
331 'cliente_tipo_de_documento' => $nubeFactCustomer['cliente_tipo_de_documento'],
332 'cliente_numero_de_documento' => $nubeFactCustomer['cliente_numero_de_documento'],
333 'cliente_denominacion' => $nubeFactCustomer['cliente_denominacion'],
334 'cliente_direccion' => $nubeFactCustomer['cliente_direccion']
335 ) );
336
337 $document->addClienteEmail( $customer->email );
338
339 // $currency = new Currency($order->id_currency);
340 // $currencies = array(
341 // 'PEN' => Vex_DocumentContract::$SOL,
342 // 'USD' => Vex_DocumentContract::$DOLAR,
343 // 'EUR' => Vex_DocumentContract::$EURO,
344 // );
345
346 // var_export( [$currency, $nubeFactCustomer] );
347
348
349 // $document->setMoneda( $currencies[ $currency->iso_code ] );
350
351 // $document->setTipoCambio();
352 $document->setPorcentajeIGV( $impuestos );
353 $document->setTotal( $incluido_impuestos );
354 $document->setTotalIGV( round( $incluido_impuestos - $sin_impuestos, 2 ) );
355 $document->setTotalGravada( $sin_impuestos );
356 // $document->setTotalInafecta();
357 // $document->setDetraccion();
358 // $document->setObservaciones();
359
360 $features = $this->getFeaturesProductOrder($order->id);
361
362 foreach ( $order->getProducts() as $productDetail ) {
363 $TotalConImpuesto = $productDetail['total_price_tax_incl'];
364 $TotalSinImpuesto = $productDetail['total_price_tax_excl'];
365 $discounts = $productDetail['reduction_percent'];
366 $valorUnitario = $productDetail['original_product_price'];
367 $impuestoUnitario = ($valorUnitario * (int) $this->get_percent_igv()) / 100;
368 $precioUnitario = round($valorUnitario + $impuestoUnitario, 2);
369 $tipoIGV = '1';
370 $IGV = $TotalConImpuesto - $TotalSinImpuesto;
371 $total = $TotalConImpuesto;
372
373 // descuento por producto
374 if($discounts > 0) {
375 $descuento = ($valorUnitario * $discounts / 100);
376 $sumaDescuentoItems += $descuento;
377 }else {
378 $descuento = 0;
379 $sumaDescuentoItems = 0;
380 }
381
382 $subtotal = ($valorUnitario * $productDetail['product_quantity']) - $descuento;
383
384 if(!empty($features[$productDetail['product_id']]['value']))
385 $codigo_producto_sunat = $features[$productDetail['product_id']]['value'];
386 else
387 $codigo_producto_sunat = Configuration::get( self::CONFIG_INVOICE_SUNAT_CODE );
388
389 // evalua si es gratuito o no
390 if($order->total_paid_tax_incl == 0){
391 $totalGratis += $subtotal;
392 $precioUnitario = $valorUnitario;
393 $subtotal = ($valorUnitario * $productDetail['product_quantity']);
394 $tipoIGV = '6';
395 $IGV = 0;
396 $total = $valorUnitario;
397 }
398
399 $document->addItem( array(
400 'unidad_de_medida' => 'NIU',
401 'codigo' => $productDetail['product_id'],
402 'descripcion' => $productDetail['product_name'],
403 'cantidad' => $productDetail['product_quantity'],
404 'valor_unitario' => $valorUnitario, // unitario sin impuesto
405 'precio_unitario' => $precioUnitario, // unitario con impuesto
406 'descuento' => $descuento,
407 'subtotal' => $subtotal,
408 'tipo_de_igv' => $tipoIGV,
409 'igv' => $IGV,
410 'total' => $total,
411 'anticipo_regularizacion' => 'false',
412 'anticipo_documento_serie' => '',
413 'anticipo_documento_numero' => '',
414 'codigo_producto_sunat' => $codigo_producto_sunat //Fórmulas y productos para apoyo nutritivo
415 ) );
416 }
417
418 // transporte
419 $shipping_sin_impuestos = $order->total_shipping_tax_excl; // total transporte sin impuesto
420 $shipping_con_impuestos = $order->total_shipping_tax_incl; // total transporte sin impuesto
421 $precioUnitario = round($shipping_con_impuestos, 2);
422 $tipoIGV = '1';
423 $IGV = $shipping_con_impuestos - $shipping_sin_impuestos;
424 $total = $shipping_con_impuestos;
425 if ($shipping_sin_impuestos > 0) {
426 // evalua si es gratuito o no
427 if($order->total_paid_tax_incl == 0){
428 $precioUnitario = $shipping_sin_impuestos;
429 $tipoIGV = '6';
430 $IGV = 0;
431 $total = $shipping_sin_impuestos;
432 }
433
434 $document->addItem( array(
435 'unidad_de_medida' => 'ZZ',
436 'codigo' => '001',
437 'descripcion' => 'Costo de envío',
438 'cantidad' => '1',
439 'valor_unitario' => $shipping_sin_impuestos, // unitario sin impuesto
440 'precio_unitario' => $precioUnitario, // unitario con impuesto
441 'descuento' => '',
442 'subtotal' => $shipping_sin_impuestos,
443 'tipo_de_igv' => $tipoIGV,
444 'igv' => $IGV,
445 'total' => $total,
446 'anticipo_regularizacion' => 'false',
447 'anticipo_documento_serie' => '',
448 'anticipo_documento_numero' => '',
449 'codigo_producto_sunat' => '78140000' //Servicios de transporte
450 ) );
451 }
452
453 // $document->setCodigoUnico();
454
455 // var_export( $document->getArray() );
456
457 // descuento general
458 $total_descuentos = 0;
459 $descuento_general = 0;
460 if($order->total_discounts > 0){
461 $descuento_general = $order->total_discounts; // total descuento orden
462 }
463 $total_descuentos = $descuento_general + $sumaDescuentoItems;
464 $document->setDescuentoGlobal( $descuento_general );
465 $document->setTotalDescuento( $total_descuentos );
466
467 // si es gratuita o no
468 if($order->total_paid_tax_incl == 0){
469 $document->setTotalGratis( $totalGratis );
470 }
471
472 //create invoice
473 $invoice = new Vex_Nubefact_Invoice();
474
475 $invoice->id_customer = $customer->id;
476 $invoice->id_order = $order->id;
477 $invoice->tipo_de_comprobante = $nubeFactCustomer['tipo_de_comprobante'];
478 $invoice->serie = $serie;
479 $invoice->numero = (int) $numero;
480 $invoice->cliente_tipo_de_documento = $nubeFactCustomer['cliente_tipo_de_documento'];
481 $invoice->cliente_numero_de_documento = $nubeFactCustomer['cliente_numero_de_documento'];
482 $invoice->cliente_denominacion = $nubeFactCustomer['cliente_denominacion'];
483 $invoice->cliente_direccion = $nubeFactCustomer['cliente_direccion'];
484 $invoice->cliente_email = $customer->email;
485 $invoice->fecha_de_emision = date( 'Y-m-d' );
486 $invoice->moneda = 1;
487 $invoice->porcentaje_de_igv = $this->get_percent_igv();
488 $invoice->descuento_global = $descuento_general;
489 $invoice->total_descuento = $total_descuentos;
490 $invoice->total_gravada = $sin_impuestos;
491 $invoice->total_igv = round( $incluido_impuestos - $sin_impuestos, 2 );
492 $invoice->total_gratuita = $totalGratis;
493 $invoice->total = $incluido_impuestos;
494
495
496 // validar que no existe ya la factura en nubefact y no este aceptada a la sunat
497 $query = new DbQuery();
498 $query->select('*');
499 $query->from('vex_nubefact_invoice');
500 $query->where('id_order = "'.$order->id.'" AND sunat_estado = 1');
501 $valueR = Db::getInstance()->executeS($query);
502
503 // si no existe en el registro la factura se envia a nubefact
504 if(empty($valueR)){
505 if( $response = $nubeFact->sendDocument( $document ) ){
506 // incrementar numero
507 // if( $nubeFactCustomer['tipo_de_comprobante'] == self::TIPOCOMPROBANTE_FACTURA ){
508 // Configuration::updateValue( self::CONFIG_INVOICE_NUM, $numero+1 );
509 // } else {
510 // Configuration::updateValue( self::CONFIG_RECEIPT_NUM, $numero+1 );
511 // }
512
513 $data = @json_decode( $response );
514
515 // guardar pdf url
516 $invoice->url_pdf = $data->enlace_del_pdf;
517 // respuesta sunat
518 $sunat = $data->aceptada_por_sunat;
519 if($sunat === true){
520 $invoice->sunat_estado = '1';
521 $invoice->sunat_respuesta_envio = $data->sunat_description;
522 }else{
523 $invoice->sunat_estado = '0';
524 $invoice->sunat_respuesta_envio = 'error';
525 }
526 } else {
527 // var_export( [ $nubeFact->getClient(), $document->getArray() ] );
528 // exit();
529 }
530
531 $invoice->wp_data = $nubeFact->getClient()->response;
532 $invoice->add();
533 }
534
535 }
536 // $customer = new Customer($customer_id);
537
538 // $clientParams = array(
539 // 'cliente_email' => $customer->email,
540 // 'cliente_tipo_de_documento' => '',
541 // 'cliente_numero_de_documento' => '',
542 // 'cliente_denominacion' => '',
543 // 'cliente_direccion' => ''
544 // );
545
546 // $clientParams = array_merge( $clientParams, $nubeFactValues );
547
548 // var_export( [$params['id_order'], $order->id] );
549 // exit();
550
551 }//fin cambio de estado
552
553 }
554
555 // public function hookDisplayCustomerAccount(){
556 // $data = array();
557 // $this->context->smarty->assign( $data );
558
559 // return $this->display(__FILE__, 'customer-account.tpl');
560 // }
561
562 public function hookDisplayOrderDetail( $params ){
563 if( $invoice = Vex_Nubefact_Invoice::getByOrderId( $params['order']->id ) ){
564 $url_pdf = '';
565
566 if( empty( $invoice['url_pdf'] ) ){
567 $data = @json_decode( $invoice['wp_data'] );
568
569 if( isset( $data->enlace_del_pdf ) ){
570 $url_pdf = $data->enlace_del_pdf;
571 }
572 } else {
573 $url_pdf = $invoice['url_pdf'];
574 }
575
576 $this->context->smarty->assign( array(
577 'serie' => $invoice['serie'],
578 'numero' => str_pad( $invoice['numero'], 4, '0', STR_PAD_LEFT ),
579 'url_pdf' => $url_pdf
580 ) );
581
582 return $this->display(__FILE__, 'order-detail.tpl');
583 }
584 }
585
586 public function getContent(){
587 if( Tools::isSubmit( 'submit' . $this->name ) ){
588 $this->postProcess();
589 }
590
591 return $this->displayForm();
592 }
593
594 protected function postProcess(){
595 $test_url = Configuration::get( self::CONFIG_TEST_URL, null, null, null, '' );
596 $test_token = Configuration::get( self::CONFIG_TEST_TOKEN, null, null, null, '' );
597
598 $live_url = Configuration::get( self::CONFIG_LIVE_URL, null, null, null, '' );
599 $live_token = Configuration::get( self::CONFIG_LIVE_TOKEN, null, null, null, '' );
600
601 // save credentials
602 if( Tools::getValue( self::CONFIG_LIVEMODE ) == 0 ){
603 if( ! Tools::getValue( self::CONFIG_TEST_URL ) ){
604 $this->context->controller->errors[] = $this->l('TEST URL required!');
605 } else {
606 $test_url = Tools::getValue( self::CONFIG_TEST_URL, '' );
607 }
608
609 if( ! Tools::getValue( self::CONFIG_TEST_TOKEN ) ){
610 $this->context->controller->errors[] = $this->l('TEST Token required!');
611 } else {
612 $test_token = Tools::getValue( self::CONFIG_TEST_TOKEN, '' );
613 }
614 } else {
615 if( ! Tools::getValue( self::CONFIG_LIVE_URL ) ){
616 $this->context->controller->errors[] = $this->l('LIVE URL required!');
617 } else {
618 $live_url = Tools::getValue( self::CONFIG_LIVE_URL, '' );
619 }
620
621 if( ! Tools::getValue( self::CONFIG_LIVE_TOKEN ) ){
622 $this->context->controller->errors[] = $this->l('LIVE Token required!');
623 } else {
624 $live_token = Tools::getValue( self::CONFIG_LIVE_TOKEN, '' );
625 }
626 }
627
628 // validate business ruc
629 if( ! Tools::getValue( self::CONFIG_BUSINESS_RUC ) ){
630 $this->context->controller->errors[] = $this->l('Business ruc required!');
631 }
632
633 // validate business name
634 if( ! Tools::getValue( self::CONFIG_BUSINESS_NAME ) ){
635 $this->context->controller->errors[] = $this->l('Business name required!');
636 }
637
638 // validate business address
639 if( ! Tools::getValue( self::CONFIG_BUSINESS_ADDRESS ) ){
640 $this->context->controller->errors[] = $this->l('Business address required!');
641 }
642
643 // validate receipt serie
644 if( ! Tools::getValue( self::CONFIG_RECEIPT_SERIE ) ){
645 $this->context->controller->errors[] = $this->l('Receipt serie required!');
646 }
647
648 // validate receipt num
649 if( ! Tools::getValue( self::CONFIG_RECEIPT_NUM ) ){
650 $this->context->controller->errors[] = $this->l('Receipt number required!');
651 }
652
653 // validate invoice serie
654 if( ! Tools::getValue( self::CONFIG_INVOICE_SERIE ) ){
655 $this->context->controller->errors[] = $this->l('Invoice serie required!');
656 }
657
658 // validate invoice num
659 if( ! Tools::getValue( self::CONFIG_INVOICE_NUM ) ){
660 $this->context->controller->errors[] = $this->l('Invoice number required!');
661 }
662
663 // validate invoice state
664 if( ! Tools::getValue( self::CONFIG_INVOICE_STATE ) ){
665 $this->context->controller->errors[] = $this->l('State number required!');
666 }
667
668 // validate api name
669 if( ! Tools::getValue( self::CONFIG_API_APPNAME ) ){
670 $this->context->controller->errors[] = $this->l('Api name required!');
671 }
672
673 // validate billing name
674 if( ! Tools::getValue( self::CONFIG_API_FE_BILLING_NAME ) ){
675 $this->context->controller->errors[] = $this->l('Billing name required!');
676 }
677
678 // validate token
679 if( ! Tools::getValue( self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE ) ){
680 $this->context->controller->errors[] = $this->l('Token required!');
681 }
682
683 // validate api url
684 if( ! Tools::getValue( self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE ) ){
685 $this->context->controller->errors[] = $this->l('URL required!');
686 }
687
688
689
690 // save other fields
691 Configuration::updateValue( self::CONFIG_LIVEMODE, ( int ) Tools::getValue( self::CONFIG_LIVEMODE ) );
692 Configuration::updateValue( self::CONFIG_TEST_URL, $test_url );
693 Configuration::updateValue( self::CONFIG_TEST_TOKEN, $test_token );
694
695 Configuration::updateValue( self::CONFIG_LIVE_URL, $live_url );
696 Configuration::updateValue( self::CONFIG_LIVE_TOKEN, $live_token );
697 Configuration::updateValue( self::CONFIG_BUSINESS_RUC, Tools::getValue( self::CONFIG_BUSINESS_RUC ) );
698 Configuration::updateValue( self::CONFIG_BUSINESS_NAME, Tools::getValue( self::CONFIG_BUSINESS_NAME ) );
699 Configuration::updateValue( self::CONFIG_BUSINESS_ADDRESS, Tools::getValue( self::CONFIG_BUSINESS_ADDRESS ) );
700 Configuration::updateValue( self::CONFIG_RECEIPT_SERIE, Tools::getValue( self::CONFIG_RECEIPT_SERIE ) );
701 Configuration::updateValue( self::CONFIG_RECEIPT_NUM, Tools::getValue( self::CONFIG_RECEIPT_NUM ) );
702 Configuration::updateValue( self::CONFIG_INVOICE_SERIE, Tools::getValue( self::CONFIG_INVOICE_SERIE ) );
703 Configuration::updateValue( self::CONFIG_INVOICE_NUM, Tools::getValue( self::CONFIG_INVOICE_NUM ) );
704 Configuration::updateValue( self::CONFIG_INVOICE_STATE, Tools::getValue( self::CONFIG_INVOICE_STATE ) );
705 Configuration::updateValue( self::CONFIG_INVOICE_SUNAT_CODE, Tools::getValue( self::CONFIG_INVOICE_SUNAT_CODE ) );
706 Configuration::updateValue( self::CONFIG_API_APPNAME, Tools::getValue( self::CONFIG_API_APPNAME ) );
707 Configuration::updateValue( self::CONFIG_API_FE_BILLING_NAME, Tools::getValue( self::CONFIG_API_FE_BILLING_NAME ) );
708 Configuration::updateValue( self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE, Tools::getValue( self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE ) );
709 Configuration::updateValue( self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE, Tools::getValue( self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE ) );
710
711 if ( ! count( $this->context->controller->errors ) ) {
712 $this->context->controller->confirmations[] = $this->l('Settings saved successfully');
713 }
714 }
715
716 protected function displayForm(){
717 $default_lang = new Language( ( int ) Configuration::get( 'PS_LANG_DEFAULT' ) );
718
719 $helper = new HelperForm();
720 $helper->show_toolbar = true;
721 $helper->table = $this->table;
722 $helper->name_controller = $this->name;
723 $helper->default_form_language = $default_lang->id;
724 $helper->submit_action = 'submit' . $this->name;
725 $helper->currentIndex = $this->context->link->getAdminLink( 'AdminModules', false ) . '&configure=' . $this->name . '&tab_module=' . $this->tab . '&module_name=' . $this->name;
726 $helper->token = Tools::getAdminTokenLite( 'AdminModules' );
727
728 $helper->tpl_vars = array(
729 'fields_value' => $this->getConfigFieldsValues(),
730 'languages' => $this->context->controller->getLanguages(),
731 'id_language' => $this->context->language->id
732 );
733
734 $this->context->controller->addJS( $this->_path . 'views/js/backoffice.js' );
735
736 return $helper->generateForm( $this->getConfigForm() );
737 }
738
739 public function getConfigFieldsValues(){
740 return array(
741 self::CONFIG_LIVEMODE => Configuration::get( self::CONFIG_LIVEMODE ),
742 self::CONFIG_TEST_URL => Configuration::get( self::CONFIG_TEST_URL ),
743 self::CONFIG_TEST_TOKEN => Configuration::get( self::CONFIG_TEST_TOKEN ),
744 self::CONFIG_LIVE_URL => Configuration::get( self::CONFIG_LIVE_URL ),
745 self::CONFIG_LIVE_TOKEN => Configuration::get( self::CONFIG_LIVE_TOKEN ),
746 self::CONFIG_BUSINESS_RUC => Configuration::get( self::CONFIG_BUSINESS_RUC ),
747 self::CONFIG_BUSINESS_NAME => Configuration::get( self::CONFIG_BUSINESS_NAME ),
748 self::CONFIG_BUSINESS_ADDRESS => Configuration::get( self::CONFIG_BUSINESS_ADDRESS ),
749 self::CONFIG_INVOICE_STATE => Configuration::get( self::CONFIG_INVOICE_STATE ),
750 self::CONFIG_INVOICE_SUNAT_CODE => Configuration::get( self::CONFIG_INVOICE_SUNAT_CODE ),
751 self::CONFIG_API_APPNAME => Configuration::get( self::CONFIG_API_APPNAME ),
752 self::CONFIG_API_FE_BILLING_NAME => Configuration::get( self::CONFIG_API_FE_BILLING_NAME ),
753 self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE => Configuration::get( self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE ),
754 self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE => Configuration::get( self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE ),
755 );
756 }
757
758 protected function getConfigForm(){
759 $testmode_form = array(
760 'form' => array(
761 'legend' => array(
762 'title' => $this->l('Environment'),
763 'icon' => 'icon-wrench'
764 ),
765 'input' => array(
766 array(
767 'type' => 'switch',
768 'label' => $this->l('Live mode'),
769 'name' => self::CONFIG_LIVEMODE,
770 'is_bool' => true,
771 'desc' => $this->l('Choose between live or test mode'),
772 'values' => array(
773 array(
774 'id' => 'active_on',
775 'value' => 1,
776 'label' => $this->l('Live')
777 ),
778 array(
779 'id' => 'active_off',
780 'value' => 0,
781 'label' => $this->l('Test')
782 )
783 )
784 )
785 ),
786 'submit' => array(
787 'title' => $this->l('Save')
788 )
789 )
790 );
791
792 $credentials_form = array(
793 'form' => array(
794 'legend' => array(
795 'title' => $this->l('API credentials'),
796 'icon' => 'icon-user'
797 ),
798 'input' => array(
799 array(
800 'type' => 'text',
801 'label' => $this->l('TEST URL'),
802 'name' => self::CONFIG_TEST_URL,
803 'placeholder' => 'https://api.nubefact.com/api/v1/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
804 'class' => 'test-field',
805 'required' => true
806 ),
807 array(
808 'type' => 'text',
809 'label' => $this->l('TEST Token'),
810 'name' => self::CONFIG_TEST_TOKEN,
811 'placeholder' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
812 'class' => 'test-field',
813 'required' => true
814 ),
815 array(
816 'type' => 'text',
817 'label' => $this->l('LIVE URL'),
818 'name' => self::CONFIG_LIVE_URL,
819 'placeholder' => 'https://api.nubefact.com/api/v1/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
820 'class' => 'live-field',
821 'required' => true
822 ),
823 array(
824 'type' => 'text',
825 'label' => $this->l('LIVE Token'),
826 'name' => self::CONFIG_LIVE_TOKEN,
827 'placeholder' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
828 'class' => 'live-field',
829 'required' => true
830 )
831 ),
832 'submit' => array(
833 'title' => $this->l('Save')
834 )
835 )
836 );
837
838 $business_data_form = array(
839 'form' => array(
840 'legend' => array(
841 'title' => $this->l('Business data'),
842 'icon' => 'icon-wrench'
843 ),
844 'input' => array(
845 array(
846 'type' => 'text',
847 'label' => $this->l('RUC'),
848 'name' => self::CONFIG_BUSINESS_RUC,
849 'placeholder' => '20xxxxxxxxx',
850 'class' => 'fixed-width-xxl',
851 'required' => true
852 ),
853 array(
854 'type' => 'text',
855 'label' => $this->l('Business name'),
856 'name' => self::CONFIG_BUSINESS_NAME,
857 'placeholder' => 'My little shop',
858 'required' => true
859 ),
860 array(
861 'type' => 'text',
862 'label' => $this->l('Business address'),
863 'name' => self::CONFIG_BUSINESS_ADDRESS,
864 'placeholder' => 'Av. xxxxxx #9999',
865 'required' => true
866 ),
867 ),
868 'submit' => array(
869 'title' => $this->l('Save')
870 )
871 )
872 );
873
874 $general_parameters_form = array(
875 'form' => array(
876 'legend' => array(
877 'title' => $this->l('General parameters'),
878 'icon' => 'icon-wrench'
879 ),
880 'input' => array(
881 array(
882 'type' => 'html',
883 'html_content' => $this->billFields( array(
884 'prefix' => 'B',
885 'serie' => array(
886 'name' => self::CONFIG_RECEIPT_SERIE,
887 'value' => Configuration::get( self::CONFIG_RECEIPT_SERIE ),
888 'placeholder' => '001'
889 ),
890 'num' => array(
891 'name' => self::CONFIG_RECEIPT_NUM,
892 'value' => Configuration::get( self::CONFIG_RECEIPT_NUM ),
893 'placeholder' => '0001'
894 )
895 ) ),
896 'label' => $this->l('Receipt series'),
897 'name' => self::CONFIG_RECEIPT_SERIE,
898 'required' => true
899 ),
900 array(
901 'type' => 'html',
902 'html_content' => $this->billFields( array(
903 'prefix' => 'F',
904 'serie' => array(
905 'name' => self::CONFIG_INVOICE_SERIE,
906 'value' => Configuration::get( self::CONFIG_INVOICE_SERIE ),
907 'placeholder' => '001'
908 ),
909 'num' => array(
910 'name' => self::CONFIG_INVOICE_NUM,
911 'value' => Configuration::get( self::CONFIG_INVOICE_NUM ),
912 'placeholder' => '0001'
913 )
914 ) ),
915 'label' => $this->l('Invoice series'),
916 'name' => self::CONFIG_INVOICE_SERIE,
917 'required' => true
918 ),
919 array(
920 'type' => 'text',
921 'label' => $this->l('State Number'),
922 'name' => self::CONFIG_INVOICE_STATE,
923 'placeholder' => 'Set the state number id here',
924 'class' => 'fixed-width-xxl',
925 'required' => true
926 ),
927 array(
928 'type' => 'text',
929 'label' => $this->l('Sunat Product Code'),
930 'name' => self::CONFIG_INVOICE_SUNAT_CODE,
931 'placeholder' => 'Set the sunat product code here',
932 'class' => 'fixed-width-xxl',
933 'required' => true
934 ),
935 array(
936 'type' => 'text',
937 'label' => $this->l('API Name'),
938 'name' => self::CONFIG_API_APPNAME,
939 'placeholder' => 'Api name for invoice number consecutive',
940 'class' => 'fixed-width-xxl',
941 'required' => true
942 ),
943 array(
944 'type' => 'text',
945 'label' => $this->l('Billing Name'),
946 'name' => self::CONFIG_API_FE_BILLING_NAME,
947 'placeholder' => 'Ej: FARMALATAM',
948 'class' => 'fixed-width-xxl',
949 'required' => true
950 ),
951 array(
952 'type' => 'text',
953 'label' => $this->l('API Token'),
954 'name' => self::CONFIG_FE_TOKEN_AUTO_INCREMENT_INVOICE,
955 'placeholder' => '',
956 'class' => 'fixed-width-xxl',
957 'required' => true
958 ),
959 array(
960 'type' => 'text',
961 'label' => $this->l('URL API'),
962 'name' => self::CONFIG_FE_URL_AUTO_INCREMENT_INVOICE,
963 'placeholder' => '',
964 'class' => 'fixed-width-xxl',
965 'required' => true
966 ),
967
968
969 ),
970 'submit' => array(
971 'title' => $this->l('Save')
972 )
973 )
974 );
975
976 return array( $testmode_form, $credentials_form, $business_data_form, $general_parameters_form );
977 }
978
979 private function billFields( $params ){
980 $serie_value = isset($params['serie']['value']) ? $params['serie']['value'] : '';
981 $num_value = isset($params['num']['value']) ? $params['num']['value'] : '';
982
983 return <<<EOF
984<div class="form-inline">
985 <div class="form-group">
986 <div class="input-group">
987 <div class="input-group-addon">{$params['prefix']}</div>
988 <input type="text" class="form-control" name="{$params['serie']['name']}" id="{$params['serie']['name']}" value="{$serie_value}" placeholder="{$params['serie']['placeholder']}">
989 </div>
990 </div>
991 <div class="form-group hidden-xs"> - </div>
992 <div class="form-group">
993 <input type="text" class="form-control" name="{$params['num']['name']}" id="{$params['num']['name']}" value="{$num_value}" placeholder="{$params['num']['placeholder']}">
994 </div>
995</div>
996EOF;
997 }
998
999 // methods
1000 public function is_test_mode(){
1001 return '0' == Configuration::get( self::CONFIG_LIVEMODE, null, null, null, '0' );
1002 }
1003
1004 public function get_url(){
1005 if( $this->is_test_mode() ){
1006 return Configuration::get( self::CONFIG_TEST_URL, null, null, null, '' );
1007 } else {
1008 return Configuration::get( self::CONFIG_LIVE_URL, null, null, null, '' );
1009 }
1010 }
1011
1012 public function get_token(){
1013 if( $this->is_test_mode() ){
1014 return Configuration::get( self::CONFIG_TEST_TOKEN, null, null, null, '' );
1015 } else {
1016 return Configuration::get( self::CONFIG_LIVE_TOKEN, null, null, null, '' );
1017 }
1018 }
1019
1020 public function get_percent_igv(){
1021 return '18.00';
1022 // return Configuration::get( self::CONFIG_TEST_TOKEN, null, null, null, '' );
1023 }
1024
1025 private function getFeaturesProductOrder($id_otrder = 0)
1026 {
1027 $return = array();
1028 $query = new DbQuery();
1029 $query->select('psfp.id_product, psfl.name, psfv.value');
1030 $query->from('feature_product', 'psfp');
1031 $query->join('INNER JOIN`' . _DB_PREFIX_ . 'feature_lang` psfl ON psfl.`id_feature` = psfp.`id_feature` AND psfl.`name` = "codigo_producto_sunat"');
1032 $query->join('INNER JOIN`' . _DB_PREFIX_ . 'feature_value_lang` psfv ON psfv.`id_feature_value` = psfp.`id_feature_value`');
1033 $query->join('INNER JOIN`' . _DB_PREFIX_ . 'order_detail` psod ON psfp.`id_product` = psod.`product_id`');
1034 $query->where('psod.`id_order` = "' . (int) $id_otrder . '"');
1035 $query->groupBy('psfl.name');
1036
1037 if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query)) {
1038
1039 foreach ($result as $value) {
1040 $return[$value['id_product']] = $value;
1041 unset($return[$value['id_product']]['id_product']);
1042 }
1043 }
1044 return $return;
1045 }
1046}