+ */
+ public $robots = [
+ 'googlebot' => 'Googlebot',
+ 'msnbot' => 'MSNBot',
+ 'baiduspider' => 'Baiduspider',
+ 'bingbot' => 'Bing',
+ 'slurp' => 'Inktomi Slurp',
+ 'yahoo' => 'Yahoo',
+ 'ask jeeves' => 'Ask Jeeves',
+ 'fastcrawler' => 'FastCrawler',
+ 'infoseek' => 'InfoSeek Robot 1.0',
+ 'lycos' => 'Lycos',
+ 'yandex' => 'YandexBot',
+ 'mediapartners-google' => 'MediaPartners Google',
+ 'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
+ 'adsbot-google' => 'AdsBot Google',
+ 'feedfetcher-google' => 'Feedfetcher Google',
+ 'curious george' => 'Curious George',
+ 'ia_archiver' => 'Alexa Crawler',
+ 'MJ12bot' => 'Majestic-12',
+ 'Uptimebot' => 'Uptimebot',
+ ];
+}
diff --git a/algoritmos/Desafio 1/Config/Validation.php b/algoritmos/Desafio 1/Config/Validation.php
new file mode 100644
index 0000000..a254c18
--- /dev/null
+++ b/algoritmos/Desafio 1/Config/Validation.php
@@ -0,0 +1,44 @@
+
+ */
+ public $templates = [
+ 'list' => 'CodeIgniter\Validation\Views\list',
+ 'single' => 'CodeIgniter\Validation\Views\single',
+ ];
+
+ //--------------------------------------------------------------------
+ // Rules
+ //--------------------------------------------------------------------
+}
diff --git a/algoritmos/Desafio 1/Config/View.php b/algoritmos/Desafio 1/Config/View.php
new file mode 100644
index 0000000..78cd547
--- /dev/null
+++ b/algoritmos/Desafio 1/Config/View.php
@@ -0,0 +1,56 @@
+[]
+ */
+ public array $decorators = [];
+}
diff --git a/algoritmos/Desafio 1/Controllers/BaseController.php b/algoritmos/Desafio 1/Controllers/BaseController.php
new file mode 100644
index 0000000..122db5f
--- /dev/null
+++ b/algoritmos/Desafio 1/Controllers/BaseController.php
@@ -0,0 +1,52 @@
+session = \Config\Services::session();
+ }
+}
diff --git a/algoritmos/Desafio 1/Controllers/Home.php b/algoritmos/Desafio 1/Controllers/Home.php
new file mode 100644
index 0000000..2c32ee3
--- /dev/null
+++ b/algoritmos/Desafio 1/Controllers/Home.php
@@ -0,0 +1,34 @@
+vendaModel = new \App\Models\VendaModel();
+ $this->vendaItemModel = new \App\Models\VendaItemModel();
+ $this->itemModel = new \App\Models\ItemModel();
+ }
+
+ /*
+ public function index()
+ {
+ return view('welcome_message');
+ }
+ */
+
+ public function index()
+ {
+
+ $data = [
+ 'titulo' => 'Home',
+ ];
+
+ return view('Home/index', $data);
+ }
+}
diff --git a/algoritmos/Desafio 1/Controllers/Itens.php b/algoritmos/Desafio 1/Controllers/Itens.php
new file mode 100644
index 0000000..fc7335d
--- /dev/null
+++ b/algoritmos/Desafio 1/Controllers/Itens.php
@@ -0,0 +1,261 @@
+itemModel = new \App\Models\ItemModel();
+ }
+
+ public function index()
+ {
+ $data = [
+
+ 'titulo' => 'Listando os itens do sistema',
+ ];
+
+ return view("Itens/index", $data);
+ }
+
+ public function exibir(int $id = null)
+ {
+
+ $item = $this->buscaItemOu404($id);
+
+ $data = [
+
+ 'titulo' => 'Detalhando o item ' . $item->nome,
+ 'item' => $item,
+ ];
+
+ return view("Itens/exibir", $data);
+ }
+
+ public function criar(int $id = null)
+ {
+ helper(['form', 'url']);
+
+ $item = new Item();
+
+ $data = [
+
+ 'titulo' => 'Cadastrando novo produto ',
+ 'item' => $item,
+ ];
+
+ return view("Itens/criar", $data);
+ }
+
+ public function cadastrar()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ $item = new Item($post);
+
+ $item->fill($post);
+
+ $precoVenda = str_replace([',', '.'], '', $item->valor_unitario);
+
+ if ($precoVenda < 0) {
+
+ $retorno['erro'] = 'Verifique os erros abaixo e tente novamente!';
+ $retorno['erros_model'] = ['itens' => 'O preço de venda não pode ser menor que o zero!'];
+
+ return $this->response->setJSON($retorno);
+ }
+
+ if ($this->itemModel->save($item)) {
+
+ $btnCriar = anchor("Itens/criar", 'Cadastrar novo item', ['class' => 'btn btn-danger mt-2']);
+
+ session()->setFlashdata('sucesso', "Dados salvos com sucesso!
$btnCriar");
+
+ $retorno['id'] = $this->itemModel->getInsertID();
+ //flash data
+ return $this->response->setJSON($retorno);
+ }
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->itemModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ public function editar(int $id = null)
+ {
+ helper(['form', 'url']);
+
+ $item = $this->buscaItemOu404($id);
+
+ $data = [
+
+ 'titulo' => 'Editando o item ' . $item->nome,
+ 'item' => $item,
+ ];
+
+ return view("Itens/editar", $data);
+ }
+
+ public function atualizar()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ $item = $this->buscaItemOu404($post['id']);
+
+ $item->fill($post);
+
+ if ($item->hasChanged() === false) {
+
+ $retorno['info'] = 'Não há dados para atualizar';
+
+ return $this->response->setJSON($retorno);
+ }
+
+ $precoVenda = str_replace([',', '.'], '', $item->valor_unitario);
+
+ if ($precoVenda < 0) {
+
+ $retorno['erro'] = 'Verifique os erros abaixo e tente novamente!';
+ $retorno['erros_model'] = ['itens' => 'O preço de venda não pode ser menor que o zero!'];
+
+ return $this->response->setJSON($retorno);
+ }
+
+ if ($this->itemModel->save($item)) {
+
+ session()->setFlashdata('sucesso', 'Dados salvos com sucesso!');
+
+ //flash data
+ return $this->response->setJSON($retorno);
+ }
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->itemModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ public function recuperaItens()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ $atributos = [
+ 'id',
+ 'nome',
+ 'valor_unitario',
+ 'deletado_em',
+ ];
+
+ $itens = $this->itemModel->select($atributos)
+ ->orderBy('id', 'DESC')
+ ->findAll();
+
+ $data = [];
+
+ foreach ($itens as $item) {
+
+ $nomeItem = esc($item->nome);
+
+ $data[] = [
+
+ 'nome' => anchor("Itens/exibir/$item->id", esc($item->nome), 'title="Exibir ' . $nomeItem . '"'),
+ 'valor_unitario' => 'R$ ' . $item->valor_unitario,
+ ];
+ }
+
+ $retorno = [
+
+ 'data' => $data,
+ ];
+
+ return $this->response->setJSON($retorno);
+ }
+
+ public function excluir(int $id = null)
+ {
+ helper(['form', 'url']);
+
+ $item = $this->buscaItemOu404($id);
+
+ if ($item->deletado_em != null) {
+
+ return redirect()->back()->with('info', "Item $item->nome já encotra-se excluido.");
+ }
+
+ if ($this->request->getMethod() === 'post') {
+
+ $this->itemModel->delete($item->id);
+
+ return redirect()->to(site_url("itens"))->with('sucesso', "Item $item->nome excluido com sucesso.");
+ }
+
+ $data = [
+
+ 'titulo' => 'Excluindo item ' . $item->nome,
+ 'item' => $item,
+ ];
+
+ return view('Itens/excluir', $data);
+ }
+
+ public function restauraritem(int $id = null)
+ {
+
+ $item = $this->buscaitemOu404($id);
+
+ if ($item->deletado_em == null) {
+ return redirect()->back()->with('info', "Esse item encontra-se ativo, impossivel restaura-lo");
+ }
+
+ $item->deletado_em = null;
+ $this->itemModel->protect(false)->save($item);
+
+ return redirect()->back()->with('sucesso', "item $item->nome restaurado com sucesso!");
+ }
+
+// ----------------------------------- buscas ---------------------------
+
+ private function buscaItemOu404(int $id = null)
+ {
+
+ if (!$id || !$item = $this->itemModel->withDeleted(true)->find($id)) {
+
+ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound("Não encontramos o item $id");
+ }
+
+ return $item;
+ }
+}
diff --git a/algoritmos/Desafio 1/Controllers/Vendas.php b/algoritmos/Desafio 1/Controllers/Vendas.php
new file mode 100644
index 0000000..38e0765
--- /dev/null
+++ b/algoritmos/Desafio 1/Controllers/Vendas.php
@@ -0,0 +1,269 @@
+vendaModel = new \App\Models\VendaModel();
+ }
+
+ public function index()
+ {
+ $data = [
+ 'titulo' => 'Listando as vendas',
+ ];
+
+ return view('Vendas/index', $data);
+ }
+
+ public function recuperaVendas()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ $vendas = $this->vendaModel->recuperaVendas();
+
+ //receberá o array de objetos de vendas
+ $data = [];
+
+ foreach ($vendas as $venda) {
+
+ $data[] = [
+ 'codigo' => anchor("Vendas/detalhes/$venda->id", esc($venda->id), 'title="Exibir ' . esc($venda->id) . '"'),
+ 'nome' => esc($venda->nome),
+ 'criado_em' => date('d/m/Y',strtotime($venda->criado_em)),
+ ];
+ }
+
+ $retorno = [
+ 'data' => $data,
+ ];
+
+ //echo '';
+ //print_r($retorno);
+ //exit;
+
+ return $this->response->setJSON($retorno);
+ }
+
+ public function criar()
+ {
+ helper(['form', 'url']);
+
+ $venda = new Venda();
+
+ $data = [
+ 'titulo' => 'Cadastrando nova venda',
+ 'venda' => $venda,
+ ];
+
+ return view('Vendas/criar', $data);
+ }
+
+ public function cadastrar()
+ {
+ helper(['form', 'url']);
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ $venda = new Venda($post);
+
+ if ($this->vendaModel->save($venda)) {
+
+ session()->setFlashdata('sucesso', 'Dados salvos com sucesso!');
+
+ $retorno['id'] = $this->vendaModel->getInsertID();
+ //flash data
+ return $this->response->setJSON($retorno);
+ }
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->vendaModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ public function detalhes(string $id = null)
+ {
+ helper(['form', 'url']);
+
+ $venda = $this->vendaModel->buscaVendaOu404($id);
+
+ $this->preparaItensDaVenda($venda);
+
+ $data = [
+ 'titulo' => "Detalhando a venda código: $venda->id",
+ 'venda' => $venda,
+ ];
+
+ return view('Vendas/detalhes', $data);
+ }
+
+ public function editar(string $id = null)
+ {
+ helper(['form', 'url']);
+
+ $venda = $this->vendaModel->buscaVendaOu404($id);
+
+ $data = [
+ 'titulo' => "Editando a venda código: $venda->id",
+ 'venda' => $venda,
+ ];
+
+ return view('Vendas/editar', $data);
+ }
+
+ public function atualizar()
+ {
+ helper(['form', 'url']);
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ //validamos a existência da venda
+ $venda = $this->vendaModel->buscaVendaOu404($post['id']);
+
+ $venda->fill($post);
+
+ if ($venda->hasChanged() === false) {
+
+ $retorno['info'] = 'Não há dados para serem atualizados';
+ return $this->response->setJSON($retorno);
+ }
+
+ if ($this->vendaModel->save($venda)) {
+
+ session()->setFlashdata('sucesso', 'Dados salvos!');
+
+ $retorno['redirect'] = "Vendas/index";
+
+ //flash data
+ return $this->response->setJSON($retorno);
+ }
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->vendaModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ public function excluir(string $codigo = null)
+ {
+ helper(['form', 'url']);
+
+ $venda = $this->vendaModel->buscaVendaOu404($codigo);
+
+ if ($venda->deletado_em != null) {
+
+ return redirect()->back()->with("info", "A venda código: $venda->id já encontra-se excluída");
+ }
+
+ if ($this->request->getMethod() === 'post') {
+
+ $this->vendaModel->delete($venda->id);
+
+ return redirect()->to(site_url("vendas"))->with("sucesso", "venda código: $venda->id, excluída com sucesso!");
+ }
+
+ $data = [
+ 'titulo' => "Excluíndo a venda código: $venda->id",
+ 'venda' => $venda,
+ ];
+
+ return view('Vendas/excluir', $data);
+ }
+
+ public function encerrar(string $codigo = null)
+ {
+ helper(['form', 'url']);
+
+ $venda = $this->vendaModel->buscavendaOu404($codigo);
+
+ if ($venda->situacao !== 'aberta') {
+
+ return redirect()->back()->with('atencao', 'Apenas vendas em aberto podem ser encerradas.');
+ }
+
+ $this->preparaItensDavenda($venda);
+
+ $data = [
+ 'titulo' => "Encerrar a venda código: $venda->id",
+ 'venda' => $venda,
+ ];
+
+ return view("vendas/encerrar", $data);
+ }
+
+ public function processaEncerramento(string $id = null)
+ {
+ helper(['form', 'url']);
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ $venda = $this->vendaModel->buscavendaOu404($id);
+
+ $this->preparaItensDavenda($venda);
+
+ //outros pagamentos
+ $this->preparavendaParaEncerrar($venda);
+
+ $venda->situacao = 'encerrada';
+
+ if ($this->vendaModel->save($venda)) {
+
+ session()->setFlashdata('sucesso', 'A venda foi encerrada!');
+
+ //descerializa, pois a view envia serializada
+ if ($venda->itens !== null) {
+
+ $venda->itens = unserialize($venda->itens);
+ }
+
+ $retorno['redirect'] = "Vendas/index";
+
+ return $this->response->setJSON($retorno);
+ }
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->vendaModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+}
diff --git a/algoritmos/Desafio 1/Controllers/VendasItens.php b/algoritmos/Desafio 1/Controllers/VendasItens.php
new file mode 100644
index 0000000..e453e04
--- /dev/null
+++ b/algoritmos/Desafio 1/Controllers/VendasItens.php
@@ -0,0 +1,334 @@
+vendaModel = new \App\Models\VendaModel();
+ $this->vendaItemModel = new \App\Models\VendaItemModel();
+ $this->itemModel = new \App\Models\ItemModel();
+ }
+
+ public function itens(string $id = null)
+ {
+
+ $venda = $this->vendaModel->buscaVendaOu404($id);
+
+ $this->preparaItensDaVenda($venda);
+
+ $data = [
+ 'titulo' => "Gerenciando os itens da venda $venda->id",
+ 'venda' => $venda,
+ ];
+
+ return view('Vendas/itens', $data);
+ }
+
+ public function pesquisaItens()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ $term = $this->request->getGet('term');
+
+ $itens = $this->itemModel->pesquisaItens($term);
+
+ $retorno = [];
+
+ foreach ($itens as $item) {
+
+ $data['id'] = $item->id;
+ $data['item_preco'] = number_format($item->valor_unitario, 2);
+
+ $data['value'] = "[ Código $item->id ] $item->nome ";
+
+ $data['label'] = ''. $data['value'] . '';
+
+ $retorno[] = $data;
+ }
+
+ return $this->response->setJSON($retorno);
+ }
+
+ public function adicionarItem()
+ {
+
+ if (!$this->request->isAJAX()) {
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ $validacao = service('validation');
+
+ $regras = [
+ 'item_id' => 'required',
+ 'item_quantidade' => 'required|greater_than[0]',
+ ];
+
+ $mensagens = [ // Errors
+ 'item_id' => [
+ 'required' => 'É necessario escolher um item válido!',
+ ],
+ 'item_quantidade' => [
+ 'required' => 'É necessario escolher uma quantidade!',
+ 'greater_than' => 'A quantidade precisa ser maior que 0!',
+ ],
+ ];
+
+ $validacao->setRules($regras, $mensagens);
+
+ if ($validacao->withRequest($this->request)->run() === false) {
+
+ //retornamos os erros de validação
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $validacao->getErrors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ //echo '';
+ //print_r($post);
+ //exit;
+
+ //se venda existe
+ $venda = $this->vendaModel->buscaVendaOu404($post['id']);
+
+ //se item existe
+ $item = $this->buscaItemOu404($post['item_id']);
+
+ if ($this->verificaSeVendaPossuiItem($venda->id, $item->id)) {
+
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = ['estoque' => 'Essa venda já possui este produto, não é possível inserir!'];
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ $vendaItem = [
+ 'venda_id' => (int) $venda->id,
+ 'item_id' => (int) $item->id,
+ 'item_quantidade' => (int) $post['item_quantidade'],
+ ];
+
+ if ($this->vendaItemModel->insert($vendaItem)) {
+
+ session()->setFlashdata('sucesso', "$item->nome adicionado à venda com sucesso!");
+
+ return $this->response->setJSON($retorno);
+ }
+
+ $retorno['erro'] = 'Por favor verifique os erros de validação e tente novamente!';
+ $retorno['erros_model'] = $this->vendaItemModel->errors();
+
+ //retorno para o ajax request
+ return $this->response->setJSON($retorno);
+ }
+
+ public function atualizarQuantidade(string $codigo = null)
+ {
+
+ if ($this->request->getMethod() !== 'post') {
+
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ $validacao = service('validation');
+
+ $regras = [
+ 'item_id' => 'required',
+ 'item_quantidade' => 'required|greater_than[0]',
+ 'id_principal' => 'required|greater_than[0]', //pk table ordens-itens
+ ];
+
+ $mensagens = [ // Errors
+ 'item_id' => [
+ 'required' => 'É necessario escolher um item válido!',
+ ],
+ 'item_quantidade' => [
+ 'required' => 'É necessario escolher uma quantidade!',
+ 'greater_than' => 'A quantidade precisa ser maior que 0!',
+ ],
+ 'id_principal' => [
+ 'required' => 'Não foi possível atualizar o item!',
+ 'greater_than' => 'O id do item precisa ser maior que 0!',
+ ],
+ ];
+
+ $validacao->setRules($regras, $mensagens);
+
+ if ($validacao->withRequest($this->request)->run() === false) {
+
+
+ return redirect()->back()->with('atencao', 'Por favor verifique os erros de validação e tente novamente!')
+ ->with('erros_model', $validacao->getErrors());
+ }
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ //echo '';
+ //print_r($post);
+ //exit;
+
+ //se venda existe
+ $venda = $this->vendaModel->buscaVendaOu404($codigo);
+
+ //se item existe
+ $item = $this->buscaItemOu404($post['item_id']);
+
+ $vendaItem = $this->buscaVendaItemOu404($post['id_principal'], $venda->id);
+
+ if ($item->tipo === 'produto' && $post['item_quantidade'] > $item->estoque) {
+
+ return redirect()->back()->with('atencao', 'Por favor verifique os erros de validação e tente novamente!')
+ ->with('erros_model', ['estoque' => 'Quantidade é maior que a disponível em estoque, não é possível adicionar!']);
+ }
+
+ if($post['item_quantidade'] === $vendaItem->item_quantidade){
+
+ return redirect()->back()->with('info', 'Informe uma quantidade diferente da atual!');
+
+ }
+
+ //aqui já passou por todas as verificações, então pode alterar na tabela
+ $vendaItem->item_quantidade = $post['item_quantidade'];
+
+ if($this->vendaItemModel->atualizaQuantidadeItem($vendaItem)){
+
+ return redirect()->back()->with('sucesso', 'Quantidade atualizada com sucesso!');
+
+ }
+
+ return redirect()->back()->with('atencao', 'Por favor verifique os erros de validação e tente novamente!')
+ ->with('erros_model', $this->vendaItemModel->errors());
+
+ }
+
+ public function removerItem(string $codigo = null)
+ {
+
+ if ($this->request->getMethod() !== 'post') {
+
+ return redirect()->back();
+ }
+
+ //envio o hash do token do form
+ $retorno['token'] = csrf_hash();
+
+ $validacao = service('validation');
+
+ $regras = [
+ 'item_id' => 'required',
+ 'id_principal' => 'required|greater_than[0]', //pk table ordens-itens
+ ];
+
+ $mensagens = [ // Errors
+ 'item_id' => [
+ 'required' => 'É necessario escolher um item válido para exclusão!',
+ ],
+ 'id_principal' => [
+ 'required' => 'Não foi possível remover o item!',
+ 'greater_than' => 'Não foi possível remover o item!',
+ ],
+ ];
+
+ $validacao->setRules($regras, $mensagens);
+
+ if ($validacao->withRequest($this->request)->run() === false) {
+
+
+ return redirect()->back()->with('atencao', 'Por favor verifique os erros de validação e tente novamente!')
+ ->with('erros_model', $validacao->getErrors());
+ }
+
+ //recupera o post da requisição
+ $post = $this->request->getPost();
+
+ //echo '';
+ //print_r($post);
+ //exit;
+
+ //se venda existe
+ $venda = $this->vendaModel->buscaVendaOu404($codigo);
+
+ //se item existe
+ $item = $this->buscaItemOu404($post['item_id']);
+
+ $vendaItem = $this->buscaVendaItemOu404($post['id_principal'], $venda->id);
+
+ //aqui já passou por todas as verificações, então pode alterar na tabela
+
+ if($this->vendaItemModel->delete($vendaItem->id)){
+
+ return redirect()->back()->with('sucesso', 'Item removido com sucesso!');
+
+ }
+
+ return redirect()->back()->with('atencao', 'Por favor verifique os erros de validação e tente novamente!')
+ ->with('erros_model', $this->vendaItemModel->errors());
+
+ }
+
+ private function buscaItemOu404(int $id = null)
+ {
+
+ if (!$id || !$item = $this->itemModel->withDeleted(true)->find($id)) {
+
+ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound("Não encontramos o item $id");
+ }
+
+ return $item;
+ }
+
+ //id principal do item
+ private function buscaVendaItemOu404(int $id_principal = null, int $venda_id)
+ {
+
+ if (!$id_principal || !$vendaItem = $this->vendaItemModel
+ ->where('id', $id_principal)
+ ->where('venda_id', $venda_id)
+ ->first()) {
+
+ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound("Não encontramos o registro principal $id_principal");
+ }
+
+ return $vendaItem;
+ }
+
+ private function verificaSeVendaPossuiItem(int $venda_id, int $item_id): bool
+ {
+
+ $possuiItem = $this->vendaItemModel->where('venda_id', $venda_id)->where('item_id', $item_id)->first();
+
+ if ($possuiItem === null) {
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/algoritmos/Desafio 1/Database/Migrations/2022-06-12-143952_GeraTabelaItens.php b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-143952_GeraTabelaItens.php
new file mode 100644
index 0000000..aa70c54
--- /dev/null
+++ b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-143952_GeraTabelaItens.php
@@ -0,0 +1,53 @@
+forge->addField([
+ 'id' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ 'unsigned' => true,
+ 'auto_increment' => true,
+ ],
+ 'nome' => [
+ 'type' => 'VARCHAR',
+ 'constraint' => '240',
+ 'unique' => true,
+ ],
+ 'valor_unitario' => [
+ 'type' => 'DECIMAL',
+ 'constraint' => '10,2',
+ 'null' => false,
+ ],
+ 'criado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ 'atualizado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ 'deletado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ ]);
+ $this->forge->addKey('id', true);
+
+ $this->forge->createTable('itens');
+ }
+
+ public function down()
+ {
+ $this->forge->dropTable('itens');
+ }
+}
diff --git a/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144512_GeraTabelaVendas.php b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144512_GeraTabelaVendas.php
new file mode 100644
index 0000000..3d1626c
--- /dev/null
+++ b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144512_GeraTabelaVendas.php
@@ -0,0 +1,72 @@
+forge->addField([
+ 'id' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ 'unsigned' => true,
+ 'auto_increment' => true,
+ ],
+ 'nome' => [
+ 'type' => 'VARCHAR',
+ 'constraint' => '240',
+ 'unique' => true,
+ ],
+ 'itens' => [
+ 'type' => 'TEXT', //serializa os itens da venda
+ 'null' => true,
+ ],
+ 'situacao' => [
+ 'type' => 'ENUM',
+ 'constraint' => ['aberta', 'encerrada'],
+ 'default' => 'aberta',
+ ],
+ 'valor_produtos' => [
+ 'type' => 'DECIMAL',
+ 'constraint' => '10,2',
+ 'null' => true,
+ ],
+ 'valor_desconto' => [
+ 'type' => 'DECIMAL',
+ 'constraint' => '10,2',
+ 'null' => true,
+ ],
+ 'valor_venda' => [
+ 'type' => 'DECIMAL',
+ 'constraint' => '10,2',
+ 'null' => true,
+ ],
+ 'criado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ 'atualizado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ 'deletado_em' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ 'default' => null,
+ ],
+ ]);
+ $this->forge->addKey('id', true);
+
+ $this->forge->createTable('vendas');
+ }
+
+ public function down()
+ {
+ $this->forge->dropTable('vendas');
+ }
+}
diff --git a/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144523_GeraTabelaItensVendas.php b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144523_GeraTabelaItensVendas.php
new file mode 100644
index 0000000..0de3b53
--- /dev/null
+++ b/algoritmos/Desafio 1/Database/Migrations/2022-06-12-144523_GeraTabelaItensVendas.php
@@ -0,0 +1,47 @@
+forge->addField([
+ 'id' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ 'unsigned' => true,
+ 'auto_increment' => true,
+ ],
+ 'venda_id' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ 'unsigned' => true,
+ 'null' => true,
+ ],
+ 'item_id' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ 'unsigned' => true,
+ ],
+ 'item_quantidade' => [
+ 'type' => 'INT',
+ 'constraint' => 5,
+ ],
+
+ ]);
+ $this->forge->addKey('id', true);
+
+ $this->forge->addForeignKey('venda_id', 'vendas', 'id', 'CASCADE', 'CASCADE');
+ $this->forge->addForeignKey('item_id', 'itens', 'id', 'CASCADE', 'CASCADE');
+
+ $this->forge->createTable('vendas_itens');
+ }
+
+ public function down()
+ {
+ $this->forge->dropTable('vendas_itens');
+ }
+}
diff --git a/algoritmos/Desafio 1/Entities/Item.php b/algoritmos/Desafio 1/Entities/Item.php
new file mode 100644
index 0000000..4a1b8b9
--- /dev/null
+++ b/algoritmos/Desafio 1/Entities/Item.php
@@ -0,0 +1,12 @@
+ 'required|max_length[120]',
+ 'valor_unitario' => 'required',
+ ];
+ protected $validationMessages = [
+ 'nome' => [
+ 'required' => 'O campo nome é obrigatório',
+ 'max_length' => 'O campo nome é muito longo, máximo de 120 caracteres',
+ ],
+ 'valor_unitario' => [
+ 'required' => 'O campo Preço de venda é obrigatório',
+ ],
+ ];
+
+ // Callbacks
+ protected $beforeInsert = ['removeVirgulaValores'];
+ protected $beforeUpdate = ['removeVirgulaValores'];
+
+ protected function removeVirgulaValores(array $data)
+ {
+ if (isset($data['data']['valor_unitario'])) {
+
+ $data['data']['valor_unitario'] = str_replace(',', '', $data['data']['valor_unitario']);
+ }
+
+ return $data;
+ }
+
+ public function pesquisaItens(string $term = null): array
+ {
+
+ if ($term === null) {
+
+ return [];
+ }
+
+ $atributos = [
+ 'itens.*'
+ ];
+
+ $itens = $this->select($atributos)
+ ->like('nome', $term)
+ ->where('deletado_em', null)
+ ->groupBy('nome')
+ ->findAll();
+
+ if ($itens === null) {
+
+ return [];
+ }
+
+ return $itens;
+ }
+}
diff --git a/algoritmos/Desafio 1/Models/VendaItemModel.php b/algoritmos/Desafio 1/Models/VendaItemModel.php
new file mode 100644
index 0000000..ccb107b
--- /dev/null
+++ b/algoritmos/Desafio 1/Models/VendaItemModel.php
@@ -0,0 +1,42 @@
+select($atributos)
+ ->join('itens', 'itens.id = vendas_itens.item_id')
+ ->where('vendas_itens.venda_id', $venda_id)
+ ->groupBy('itens.nome')
+ ->findAll();
+ }
+
+ public function atualizaQuantidadeItem(object $vendaItem){
+
+ return $this->set('item_quantidade', $vendaItem->item_quantidade)
+ ->where('id', $vendaItem->id)
+ ->update();
+ }
+}
diff --git a/algoritmos/Desafio 1/Models/VendaModel.php b/algoritmos/Desafio 1/Models/VendaModel.php
new file mode 100644
index 0000000..ab934e1
--- /dev/null
+++ b/algoritmos/Desafio 1/Models/VendaModel.php
@@ -0,0 +1,75 @@
+ 'required',
+ ];
+ protected $validationMessages = [
+ 'nome' => [
+ 'required' => 'O campo Nome é obrigatório',
+ ],
+ ];
+
+ public function recuperaVendas(){
+
+ $atributos = [
+ 'id',
+ 'nome',
+ 'situacao',
+ 'valor_venda',
+ 'criado_em',
+ 'deletado_em'
+ ];
+
+ return $this->select($atributos)->orderBy('id', 'DESC')->withDeleted(true)->findAll();
+ }
+
+ public function buscaVendaOu404(string $codigo = null){
+
+ if($codigo === null){
+
+ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound("Não encontramos a venda $codigo");
+ }
+
+ $atributos = [
+ 'vendas.*',
+ ];
+
+ $venda = $this->select($atributos)
+ ->where('id', $codigo)
+ ->withDeleted(true)
+ ->first();
+
+ if($venda === null){
+
+ throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound("Não encontramos a venda $codigo");
+ }
+
+ return $venda;
+
+ }
+}
diff --git a/algoritmos/Desafio 1/Traits/VendaTrait.php b/algoritmos/Desafio 1/Traits/VendaTrait.php
new file mode 100644
index 0000000..907c25b
--- /dev/null
+++ b/algoritmos/Desafio 1/Traits/VendaTrait.php
@@ -0,0 +1,89 @@
+recuperaItensDaVenda($venda->id);
+
+ $venda->itens = (!empty($vendaItens) ? $vendaItens : null);
+
+ return $venda;
+
+ //aqui a venda não está em aberto, encerrada com pagamento
+ if($venda->itens !== null){
+
+ $venda->itens = unserialize($venda->itens);
+ }
+
+ //retorna venda
+ return $venda;
+ }
+
+ public function preparaVendaParaEncerrar(object $venda): object {
+
+ $venda->situacao = 'encerrada';
+
+ if($venda->itens === null){
+
+ //venda vazia
+
+ $venda->valor_produtos = null;
+ $venda->valor_desconto = null;
+ $venda->valor_venda = null;
+
+ return $venda;
+ }
+
+ $valorProdutos = null;
+ $auxquantidade = 0;
+ $auxvalor = 0;
+
+ $produtos = [];
+
+ foreach($venda->itens as $item){
+
+ $valorProdutos += $item->valor_unitario * $item->item_quantidade;
+
+ $auxquantidade++;
+
+ array_push($produtos, [
+ 'id' => $item->id,
+ 'quantidade' => (int) $item->item_quantidade,
+ ]);
+ }
+
+ if($auxquantidade >= 10 && $auxquantidade < 20){
+ $auxvalor = $valorProdutos * 0.05;
+
+ }else if($auxquantidade >=20 && $auxquantidade < 30){
+ $auxvalor = $valorProdutos * 0.1;
+
+ }else if($auxquantidade >= 30){
+ $auxvalor = $valorProdutos * 0.2;
+ }
+
+ $venda->valor_desconto = $auxvalor;
+
+ if(!empty($produtos)){
+
+ $venda->produtos = $produtos;
+ }
+
+ $venda->valor_produtos = str_replace(',', '', number_format($valorProdutos, 2));
+
+ $valorFinalvenda = number_format(($valorProdutos) - $venda->valor_desconto, 2);
+
+ //valor final da venda, formatado e unido com desconto
+ $venda->valor_venda = str_replace(',', '', $valorFinalvenda);
+
+ //serializamos os itens
+ $venda->itens = serialize($venda->itens);
+
+ return $venda;
+ }
+}
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Home/index.php b/algoritmos/Desafio 1/Views/Home/index.php
new file mode 100644
index 0000000..429058f
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Home/index.php
@@ -0,0 +1,29 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/_form.php b/algoritmos/Desafio 1/Views/Itens/_form.php
new file mode 100644
index 0000000..6fa833f
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/_form.php
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ * Campos Obrigatórios.
+
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/criar.php b/algoritmos/Desafio 1/Views/Itens/criar.php
new file mode 100644
index 0000000..7ae64e7
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/criar.php
@@ -0,0 +1,156 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'form'], ['id' => "$item->id"]) ?>
+
+ include('Itens/_form'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/editar.php b/algoritmos/Desafio 1/Views/Itens/editar.php
new file mode 100644
index 0000000..a3753f0
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/editar.php
@@ -0,0 +1,144 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'form'], ['id' => "$item->id"]) ?>
+
+ include('Itens/_form'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+
+tipo === 'serviço') : ?>
+
+
+
+
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/excluir.php b/algoritmos/Desafio 1/Views/Itens/excluir.php
new file mode 100644
index 0000000..406fa99
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/excluir.php
@@ -0,0 +1,61 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+
+
+
+
+
+
+
+ id") ?>
+
+
+ Tem certeza que deseja excluir?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/exibir.php b/algoritmos/Desafio 1/Views/Itens/exibir.php
new file mode 100644
index 0000000..a63a180
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/exibir.php
@@ -0,0 +1,63 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Itens/index.php b/algoritmos/Desafio 1/Views/Itens/index.php
new file mode 100644
index 0000000..191c08d
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Itens/index.php
@@ -0,0 +1,116 @@
+extend('Layouts/principal'); ?>
+
+
+
+section('titulo') ?>endSection() ?>
+
+
+
+section('estilos') ?>
+
+
+
+
+
+endSection() ?>
+
+
+
+section('conteudo') ?>
+
+
+
+
+
+
+
+
+
+
+
+ Nome |
+ Preço de venda(R$) |
+
+
+
+
+
+
+
+
+
+endSection() ?>
+
+
+
+section('scripts') ?>
+
+
+
+
+
+
+
+endSection() ?>
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Layouts/_mensagens.php b/algoritmos/Desafio 1/Views/Layouts/_mensagens.php
new file mode 100644
index 0000000..b46aa3e
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Layouts/_mensagens.php
@@ -0,0 +1,52 @@
+has('sucesso')) : ?>
+
+
+ Sucesso!
+
+
+
+
+has('info')) : ?>
+
+
+ Informação!
+
+
+
+
+has('atencao')) : ?>
+
+
+ Atenção!
+
+
+
+
+
+has('erros_model')) : ?>
+
+
+
+
+
+has('error')) : ?>
+
+
+ Erro!
+
+
+
\ No newline at end of file
diff --git a/algoritmos/Desafio 1/Views/Layouts/principal.php b/algoritmos/Desafio 1/Views/Layouts/principal.php
new file mode 100644
index 0000000..6858bd6
--- /dev/null
+++ b/algoritmos/Desafio 1/Views/Layouts/principal.php
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ Vendas | renderSection('titulo'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ renderSection('estilos'); ?>
+
+
+
+
+