ProdutoController::adicionar_cadastro()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 14
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
c 0
b 0
f 0
nc 1
nop 0
dl 14
loc 14
rs 9.4285
1
<?php
2
3
require_once(ROOT . DS . 'vendor' . DS . 'autoload.php');
4
5
use Dompdf\Dompdf;
6
7
class ProdutoController extends AppController{		
8
9
	public function listar_cadastros() {
10
		$this->layout = 'wadmin';
11
	}
12
13
	public function listar_cadastros_ajax() {
0 ignored issues
show
Coding Style introduced by
listar_cadastros_ajax uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
14
		$this->layout = 'ajax';
15
16
		$aColumns = array( 'sku', 'imagem', 'nome', 'preco', 'estoque' );
17
		
18
		$conditions = array('conditions' =>
19
			array(
20
				'ativo' => 1,
21
				'id_usuario' => $this->instancia
22
			)
23
		);
24
25
		$allProdutos = $this->Produto->find('all', $conditions);
26
		
27 View Code Duplication
		if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' )
28
		{
29
			$conditions['offset'] = $_GET['iDisplayStart'];
30
			$conditions['limit'] = $_GET['iDisplayLength'];
31
		}
32
33 View Code Duplication
		if ( isset( $_GET['iSortCol_0'] ) )
34
		{
35
			for ( $i=0 ; $i < intval( $_GET['iSortingCols'] ) ; $i++ )
36
			{
37
				if ( $_GET[ 'bSortable_' . intval($_GET['iSortCol_' . $i]) ] == "true" )
38
				{
39
					$conditions['order'] = array('Produto.' . $aColumns[intval($_GET['iSortCol_' . $i])] => $_GET['sSortDir_'.$i]);
40
				}
41
			}
42
		}
43
44 View Code Duplication
		if ( isset( $_GET['sSearch'] ) && !empty( $_GET['sSearch'] ) )
45
		{
46
			$conditions['conditions']['Produto.nome LIKE '] = '%' . $_GET['sSearch'] . '%';
47
		}
48
		
49
		$produtos = $this->Produto->find('all', $conditions);
50
51
		$output = array(
52
			"sEcho" => intval($_GET['sEcho']),
53
			"iTotalDisplayRecords" => count($allProdutos),
54
			"iTotalRecords" => count($produtos),
55
			"aaData" => array()
56
		);
57
58
		foreach ( $produtos as $i => $produto )
59
		{
60
			$row = array();
61
62
			for ( $i=0 ; $i < count($aColumns) ; $i++ )
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
63
			{
64
				$value = $produto['Produto'][$aColumns[$i]];
65
66
				if ($aColumns[$i] == "imagem")
67
				{
68
					$value = '<img src="/uploads/produto/imagens/' . $produto['Produto'][$aColumns[$i]] . '" width="120" height="120">';
69
70
					if (!isset($produto['Produto'][$aColumns[$i]]) || empty($produto['Produto'][$aColumns[$i]]))
71
					{
72
						$value = '<img src="/images/no_image.png" width="120" height="120">';
73
					}
74
				}
75
76
				if ($aColumns[$i] == "preco") 
77
				{
78
					$value = 'R$ ' . number_format($value, 2, ',', '.');
79
				}
80
				
81
				$row[] = $value;
82
			}
83
84
			$btEdit = '<a class="btn btn-info" href="/produto/editar_cadastro/' . $produto['Produto']['id'] . '"><i class="fa fa-pencil"></i></a>';
85
86
			$btMove = '<a class="btn btn-primary" href="/produto/movimentacoes_estoque/' . $produto['Produto']['id'] . '"><i class="fa fa-bars"></i></a>';
87
88
			$btImage = ' <a class="btn btn-primary" href="/produto/imagens/' . $produto['Produto']['id'] . '"><i class="fa fa-picture-o"></i></a>';
89
90
			$row[] = $btEdit . ' ' . $btMove . ' ' . $btImage;
91
92
			$output['aaData'][] = $row;
93
		}
94
		
95
		echo json_encode($output);
96
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method listar_cadastros_ajax() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
97
	}
98
99
	public function imagens($id) {
100
		$this->layout = 'wadmin';
101
102
		$produto = $this->Produto->find('first', array(
103
				'conditions' => array(
104
					'Produto.id' => $id
105
				)
106
			)
107
		);
108
109
		$this->loadModel('Imagen');
110
		$imagens = $this->Imagen->find('all', array(
111
				'conditions' => array(
112
					'Imagen.produto_id' => $id,
113
					'Imagen.usuario_id' => $this->instancia,
114
					'Imagen.ativo' => 1
115
				)
116
			)
117
		);
118
119
		$this->set('imagens', $imagens);
120
		$this->set('produto', $produto);
121
	}
122
123
	public function listar_cadastros_estoque_minimo(){
124
		$this->layout = 'wadmin';
125
	}
126
127
	public function listar_cadastros_estoque_minimo_ajax(){
0 ignored issues
show
Coding Style introduced by
listar_cadastros_estoque_minimo_ajax uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
128
129
		$this->layout = 'ajax';
130
131
		$aColumns = array( 'sku', 'imagem', 'nome', 'preco', 'estoque' );
132
133
		$this->loadModel('Usuario');
134
135
		$usuario = $this->Usuario->find('all', array('conditions' =>
136
				array(
137
					'Usuario.id' => $this->instancia
138
				)
139
			)
140
		)[0]['Usuario'];
141
		
142
		$conditions = array('conditions' =>
143
			array(
144
				'ativo' => 1,
145
				'id_usuario' => $this->instancia,
146
				'Produto.estoque < ' => 'Produto.quantidade_minima',
147
				//'OR' => array(
148
				//	'Produto.estoque <= ' => $usuario['estoque_minimo']
149
				//)
150
			)
151
		);
152
153
		$allProdutos = $this->Produto->query("select * from produtos where estoque < quantidade_minima and id_usuario = " . $this->instancia . " and ativo = 1");
154
155
		
156
		$sql = "select * from produtos as Produto where estoque < quantidade_minima and id_usuario = " . $this->instancia . " and ativo = 1";
157
158
		if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' )
159
		{
160
			$sql .= ' LIMIT ' . $_GET['iDisplayLength'] . ' OFFSET ' . $_GET['iDisplayStart'];
161
		}
162
163 View Code Duplication
		if ( isset( $_GET['iSortCol_0'] ) )
164
		{
165
			for ( $i=0 ; $i < intval( $_GET['iSortingCols'] ) ; $i++ )
166
			{
167
				if ( $_GET[ 'bSortable_' . intval($_GET['iSortCol_' . $i]) ] == "true" )
168
				{
169
					$conditions['order'] = array('Produto.' . $aColumns[intval($_GET['iSortCol_' . $i])] => $_GET['sSortDir_'.$i]);
170
				}
171
			}
172
		}
173
		
174 View Code Duplication
		if ( isset( $_GET['sSearch'] ) && !empty( $_GET['sSearch'] ) )
175
		{
176
			$conditions['conditions']['Produto.nome LIKE '] = '%' . $_GET['sSearch'] . '%';
177
		}
178
179
		$produtos = $this->Produto->query($sql);
180
181
		$output = array(
182
			"sEcho" => intval($_GET['sEcho']),
183
			"iTotalDisplayRecords" => count($allProdutos),
184
			"iTotalRecords" => count($produtos),
185
			"aaData" => array()
186
		);
187
188
		foreach ( $produtos as $i => $produto )
189
		{
190
			$row = array();
191
192
			for ( $i=0 ; $i < count($aColumns) ; $i++ )
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
193
			{
194
				$value = $produto['Produto'][$aColumns[$i]];
195
196
				if ($aColumns[$i] == "imagem")
197
				{
198
					$value = '<img src="/uploads/produto/imagens/' . $produto['Produto'][$aColumns[$i]] . '" width="120" height="120">';
199
200
					if (!isset($produto['Produto'][$aColumns[$i]]) || empty($produto['Produto'][$aColumns[$i]]))
201
					{
202
						$value = '<img src="/images/no_image.png" width="120" height="120">';
203
					}
204
				}
205
				
206
				$row[] = $value;
207
			}
208
209
			$output['aaData'][] = $row;
210
		}
211
		
212
		echo json_encode($output);
213
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method listar_cadastros_estoque_minimo_ajax() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
214
	}
215
216
	public function baixar_estoque_minimo_pdf() {
217
		$this->loadModel('Produto');
218
		$this->loadModel('Usuario');
219
220
		$dompdf = new Dompdf();
221
222
		$usuario = $this->Usuario->find('all', array('conditions' =>
223
				array(
224
					'Usuario.id' => $this->instancia
225
				)
226
			)
227
		)[0]['Usuario'];
228
229
		$conditions = array('conditions' =>
230
			array(
231
				'ativo' => 1,
232
				'id_usuario' => $this->instancia,
233
				'Produto.estoque < ' => 'Produto.quantidade_minima',
234
				//'OR' => array(
235
				//	'Produto.estoque <= ' => $usuario['estoque_minimo']
236
				//)
237
			)
238
		);
239
240
		$produtos = $this->Produto->query("select * from produtos as Produto where estoque < quantidade_minima and id_usuario = " . $this->instancia . " and ativo = 1");
241
		
242
		$html = $this->getProdutosEstoqueMinimoComoHtml($produtos);
243
244
		$dompdf->loadHtml($html);
245
246
		$dompdf->set_paper(array(0, 0, 595.28, count($produtos) * 25));
0 ignored issues
show
Deprecated Code introduced by
The method Dompdf\Dompdf::set_paper() has been deprecated.

This method has been deprecated.

Loading history...
247
248
		$dompdf->render();
249
250
		$dompdf->stream();
251
252
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method baixar_estoque_minimo_pdf() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
253
	}
254
255
	public function getProdutosEstoqueMinimoComoHtml($produtos) {
256
    	ob_start();
257
258
		$html = '';
259
		$html .= '<html>';
260
		$html .= '<head>';
261
		$html .= '	<title></title>';
262
		$html .= '</head>';
263
		$html .= '<body>';
264
		$html .= '';
265
		$html .= '	<table style="background-color: #cacaca;"  width="100%" valign="center" align="center">';
266
		$html .= '		<tr align="center">';
267
		$html .= '			<td>';
268
		$html .= '				<h2>Produtos com quantidade de estoque minimo</h2>';
269
		$html .= '			</td>';
270
		$html .= '		</tr> ';
271
		$html .= '	</table>';
272
		$html .= '	<br>';
273
		$html .= '	<br>';
274
		$html .= '	<table  width="100%" valign="center" align="center">';
275
		$html .= '		<tr style="background-color: #cacaca;" align="center">';
276
		$html .= '			<td>';
277
		$html .= '				<h2>Produtos</h2>';
278
		$html .= '			</td>';
279
		$html .= '		</tr> ';
280
		$html .= '	</table>';
281
		$html .= '	<br>';
282
		$html .= '	<table  width="100%" valign="center" align="center">';
283
		$html .= '		<tr>';
284
		$html .= '			<td>';
285
		$html .= '				<table width="100%" valign="center" align="center">';
286
		$html .= '					<tr style="background-color: #cacaca;">';
287
		$html .= '						<td>Nome Produto</td>';
288
		$html .= '						<td>Quantidade</td>';
289
		$html .= '						<td>Custo</td>';
290
		$html .= '					</tr>';
291
		$html .= '';
292
293
		foreach ($produtos as $i => $produto) {
294
			$html .= '					<tr>';
295
			$html .= '						<td>' . $produto['Produto']['nome'] . '</td>';
296
			$html .= '						<td>' . $produto['Produto']['estoque'] . '</td>';
297
			$html .= '						<td>R$ ' . number_format($produto['Produto']['custo'], 2, ',', '.') . '</td>';
298
			$html .= '					</tr>';
299
		}
300
301
		$html .= '				</table>';
302
		$html .= '			</td>';
303
		$html .= '		</tr>';
304
		$html .= '	</table>';
305
		$html .= '	<br>';
306
		$html .= '';
307
		$html .= '</body>';
308
		$html .= '</html>';
309
		echo $html;exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method getProdutosEstoqueMinimoComoHtml() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
310
		return $html;
0 ignored issues
show
Unused Code introduced by
return $html; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
311
	}
312
313 View Code Duplication
	public function adicionar_cadastro() {
314
		$this->loadModel('Categoria');
315
316
		$this->set('categorias', $this->Categoria->find('all', 
317
				array('conditions' => 
318
					array('ativo' => 1,
319
						  'usuario_id' => $this->instancia
320
					)
321
				)
322
			)
323
		);	
324
325
		$this->layout = 'wadmin';
326
	}
327
328
	public function s_adicionar_cadastro() {
0 ignored issues
show
Coding Style introduced by
s_adicionar_cadastro uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
329
		$dados  = $this->request->data('dados');
330
331
		$variacoes = $this->request->data('variacao');
332
333
		$image  = $_FILES['imagem'];
334
335
		$retorno = $this->uploadImage($image);
336
337
		if (!$retorno['status']) 
338
			$this->Session->setFlash('Não foi possivel salvar a imagem tente novamente');
339
340
		$dados['imagem'] = $retorno['nome'];
341
		$dados['id_usuario'] = $this->instancia;
342
		$dados['ativo'] = 1;
343
		$dados['id_alias'] = $this->id_alias();
344
		$dados['preco'] = str_replace(',', '', $dados['preco']);
345
346
		if($this->Produto->save($dados)) {
347
			$produto_id = $this->Produto->getLastInsertId();
348
			
349
			require 'VariacaoController.php';
350
351
			$objVariacaoController = new VariacaoController();
352
353
			$objVariacaoController->s_adicionar_variacao($variacoes, $produto_id, $this->instancia);			
354
355
			if ($this->verificar_modulo_ativo('pluggto'))
356
			{
357
				require 'PluggtoController.php';
358
				$objPluggTo = new PluggtoController();
359
				$produto_pluggto = $objPluggTo->enviar_produto($dados, $variacoes);
360
361
				if (!isset($produto_pluggto->Product->id)) 
362
				{
363
					$this->Session->setFlash('Produto não foi enviado para o Plugg.to!');
364
				}
365
			}
366
367
			$this->Session->setFlash('Produto salvo com sucesso!');
368
            
369
            return $this->redirect('/produto/listar_cadastros');
370
		} else {
371
			$this->Session->setFlash('Ocorreu um erro ao salva o produto!');
372
            
373
            return $this->redirect('/produto/listar_cadastros');
374
		}
375
	}
376
377
	public function editar_cadastro($id) {
378
		$this->layout = 'wadmin';
379
380
		$this->loadModel('Variacao');
381
382
		$query = array (
383
			'joins' => array(
384
			    array(
385
			        'table' => 'produtos',
386
			        'alias' => 'Produto',
387
			        'type' => 'LEFT',
388
			        'conditions' => array(
389
			            'Variacao.produto_id = Produto.id',
390
			        ),
391
			    )
392
			),
393
	        'conditions' => array('Variacao.produto_id' => $id, 'Variacao.ativo' => 1),
394
	        'fields' => array('Produto.id, Variacao.*'),
395
		);
396
397
		$variacoes = $this->set('variacoes', $this->Variacao->find('all', $query));
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $variacoes is correct as $this->set('variacoes', ...o->find('all', $query)) (which targets Controller::set()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
398
399
		$this->set('produto', $this->Produto->find('all', 
400
				array('conditions' => 
401
					array('ativo' => 1,
402
						  'id' => $id
403
					)
404
				)
405
			)[0]
406
		);
407
408
		$this->loadModel('Categoria');
409
410
		$this->set('categorias', $this->Categoria->find('all', 
411
				array('conditions' => 
412
					array('ativo' => 1,
413
						  'usuario_id' => $this->instancia
414
					)
415
				)
416
			)
417
		);	
418
	}
419
420
	public function s_editar_cadastro($id) {
0 ignored issues
show
Coding Style introduced by
s_editar_cadastro uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
421
		$dados = $this->request->data('dados');
422
423
		$variacoes = $this->request->data('variacao');
424
425
		$image  = $_FILES['imagem'];
426
		
427 View Code Duplication
		if (!empty($image['name'])) {
428
			$retorno = $this->uploadImage($image);
429
			
430
			if (!$retorno['status']) 
431
				$this->Session->setFlash('Não foi possivel salvar a imagem tente novamente');
432
			
433
			$dados['imagem'] = $retorno['nome'];
434
		}
435
436
437
		$dados['id_usuario'] = $this->instancia;
438
		$dados['ativo'] = 1;
439
		$dados['id_alias'] = $this->id_alias();
440
		$dados['preco'] = str_replace(',', '', $dados['preco']);
441
442
		$this->Produto->id = $id;
443
		
444
		if ($this->Produto->save($dados)) {
445
446
			require 'VariacaoController.php';
447
			$objVariacaoController = new VariacaoController();
448
			$objVariacaoController->desativar_variacoes($id);
449
			$objVariacaoController->s_adicionar_variacao($variacoes, $id, $this->instancia);	
450
451
			$this->Session->setFlash('Produto editado com sucesso!','default','good');
452
            return $this->redirect('/produto/listar_cadastros');
453
		} else {
454
			$this->Session->setFlash('Ocorreu um erro ao editar o produto!','default','good');
455
            return $this->redirect('/produto/listar_cadastros');
456
		}
457
	}
458
459 View Code Duplication
	public function excluir_cadastro() {
460
		$this->layout = 'ajax';
461
462
		$id = $this->request->data('id');
463
464
		$dados = array('ativo' => '0');
465
		$parametros = array('id' => $id);
466
467
		if ($this->Produto->updateAll($dados, $parametros)) {
468
			echo json_encode(true);
469
		} else {
470
			echo json_encode(false);
471
		}
472
	}
473
474
	public function id_alias() {
475
		$id_alias = $this->Produto->find('first', array(
476
				'conditions' => array('Produto.ativo' => 1),
477
				'order' => array('Produto.id' => 'desc')
478
			)
479
		);
480
481
		return $id_alias['Produto']['id_alias'] + 1;
482
	}
483
484
	public function carregar_dados_venda_ajax() {
485
		$this->layout = 'ajax';
486
487
		$retorno = $this->Produto->find('first', 
488
			array('conditions' => 
489
				array('Produto.ativo' => 1,
490
					  'Produto.id_usuario' => $this->instancia,
491
					  'Produto.id' => $this->request->data('id')
492
				)
493
			)
494
		);
495
496
		if (!$this->validar_estoque($retorno)) {
497
			return false;
498
		}
499
500
		$retorno['Produto']['total'] = $this->calcular_preco_produto_venda($retorno['Produto']['preco'], $this->request->data('qnt'));
501
502
		$retorno['Produto']['preco'] = (float) $retorno['Produto']['preco'];
503
		
504
		echo json_encode($retorno);
505
	}
506
507 View Code Duplication
	public function getUserActive($id) {
508
		$this->loadModel('Usuario');
509
510
		$user = $this->Usuario->find('all', 
511
			array('conditions' => 
512
				array('Usuario.id' => $id)
513
			)
514
		);
515
		
516
		return $user;
517
	}
518
519
	public function validar_estoque($produto) {
520
521
		$user_active = $this->getUserActive($produto['Produto']['id_usuario']);
522
523
		if ($user_active[0]['Usuario']['sale_without_stock'])
524
			return true;
525
526
		if (empty($produto) && !isset($produto)) {
527
			return false;
528
		}
529
		
530
		if ($produto['Produto']['estoque'] <= 0) {
531
			return false;
532
		}
533
534
		return true;
535
	}
536
537
	public function calcular_preco_produto_venda($preco, $qnt) {
538
		if (empty($preco) || !isset($preco)) {
539
			return false;
540
		}
541
542
		if (!is_numeric($qnt)) {
543
			return false;
544
		}
545
546
		$retorno = $preco * $qnt;
547
548
		return (float) $retorno;
549
	}
550
551
	public function uploadImage(&$image) {
552
		$type = substr($image['name'], -4);
553
		$nameImage = uniqid() . md5($image['name']) . $type;
554
		$dir = APP . 'webroot/uploads/produto/imagens/';
555
		
556
		$returnUpload = move_uploaded_file($image['tmp_name'], $dir . $nameImage);
557
558
		if (!$returnUpload)
559
			return array('nome' => null, 'status' => false);
560
561
		return array('nome' => $nameImage, 'status' => true);
562
	}
563
564
	public function visualizar_cadastro($id) {
565
		$this->layout = 'wadmin';
566
567
		$produto = $this->Produto->find('all', 
568
			array('conditions' => 
569
				array('ativo' => 1,
570
					  'id' => $id
571
				)
572
			)
573
		);
574
575
		if (empty($produto)) {
576
			$this->Session->setFlash("Produto não encotrado, tente novamente");
577
			$this->redirect("/produto/listar_cadastros");
578
		}
579
580
		$this->set('produto', $produto[0]);
581
	}
582
583
	public function exportar_excel_exemplo() {
584
		include(APP . 'Vendor/PHPExcel/PHPExcel.php');
585
		include(APP . 'Vendor/PHPExcel/PHPExcel/IOFactory.php');
586
587
        $objPHPExcel = new PHPExcel();
588
        // Definimos o estilo da fonte
589
        $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);
590
591
        $objPHPExcel->getActiveSheet()->getRowDimension('1')->setRowHeight(40);
592
593
        // Criamos as colunas
594
        $objPHPExcel->setActiveSheetIndex(0)
0 ignored issues
show
Bug introduced by
The method setCellValue does only exist in PHPExcel_Worksheet, but not in PHPExcel_Cell.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
595
                    ->setCellValue('A1', "Nome do Produto")
596
                    ->setCellValue('B1', "Preço ")
597
                    ->setCellValue("C1", "Peso Bruto")
598
                    ->setCellValue("D1", "Peso Liquido")
599
                    ->setCellValue("E1", "Estoque")
600
                    ->setCellValue("F1", "Descrição");
601
602
        // Podemos renomear o nome das planilha atual, lembrando que um único arquivo pode ter várias planilhas
603
        $objPHPExcel->getActiveSheet()->setTitle('Listagem de produtos');
604
605
        // Cabeçalho do arquivo para ele baixar
606
        header('Content-Type: application/vnd.ms-excel');
607
        header('Content-Disposition: attachment;filename="planilha_importacao_exemplo.xls"');
608
        header('Cache-Control: max-age=0');
609
        // Se for o IE9, isso talvez seja necessário
610
        header('Cache-Control: max-age=1');
611
612
        // Acessamos o 'Writer' para poder salvar o arquivo
613
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
614
615
        // Salva diretamente no output, poderíamos mudar arqui para um nome de arquivo em um diretório ,caso não quisessemos jogar na tela
616
        $objWriter->save('php://output'); 
617
618
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method exportar_excel_exemplo() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
619
    }
620
621
    public function importar_produtos_planilha() {
0 ignored issues
show
Coding Style introduced by
importar_produtos_planilha uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
622
        if (!isset($_FILES['arquivo']['tmp_name']) && empty($_FILES['arquivo']['tmp_name']))
623
        {
624
			$this->Session->setFlash("Erro ao subir a planilha, tente novamente.");
625
			$this->redirect("/produto/listar_cadastros");        	
626
        }
627
628
        $typesPermissions = ['application/vnd.ms-excel'];
629
630
        if (!in_array($_FILES['arquivo']['type'], $typesPermissions))
631
        {
632
			$this->Session->setFlash("O arquivo deve ser no formato .xls.");
633
			$this->redirect("/produto/listar_cadastros");                	
634
        }
635
636
        $caminho = APP . 'webroot/uploads/produto/planilhas/' . uniqid() . '.xls';
637
638
        $inputFileName = $_FILES['arquivo']['tmp_name'];
639
640
        move_uploaded_file($inputFileName, $caminho);
641
642
        $data = [
643
        	'caminho' => $caminho,
644
        	'usuario_id' => $this->instancia,
645
        	'processado' => 0,
646
        	'ativo' => 1
647
        ];
648
649
        $this->loadModel('QueueProduct');
650
651
        if ($this->QueueProduct->save($data))
652
        {
653
			$this->Session->setFlash("O arquivo está na fila para ser importado, iremos enviar um e-mail quando terminar.");
654
			$this->redirect("/produto/listar_cadastros");  
655
        }
656
        else 
657
        {
658
			$this->Session->setFlash("Ocorreu um erro, tente novamente.");
659
			$this->redirect("/produto/listar_cadastros");          	
660
        }
661
    }
662
663
    public function processar_planilhas_na_fila() {
664
    	$this->loadModel('QueueProduct');
665
666
    	$planilhas = $this->QueueProduct->loadPlanilhasNotProcesseds();
667
668
    	$response = [];
669
    	foreach ($planilhas as $planilha) {
670
    		$response[] = $this->processar_planilhas($planilha['caminho'], $planilha['usuario_id'], $planilha['id']);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $response[] is correct as $this->processar_planilh..._id'], $planilha['id']) (which targets ProdutoController::processar_planilhas()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
671
    	}
672
673
    	return $response;
674
    }
675
676
    public function processar_planilhas($inputFileName, $usuarioId, $planilhaId) {
677
		include(APP . 'Vendor/PHPExcel/PHPExcel.php');
678
		include(APP . 'Vendor/PHPExcel/PHPExcel/IOFactory.php');
679
    	
680
        $objPHPExcel = new PHPExcel();
681
682
		try {
683
		    $inputFileType 	= PHPExcel_IOFactory::identify($inputFileName);
684
		    $objReader 		= PHPExcel_IOFactory::createReader($inputFileType);
685
		    $objPHPExcel 	= $objReader->load($inputFileName);
686
		} catch(Exception $e) {
687
		    die('Error loading file "' . pathinfo($inputFileName, PATHINFO_BASENAME) . '": ' . $e->getMessage());
0 ignored issues
show
Coding Style Compatibility introduced by
The method processar_planilhas() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
688
		}
689
690
		$dados = [];
691
692
		$rows = $objPHPExcel->setActiveSheetIndex(0)->getHighestRow();
693
694
		for ($row = 2; $row <= $rows; $row++) {
695
			
696
			$rowInterator = $objPHPExcel->getActiveSheet()->getRowIterator($row)->current();
697
698
			$cellIterator = $rowInterator->getCellIterator();
699
			$cellIterator->setIterateOnlyExistingCells(false);
700
701
			foreach ($cellIterator as $i => $cell) {
702
				switch ($i) {
703
					case 0: //Codigo/SKU
704
						$dados[$row]['sku'] = $cell->getValue();
705
					break; 
706
					case 1: // Nome/Descrição 
707
						$dados[$row]['nome'] = $cell->getValue();						
708
					break;
709
					case 2: // QtdAtual
710
						//$dados[$row]['sku'] = $cell->getValue();						
711
					break;
712
					case 3: // QtdMinima  
713
						$dados[$row]['quantidade_minima'] = $cell->getValue();						
714
					break;
715
					case 4: // QtdTotal
716
						$dados[$row]['estoque'] = $cell->getValue();						
717
					break;
718
					case 5: // ValCusto
719
						$dados[$row]['custo'] = $cell->getValue();						
720
					break;
721
					case 6:  // ValVenda
722
						$dados[$row]['preco'] = $cell->getValue();						
723
					break;
724
				}
725
			}
726
727
			$dados[$row]['id_usuario'] = $usuarioId;	
728
			$dados[$row]['ativo'] = 1;
729
730
		}
731
732
		$errors = $this->processar_lista_produtos($dados);
733
734
		if (isset($errors) && !empty($errors))
735
		{
736
			$this->QueueProduct->planilhaProcessedIncomplete($planilhaId);
737
		}
738
739
		$this->QueueProduct->planilhaProcessedComplete($planilhaId);
740
741
		echo json_encode(array('sucess' => true));
742
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method processar_planilhas() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
743
    }
744
745
    public function processar_lista_produtos($dados) {
746
    	$errors = [];
747
748
    	foreach ($dados as $dado) {
749
    		$this->loadModel('Produto');
750
    		
751
    		$existProduto = $this->Produto->find('all',
752
    			array(
753
    				'conditions' => array(
754
    					'Produto.sku' => $dado['sku'],
755
    					'Produto.ativo' => 1
756
    				)
757
    			)
758
    		);
759
760
    		if (isset($existProduto) && !empty($existProduto))
761
    		{
762
    			$this->Produto->id = $existProduto[0]['Produto']['id'];
763
    			$this->Produto->save($dado);
764
    			continue;
765
    		}
766
767
			$this->Produto->create();
768
769
    		if (!$this->Produto->save($dado))
770
    		{
771
    			$errors[] = $dado;
772
    		}
773
    	}
774
775
    	return $errors;
776
    }
777
778
    public function movimentacoes_estoque($produtoId) {
779
    	$this->layout = 'wadmin';
780
781
    	$this->set('id', $produtoId);
782
    }
783
784
	public function listar_cadastros_estoque_ajax($produtoId) {
0 ignored issues
show
Coding Style introduced by
listar_cadastros_estoque_ajax uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
785
		$this->loadModel('VendaItensProduto');
786
787
		$this->layout = 'ajax';
788
789
		$aColumns = array( 'id', 'produto_id', 'venda_id', 'quantidade_produto' );
790
		
791
		$conditions = array(
792
			'conditions' => array(
793
				'VendaItensProduto.ativo' => 1,
794
				'VendaItensProduto.produto_id' => $produtoId
795
			),
796
			'joins' => array(
797
			    array(
798
			        'table' => 'produtos',
799
			        'alias' => 'Produto',
800
			        'type' => 'LEFT',
801
			        'conditions' => array(
802
			            'VendaItensProduto.produto_id = Produto.id',
803
			        ),
804
			    )
805
			),
806
	        'fields' => array('VendaItensProduto.*, Produto.*'),
807
		);
808
809
		$allProdutos = $this->VendaItensProduto->find('all', $conditions);
810
		
811
		if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' )
812
		{
813
			$conditions['offset'] = $_GET['iDisplayStart'];
814
			$conditions['limit'] = $_GET['iDisplayLength'];
815
		}
816
817 View Code Duplication
		if ( isset( $_GET['iSortCol_0'] ) )
818
		{
819
			for ( $i=0 ; $i < intval( $_GET['iSortingCols'] ) ; $i++ )
820
			{
821
				if ( $_GET[ 'bSortable_' . intval($_GET['iSortCol_' . $i]) ] == "true" )
822
				{
823
					$conditions['order'] = array('VendaItensProduto.' . $aColumns[intval($_GET['iSortCol_' . $i])] => $_GET['sSortDir_'.$i]);
824
				}
825
			}
826
		}
827
828 View Code Duplication
		if ( isset( $_GET['sSearch'] ) && !empty( $_GET['sSearch'] ) )
829
		{
830
			$conditions['conditions']['VendaItensProduto.id LIKE '] = '%' . $_GET['sSearch'] . '%';
831
		}
832
		
833
		$produtos = $this->VendaItensProduto->find('all', $conditions);
834
835
		$output = array(
836
			"sEcho" => intval($_GET['sEcho']),
837
			"iTotalDisplayRecords" => count($allProdutos),
838
			"iTotalRecords" => count($produtos),
839
			"aaData" => array()
840
		);
841
842
		foreach ( $produtos as $i => $produto )
843
		{
844
			$row = array();
845
846
			for ( $i=0 ; $i < count($aColumns) ; $i++ )
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
847
			{
848
				if ($aColumns[$i] == "produto_id") {
849
					$value = $produto['Produto']['nome'];
850
				} else if ($aColumns[$i] == "quantidade_produto") {
851
					$value = -$produto['VendaItensProduto'][$aColumns[$i]];
852
				} else {
853
					$value = $produto['VendaItensProduto'][$aColumns[$i]];
854
				}
855
				
856
				$row[] = $value;
857
			}
858
859
			$output['aaData'][] = $row;
860
		}
861
		
862
		echo json_encode($output);
863
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method listar_cadastros_estoque_ajax() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
864
	}
865
866
    public function salvar_imagem($id) {
0 ignored issues
show
Coding Style introduced by
salvar_imagem uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
867
		$image  = $_FILES['arquivo'];
868
		
869
		$retorno = $this->uploadImage($image);
870
871
		if (!$retorno['status']) {
872
			$this->Session->setFlash('A imagem não foi salva tente novamente ou contate o suporte!');
873
            return $this->redirect('/produto/imagens/' . $id);
874
		}
875
876
		$photo = $this->request->data('photo');
877
878
		$data = array(
879
			'arquivo' => $retorno['nome'],
880
			'order' => $photo['order'],
881
			'alt' => $photo['alt'],
882
			'title' => $photo['title'],
883
			'ativo' => 1,
884
			'usuario_id' => $this->instancia,
885
			'produto_id' => $id
886
		);
887
888
		$this->loadModel('Imagen');
889
890
		$retorno = $this->Imagen->save($data);
891
892
		if (!$retorno) {
893
			$this->Session->setFlash('A imagem não foi salva tente novamente ou contate o suporte!');
894
            return $this->redirect('/produto/imagens/' . $id);
895
		}
896
897
		$this->Session->setFlash('A salva com sucesso!');
898
        return $this->redirect('/produto/imagens/' . $id);
899
    }
900
901
    public function imagem_excluir_cadastro($id) {
902
    	$this->loadModel('Imagen');
903
904
    	$this->Imagen->id = $id;
905
906
    	$this->Imagen->save(['ativo' => 0]);
907
908
    	echo json_encode(array('success' => true));
909
    	exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method imagem_excluir_cadastro() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
910
    }
911
912
    public function produto_item()
0 ignored issues
show
Coding Style introduced by
produto_item uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
913
    {
914
		$search = strip_tags(trim($_GET['q'])); 
915
916
		$conditions['limit'] = 25;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$conditions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $conditions = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
917
		$conditions['conditions']['Produto.nome LIKE '] = '%' . $search . '%';
918
		
919
		$produtos = $this->Produto->find('all', $conditions);
920
921
		$data = [];
922
		foreach ($produtos as $produto) {
923
			$data[] = [
924
				'id' => $produto['Produto']['id'],
925
				'text' => $produto['Produto']['nome']
926
			];
927
		}
928
929
		echo json_encode($data);
930
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method produto_item() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
931
    }
932
933
}
934