Skip to content

Commit

Permalink
Merge pull request #30 from sombriks/develop
Browse files Browse the repository at this point in the history
teste de release - pagamentos e transferências
  • Loading branch information
sombriks committed Jun 9, 2024
2 parents 1904eed + 0a43507 commit 473f616
Show file tree
Hide file tree
Showing 31 changed files with 519 additions and 193 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.private.env.json
*.save
.idea
node_modules
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,23 @@ Study project - Yet another personal finance app

![jerry-maguire-show-me-the-money.gif](docs/jerry-maguire-show-me-the-money.gif)

## Project setup
## Project setup, how to run, how to test, etc

See [individual](service-node-koa/README.md) [readme's](web-app-vue/README.md)
for each project.

## Noteworthy

- It all started for fun with a [db schema](docs/redline.sql) for a personal
finance app.
- Then we added a node with koa backend to study api building, and a frontend
made with vue3, vuetify and a few other cool libraries.
- Then the project was used to study
[docker](service-node-koa/infrastructure/Dockerfile)
[containers](web-app-vue/infrastructure/Dockerfile).
- At some moment it was used to
[study kubernetes](service-node-koa/infrastructure/k8s/deployment.yml).
- And finally Continuous Delivery with GitOps, using ArgoCD to observe the
desired state for the cluster and applying it when it changes.
- There is [a few things to be done](docs/THINGS_TO_FIX.md) to proper call it a
respectable code reference, but i think it's cool.
1 change: 1 addition & 0 deletions service-node-koa/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules
.vscode
dist
coverage
.idea
20 changes: 18 additions & 2 deletions service-node-koa/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# service-node-koa

Backend part of redline finances
Backend part of redline finance

## Requirements

Expand All @@ -27,7 +27,7 @@ npm run test:service:coverage
docker build -f infrastructure/Dockerfile -t sombriks/redline-api:testing .
```

You can change the postgres database url for proper test values
You can change the postgres database url for proper test values:

```sh
docker run --rm -it -p 3000:3000 --network=host \
Expand All @@ -41,3 +41,19 @@ just for that:
```bash
docker compose -f infrastructure/test-database-docker-compose.yml up
```

## Database migrations

There are npm scripts to help on database migration:

```bash
npm run migrate:make new_script # give a proper name for the migrate
```

```bash
npm run migrate:latest # apply all pending migrates
```

```bash
npm run migrate:rollback # undo latest applied migrate batch
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @param { import('knex').Knex } knex
* @returns { Promise<void> }
*/
export const up = async (knex) =>
knex.schema.table('movimentacao', tb => {
tb.dropNullable('categoria_id')
tb.foreign('categoria_id').references('categoria.id').onDelete('cascade')
tb.boolean('interna').defaultTo(false)
.comment('indica uma movimentação entre contas')
})

/**
* @param { import('knex').Knex } knex
* @returns { Promise<void> }
*/
export const down = async (knex) =>
knex.schema.table('movimentacao', tb => {
tb.setNullable('categoria_id')
tb.dropColumn('interna')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @param { import('knex').Knex } knex
* @returns { Promise<void> }
*/
export const up = async (knex) =>
knex('modelocategoria').insert([
{ descricao: 'ESTUDO', cor: '#A0FF16' }, { descricao: 'TRANSFERENCIA', cor: '#AAEEEE' }
])

/**
* @param { import('knex').Knex } knex
* @returns { Promise<void> }
*/
export const down = async (knex) =>
knex('modelocategoria').del()
.whereIn('descricao', ['ESTUDO', 'TRANSFERENCIA'])
27 changes: 26 additions & 1 deletion service-node-koa/app/controllers/movimentacao.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
findMovimentacao,
insertMovimentacao,
listMovimentacaoByConta,
listMovimentacaoByUsuario,
listMovimentacaoByUsuario, pagamento,
removeMovimentacao, transferencia,
updateMovimentacao,
uploadMovimentacoes
Expand Down Expand Up @@ -72,12 +72,37 @@ export const downloadMovimentacoesRequest = async ctx => {
export const transferenciaRequest = async ctx => {
const { usuario_id, conta_id: conta_origem_id, conta_destino_id } = ctx.request.params
const { valor, vencimento, categoria: categoria_id } = ctx.request.body

const origem = await findConta({ id: conta_origem_id, usuario_id })
const destino = await findConta({ id: conta_destino_id, usuario_id })
const categoria = await findCategoria({ id: categoria_id, usuario_id })

if (!origem) return ctx.throw(400, 'conta origem não encontrada')
if (!destino) return ctx.throw(400, 'conta destino não encontrada')
if (!categoria) return ctx.throw(400, 'categoria não encontrada')

const result = await transferencia({ origem, destino, categoria, valor, vencimento })
ctx.body = result
}

export const pagamentoRequest = async ctx => {
const { usuario_id, conta_id, conta_destino_id } = ctx.request.params
const {
movimentacoes_id,
categoria_id,
vencimento,
valor
} = ctx.request.body

const origem = await findConta({ id: conta_id, usuario_id })
const destino = await findConta({ id: conta_destino_id, usuario_id })
const categoria = await findCategoria({ id: categoria_id, usuario_id })

if (!origem) return ctx.throw(400, 'conta origem não encontrada')
if (!destino) return ctx.throw(400, 'conta destino não encontrada')
if (!categoria) return ctx.throw(400, 'categoria não encontrada')
if (!movimentacoes_id || movimentacoes_id.length === 0) return ctx.throw(400, 'informe as movimentações a pagar')

const result = await pagamento({ origem, destino, categoria, valor, vencimento, movimentacoes_id })
ctx.body = result
}
4 changes: 4 additions & 0 deletions service-node-koa/app/controllers/movimentacao.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe("Movimentacao API test", () => {
const novaMovimentacao = {
tipo_movimentacao_id: 1,
descricao: "Teste movimentação",
categoria_id: categoria.id,
conta_id: conta.id,
valor: 100,
vencimento: "2024-02-04",
Expand All @@ -99,6 +100,7 @@ describe("Movimentacao API test", () => {
const novaMovimentacao = {
tipo_movimentacao_id: 1,
descricao: "Test movimentação",
categoria_id: categoria.id,
conta_id: conta.id,
valor: 100,
vencimento: "2024-02-04",
Expand All @@ -123,6 +125,7 @@ describe("Movimentacao API test", () => {
const novaMovimentacao = {
tipo_movimentacao_id: 1,
descricao: "Test movimentação",
categoria_id: categoria.id,
conta_id: conta.id,
valor: 100,
vencimento: "2024-02-04",
Expand Down Expand Up @@ -153,6 +156,7 @@ describe("Movimentacao API test", () => {
const novaMovimentacao = {
tipo_movimentacao_id: 1,
descricao: "Test movimentação",
categoria_id: categoria.id,
conta_id: conta.id,
valor: 100,
vencimento: "2024-02-04",
Expand Down
6 changes: 3 additions & 3 deletions service-node-koa/app/controllers/recorrencia.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
delRecorrencia,
findRecorrencia, geraLancamentos,
findRecorrencia,
geraLancamentos,
insertRecorrencia,
listRecorrencia,
updateRecorrencia
Expand Down Expand Up @@ -36,6 +37,5 @@ export const delRecorrenciaRequest = async ctx => {

export const geraLancamentosRequest = async ctx => {
const { usuario_id, id } = ctx.request.params
const result = await geraLancamentos({ usuario_id, id })
ctx.body = result
ctx.body = await geraLancamentos({ usuario_id, id })
}
101 changes: 55 additions & 46 deletions service-node-koa/app/controllers/recorrencia.spec.mjs
Original file line number Diff line number Diff line change
@@ -1,107 +1,116 @@
import chai from 'chai'
import chaiHttp from 'chai-http'

import {app} from '../main.mjs'
import { app } from '../main.mjs'
import {
findRecorrencia,
getAdmin,
insertRecorrencia,
insertRecorrencia, listCategorias,
listContas,
listMovimentacaoByConta,
resetConta
} from "../services/index.mjs";
import {sign} from "../config/security/index.mjs";
import {endOfYear, startOfYear} from "date-fns";
} from '../services/index.mjs'
import { sign } from '../config/security/index.mjs'
import { endOfYear, startOfYear } from 'date-fns'

chai.should();
chai.use(chaiHttp);
chai.should()
chai.use(chaiHttp)

describe("Recorrencia API requests", () => {
describe('Recorrencia API requests', () => {

let user;
let authorization;
let conta;
let user
let authorization
let conta
let categoria

before(async () => {
user = await getAdmin()
await resetConta({usuario_id: user.id})
const {token} = sign(user)
await resetConta({ usuario_id: user.id })
const { token } = sign(user)
authorization = `Bearer ${token}`
conta = (await listContas({usuario_id: user.id}))[0]
conta = (await listContas({ usuario_id: user.id }))[0]
categoria = (await listCategorias({ usuario_id: user.id }))[0]
})

it("Should list recorrencias", async () => {
it('Should list recorrencias', async () => {
try {
const res = await chai
.request(app.callback())
.get(`/${user.id}/recorrencia`)
.set("Authorization", authorization)
res.should.have.status(200);
res.body.should.be.an("array");
.set('Authorization', authorization)
res.should.have.status(200)
res.body.should.be.an('array')
} catch (e) {
chai.expect.fail(e)
}
})

it("Should insert recorrencia", async () => {
const novaRecorrencia = {tipo_recorrencia_id: 1, conta_id: conta.id, descricao: "nova", valorParcela: 100.50}
it('Should insert recorrencia', async () => {
const novaRecorrencia = {
tipo_recorrencia_id: 1,
conta_id: conta.id,
categoria_id: categoria.id,
descricao: 'nova',
valorParcela: 100.50
}
const res = await chai
.request(app.callback())
.post(`/${user.id}/recorrencia`)
.send(novaRecorrencia)
.set("Authorization", authorization)
res.should.have.status(200);
res.body.should.be.an("array"); // [{id:1}]
.set('Authorization', authorization)
res.should.have.status(200)
res.body.should.be.an('array') // [{id:1}]
})

it("Should find recorrencia", async () => {
const [{id}] = await insertRecorrencia({
recorrencia: {tipo_recorrencia_id: 1, conta_id: conta.id, descricao: "nova", valorParcela: 100.50}
it('Should find recorrencia', async () => {
const [{ id }] = await insertRecorrencia({
recorrencia: { tipo_recorrencia_id: 1, conta_id: conta.id, descricao: 'nova', valorParcela: 100.50 }
})
const res = await chai
.request(app.callback())
.get(`/${user.id}/recorrencia/${id}`)
.set("Authorization", authorization)
res.should.have.status(200);
res.body.should.be.an("object");
.set('Authorization', authorization)
res.should.have.status(200)
res.body.should.be.an('object')
res.body.id.should.be.eq(id)
})

it("Should update recorrencia", async () => {
const [{id}] = await insertRecorrencia({
recorrencia: {tipo_recorrencia_id: 1, conta_id: conta.id, descricao: "nova", valorParcela: 100.50}
it('Should update recorrencia', async () => {
const [{ id }] = await insertRecorrencia({
recorrencia: { tipo_recorrencia_id: 1, conta_id: conta.id, descricao: 'nova', valorParcela: 100.50 }
})
const res = await chai
.request(app.callback())
.put(`/${user.id}/recorrencia/${id}`)
.set("Authorization", authorization)
.send({descricao: "atualizada"})
.set('Authorization', authorization)
.send({ descricao: 'atualizada' })
res.should.have.status(200)
res.body.should.be.ok
const recorrencia = await findRecorrencia({id})
recorrencia.descricao.should.be.eq("atualizada")
const recorrencia = await findRecorrencia({ id })
recorrencia.descricao.should.be.eq('atualizada')
})

it("should delete recorrencia", async () => {
const [{id}] = await insertRecorrencia({
recorrencia: {tipo_recorrencia_id: 1, conta_id: conta.id, descricao: "nova", valorParcela: 100.50}
it('should delete recorrencia', async () => {
const [{ id }] = await insertRecorrencia({
recorrencia: { tipo_recorrencia_id: 1, conta_id: conta.id, descricao: 'nova', valorParcela: 100.50 }
})
const res = await chai
.request(app.callback())
.del(`/${user.id}/recorrencia/${id}`)
.set("Authorization", authorization)
.set('Authorization', authorization)
res.should.have.status(200)
res.body.should.be.ok
const recorrencia = await findRecorrencia({id})
const recorrencia = await findRecorrencia({ id })
chai.expect(recorrencia).to.be.undefined
})

it("should check generated parcels", async () => {
const [{id}] = await insertRecorrencia({
it('should check generated parcels', async () => {
const [{ id }] = await insertRecorrencia({
recorrencia: {
tipo_recorrencia_id: 1,
conta_id: conta.id,
descricao: "ver parcelas",
categoria_id: categoria.id,
descricao: 'ver parcelas',
valorParcela: 100.50,
inicial: startOfYear(new Date()),
final: endOfYear(new Date())
Expand All @@ -111,11 +120,11 @@ describe("Recorrencia API requests", () => {
const res = await chai
.request(app.callback())
.get(`/${user.id}/recorrencia/${id}/lancamentos`)
.set("Authorization", authorization)
.set('Authorization', authorization)
res.should.have.status(200)
res.body.should.be.ok

const parcelas = await listMovimentacaoByConta({conta_id: conta.id})
const parcelas = await listMovimentacaoByConta({ conta_id: conta.id })
parcelas.should.be.ok
parcelas.should.be.an('array')
parcelas.length.should.be.eq(12)
Expand Down
3 changes: 2 additions & 1 deletion service-node-koa/app/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
listContasRequest,
listMovimentacaoRequest,
listPlanejamentoRequest,
listRecorrenciaRequest,
listRecorrenciaRequest, pagamentoRequest,
removeMovimentacaoRequest, transferenciaRequest,
updateCategoriaRequest,
updateContaRequest,
Expand Down Expand Up @@ -83,6 +83,7 @@ new ApiBuilder({ router }).path(b => {
b.path('/:conta_id', contaOwnedBy, b => {
b.post(insertMovimentacaoRequest)
b.post('/transferir/:conta_destino_id', transferenciaRequest)
b.post('/pagar/:conta_destino_id', pagamentoRequest)
b.path('/:id', b => {
b.get(findMovimentacaoRequest)
b.put(updateMovimentacaoRequest)
Expand Down
Loading

0 comments on commit 473f616

Please sign in to comment.