13.5 - Aplicativo Finanças Pessoais
Cada um de nós tem um fogo no coração para alguma coisa. É nossa meta na vida encontrá-lo e mantê-lo aceso. (Mary Lou Retton)
Este aplicativo tem como objetivo principal efetuar operações entre os elementos do MVC (Controller, Model e View) para um simplificada aplicação de controle de receitas e despesas pessoais.
Procurarei simplificar outras operações, focando apenas na codificação.
Versão com CakePHP 3.6.1
- Criar um Aplicativo com o CakePHP 3.6.1
- Para gerenciamento de finanças pessoais.
- Apenas com as tabelas despesas e receitas
Importante: este código customizado funciona apenas no CakePHP 3.6 ou superior
Criando behaviors para executar o código da camada de negócios nos models
Criando components para executar o código da camada de negócios nos controllers
- Criar o aplicativo
cd /var/www/html
composer create-project --prefer-dist cakephp/app financas
- Criar o banco de dados
Usaremos como SGBD o MySQL
Criar o banco financas contendo:
CREATE TABLE `despesas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`descricao` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`valor` int(11) DEFAULT NULL,
`mes` char(8) COLLATE utf8_unicode_ci DEFAULT NULL,
`created` date DEFAULT NULL,
`modified` date DEFAULT NULL,
`receita_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `despesas` (`id`, `descricao`, `valor`, `mes`, `created`, `modified`, `receita_id`) VALUES
(1, 'Mercantil', 500, '05/2017', '2017-05-11', '2017-05-15', 1),
(2, 'Condomínio', 100, '05/2017', '2017-05-11', '2017-05-15', 1),
(3, 'Teste', 300, '06/2017', '2017-05-11', '2017-05-11', 2);
CREATE TABLE `receitas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`descricao` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`mes` char(7) COLLATE utf8_unicode_ci DEFAULT NULL,
`valor` int(11) DEFAULT NULL,
`created` date DEFAULT NULL,
`modified` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `receitas` (`id`, `descricao`, `mes`, `valor`, `created`, `modified`) VALUES
(1, 'Salário', '05/2017', 3000, '2017-05-11', '2017-05-15'),
(2, 'Extra', '05/2017', 100, '2017-05-11', '2017-05-15');
Observe acima que o mês é tipo texto para que seja inserido algo com mes/ano
- Configurar o banco de dados em config/app.php
e o
config/routes.php para Despesas/index
Gerar o código dos dois CRUDs com o Bake
cd /var/www/html/financas
bin/cake bake all despesas
bin/cake bake all receitas
Veja pelo navegador
http://localhost/financas
Já temos um CRUD básico para as despesas e para as receitas
Mas o importante de um aplicativo deste tipo são o código personalidado, chamado de lógica de negócio, que é por exemplo somar todas as despesas de um mês e subtrair as receitas do mês do total de despesas. Isso o CakePHP não faz e precisamos fazer. Também precisamos criar código nos tempaltes adicionando um formulário
Agora a parte interessante
O código da camada de negócios
Observe que o mês tem um formato próprio, texto sendo dia/ano (dd/aaaa).
Vamos criar uma função em DespesasTable.php, que retorne a soma das despesas do mês:
Adicionar ao início:
use Cake\ORM\TableRegistry;
Adicionar:
public function despesasMes($mes){
$despesas = TableRegistry::get('Despesas')->find();
$res = $despesas->select(['total_sum' =>$despesas->func()->sum('Despesas.valor')])
->where(['Despesas.mes' => $mes])->first();
$total = $res->total_sum;
return $total;
}
Criar duas funções no DespesasController.php, que retornem o resultado das funções acima:
Adicionar ao início do DespesasController
use Cake\ORM\TableRegistry;
Mais abaixo
public function despesasMes()
{
$mes = $this->request->data('mes');
$despesas = TableRegistry::get('Despesas');
$total = $despesas->despesasMes($mes);
$this->set('total',$total);
$this->set('mes',$mes);
}
public function saldoMes()
{
$mes = $this->request->data('mes');
$this->LoadModel('Receitas');
$receitas = $this->Receitas->receitaMes($mes);
$despesas = TableRegistry::get('Despesas');
$total = $despesas->despesasMes($mes);
$saldo = $receitas - $total;
$this->set('saldo',$saldo);
$this->set('mes',$mes);
}
Agora criaremos uma função no ReceitasTable.php, que retorne a soma das receitas do mês:
Adicionar ao início:
use Cake\ORM\TableRegistry;
Mais abaixo:
public function receitaMes($mes){
$receitas = TableRegistry::get('Receitas')->find();
$res = $receitas->select(['total_sum' =>$receitas->func()->sum('Receitas.valor')])
->where(['Receitas.mes' => $mes])
->first(); //perform the sum operation
$total = $res->total_sum;
return $total;
}
Veja que existe grande semelhança entre esta e a das despesas.
Vamos customizar a src/Template/Despesas e criar duas views novas:
src/Template/Despesas/despesas_mes.ctp:
<?php ?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<h3><?= __('Despesas') ?></h3>
<?php
print '<b>Mês: </b>'.$mes. '<br><b>Total: </b>'. $total;
?>
<br>
<br>
<br>
<li><?= $this->Html->link(__('Voltar'), ['action' => 'index']) ?></li>
</nav>
src/Template/Despesas/saldo_mes.ctp:
<?php ?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<h3><?= __('Despesas') ?></h3>
<?php
print '<b>Mês: </b>'.$mes. '<br><b>Saldol: </b>'. $saldo;
?>
<br>
<br>
<br>
<li><?= $this->Html->link(__('Voltar'), ['action' => 'index']) ?></li>
</nav>
Agora vejamos a customização do index.ctp
Logo abaixo da linha:
<li><?= $this->Html->link(__('New Receita'), ['controller' => 'Receitas', 'action' => 'add']) ?></li>
Adicione os dois pequenos forms:
<b>Despesas de um mês</b>
<?php
echo $this->Form->create("Despesas",['url'=>'/despesas/despesas_mes']);
echo $this->Form->input('mes');
echo $this->Form->button('Submit');
echo $this->Form->end();
?>
<b>Saldo de um mês</b>
<?php
echo $this->Form->create("Saldo",['url'=>'/despesas/saldo_mes']);
echo $this->Form->input('mes');
echo $this->Form->button('Submit');
echo $this->Form->end();
?>
Depois de pronto podemos efetuar as operações através dos pequenos forms.
- O form chama o action do controller
- O controller chama o model para que devolva o resultado de uma função
- Recebendo o resultado o controller devolve para a view/template respectiva
Testando
Agora acesse pela web
http://localhost/financas
Pesquise o total das despesas do mês de 05/2017 ou outro que você tenha cadastrado.
Pesquise qual o saldo de um mês
Isso dá para começar a mexer no código e ir em frente.
Fluxo das informações
- O usuário acessa o aplicativo pela URL:
http://localhost/financas
- Então ele cai em (pela configuração do routes):
http://localhost/financas/despesas/index
- Na view Despesas/index.ctp ele consulta a despesa total de um certo mês pelo formulário Despesas de um mês
- Este form o direciona para o action DespesasController/despesasMes() através do comando do form: $this->Form->create("Despesas",['url'=>'/despesas/despesas_mes'])
- O controller então registra o DespesasTable e chama através do seu método despesasMes() para saber o total das despesas do referido mês
- O DespesasTable, através do seu método despesasMes() prepara uma consulta e a envia ao banco de dados.
- O banco de dados retorna o resultado para o método despesasMes() do DespesasTable.
- O método do DespesasTable retorna o valor para o DespesasController, em seu método despesasMes()
- O método despesasMes() do DespesasController envia através do método set() o mês e o total de despesas do referido mês para a view com o mesmo nome dele, que é a Despesas/despesas_mes.ctp
- Finalmente o usuário é redirecionado para a view despesas_mes.ctp onde recebe o resultado de sua consulta
http://localhost/financas/despesas/despesas_mes
Comments fornecido por CComment