Skip to content

Commit b92aee5

Browse files
feat: filtrar emprestimos por usuario autenticado
1 parent a862faf commit b92aee5

5 files changed

Lines changed: 187 additions & 188 deletions

File tree

src/backend/Emprestimos.API/Controllers/EmprestimosController.cs

Lines changed: 144 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,55 @@
22
using MongoDB.Driver;
33
using MongoDB.Bson;
44
using Emprestimos.API.Models;
5+
using Microsoft.AspNetCore.Authorization;
56

67
namespace Emprestimos.API.Controllers;
78

9+
[Authorize]
810
[ApiController]
911
[Route("api/[controller]")]
1012
public class EmprestimosController : ControllerBase
1113
{
1214
private readonly IMongoCollection<Emprestimo> _emprestimos;
1315
private readonly IMongoDatabase _db;
1416

15-
// Construtor único unificado
1617
public EmprestimosController(IMongoDatabase database)
1718
{
1819
_db = database;
1920
_emprestimos = database.GetCollection<Emprestimo>("emprestimos");
2021
}
2122

22-
[HttpGet("{id:int}/{nomeCobrador}")]
23-
public async Task<ActionResult<Emprestimo>> Get(int id, string nomeCobrador)
24-
{
23+
[HttpGet("{id:int}")]
24+
public async Task<ActionResult<Emprestimo>> Get(int id)
25+
{
26+
var cobrador = User.Identity?.Name;
2527
var emprestimo = await _emprestimos
26-
.Find(x => x.Id == id && x.Cobrador == nomeCobrador)
28+
.Find(x => x.Id == id && x.Cobrador == cobrador)
2729
.FirstOrDefaultAsync();
28-
30+
2931
if (emprestimo is null)
30-
return NotFound(new { mensagem = $"Empréstimo {id} não encontrado para o cobrador {nomeCobrador}." });
32+
return NotFound(new { mensagem = $"Empréstimo {id} não encontrado." });
3133

3234
return Ok(emprestimo);
3335
}
3436

35-
[HttpGet("carteira/{nomeCobrador}")]
36-
public async Task<ActionResult<IEnumerable<Emprestimo>>> GetCarteira(string nomeCobrador)
37+
[HttpGet("carteira")]
38+
public async Task<ActionResult<IEnumerable<Emprestimo>>> GetCarteira()
3739
{
40+
var cobrador = User.Identity?.Name;
3841
var lista = await _emprestimos
39-
.Find(x => x.Cobrador == nomeCobrador && !x.Pago)
42+
.Find(x => x.Cobrador == cobrador && !x.Pago)
4043
.SortBy(x => x.DataVencimento)
4144
.ToListAsync();
4245

4346
return Ok(lista);
4447
}
4548

46-
[HttpGet("relatorio-lucro/{nomeCobrador}")]
47-
public async Task<IActionResult> GetRelatorioLucro(string nomeCobrador)
49+
[HttpGet("relatorio-lucro")]
50+
public async Task<IActionResult> GetRelatorioLucro()
4851
{
49-
var emprestimos = await _emprestimos.Find(x => x.Cobrador == nomeCobrador).ToListAsync();
52+
var cobrador = User.Identity?.Name;
53+
var emprestimos = await _emprestimos.Find(x => x.Cobrador == cobrador).ToListAsync();
5054

5155
var totalInvestido = emprestimos.Sum(x => x.Valor);
5256
var totalAReceberGeral = emprestimos.Sum(x => x.ValorFinal);
@@ -61,7 +65,7 @@ public async Task<IActionResult> GetRelatorioLucro(string nomeCobrador)
6165
});
6266

6367
return Ok(new {
64-
Cobrador = nomeCobrador,
68+
Cobrador = cobrador,
6569
ResumoGeral = new {
6670
InvestimentoTotal = totalInvestido,
6771
RecebimentoTotalGeral = totalAReceberGeral,
@@ -71,169 +75,165 @@ public async Task<IActionResult> GetRelatorioLucro(string nomeCobrador)
7175
});
7276
}
7377

74-
[HttpPost]
75-
public async Task<IActionResult> Post(Emprestimo novo)
76-
{
77-
var ultimoEmprestimo = await _emprestimos.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
78-
novo.Id = (ultimoEmprestimo == null) ? 1 : ultimoEmprestimo.Id + 1;
78+
[HttpPost]
79+
public async Task<IActionResult> Post(Emprestimo novo)
80+
{
81+
novo.Cobrador = User.Identity?.Name ?? novo.Cobrador;
7982

80-
if (novo.TaxaJuros > 1) novo.TaxaJuros = novo.TaxaJuros / 100;
81-
if (novo.TaxaJuros == 0) novo.TaxaJuros = 0.30m;
83+
var ultimoEmprestimo = await _emprestimos.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
84+
novo.Id = (ultimoEmprestimo == null) ? 1 : ultimoEmprestimo.Id + 1;
8285

83-
if (novo.NumeroParcelas <= 0) novo.NumeroParcelas = 1;
86+
if (novo.TaxaJuros > 1) novo.TaxaJuros = novo.TaxaJuros / 100;
87+
if (novo.TaxaJuros == 0) novo.TaxaJuros = 0.30m;
8488

85-
// Juros simples: ValorFinal = Valor * (1 + TaxaJuros)
86-
novo.ValorFinal = novo.Valor * (1 + novo.TaxaJuros);
87-
novo.ValorParcela = Math.Round(novo.ValorFinal / novo.NumeroParcelas, 2);
89+
if (novo.NumeroParcelas <= 0) novo.NumeroParcelas = 1;
8890

89-
novo.DataEmprestimo = DateTime.UtcNow;
91+
novo.ValorFinal = novo.Valor * (1 + novo.TaxaJuros);
92+
novo.ValorParcela = Math.Round(novo.ValorFinal / novo.NumeroParcelas, 2);
93+
novo.DataEmprestimo = DateTime.UtcNow;
9094

91-
// Se não informou primeiro vencimento, assume 30 dias
92-
if (novo.DataVencimento == default)
93-
novo.DataVencimento = DateTime.UtcNow.AddDays(30);
95+
if (novo.DataVencimento == default)
96+
novo.DataVencimento = DateTime.UtcNow.AddDays(30);
9497

95-
// Gera as parcelas a cada 30 dias a partir do primeiro vencimento
96-
novo.Parcelas = new List<Parcela>();
97-
for (int i = 0; i < novo.NumeroParcelas; i++)
98-
{
99-
novo.Parcelas.Add(new Parcela
98+
novo.Parcelas = new List<Parcela>();
99+
for (int i = 0; i < novo.NumeroParcelas; i++)
100100
{
101-
Numero = i + 1,
102-
Valor = novo.ValorParcela,
103-
DataVencimento = novo.DataVencimento.AddDays(30 * i),
104-
Pago = false
105-
});
106-
}
101+
novo.Parcelas.Add(new Parcela
102+
{
103+
Numero = i + 1,
104+
Valor = novo.ValorParcela,
105+
DataVencimento = novo.DataVencimento.AddDays(30 * i),
106+
Pago = false
107+
});
108+
}
107109

108-
novo.Pago = false;
110+
novo.Pago = false;
109111

110-
await _emprestimos.InsertOneAsync(novo);
112+
await _emprestimos.InsertOneAsync(novo);
111113

112-
// NOTIFICAÇÃO ÚNICA DE NOVO EMPRÉSTIMO
113-
var colNotificacoes = _db.GetCollection<Notificacao>("notificacoes");
114-
var ultima = await colNotificacoes.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
114+
var colNotificacoes = _db.GetCollection<Notificacao>("notificacoes");
115+
var ultima = await colNotificacoes.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
115116

116-
var mensagem = novo.NumeroParcelas == 1
117-
? $"Novo empréstimo criado para {novo.Cliente} — vence em {novo.DataVencimento:dd/MM/yyyy}"
118-
: $"Novo empréstimo criado para {novo.Cliente}{novo.NumeroParcelas}x de {novo.ValorParcela:C}, primeiro vencimento em {novo.DataVencimento:dd/MM/yyyy}";
117+
var mensagem = novo.NumeroParcelas == 1
118+
? $"Novo empréstimo criado para {novo.Cliente} — vence em {novo.DataVencimento:dd/MM/yyyy}"
119+
: $"Novo empréstimo criado para {novo.Cliente}{novo.NumeroParcelas}x de {novo.ValorParcela:C}, primeiro vencimento em {novo.DataVencimento:dd/MM/yyyy}";
119120

120-
var novaNotif = new Notificacao
121-
{
122-
Id = (ultima == null) ? 1 : ultima.Id + 1,
123-
ClienteId = novo.ClienteId,
124-
ClienteNome = novo.Cliente,
125-
Cobrador = novo.Cobrador,
126-
Valor = novo.ValorFinal,
127-
DataVencimento = novo.DataVencimento,
128-
Tipo = "Cobrança",
129-
DataCriacao = DateTime.UtcNow,
130-
Lida = false,
131-
Mensagem = mensagem
132-
};
133-
134-
await colNotificacoes.InsertOneAsync(novaNotif);
121+
var novaNotif = new Notificacao
122+
{
123+
Id = (ultima == null) ? 1 : ultima.Id + 1,
124+
ClienteId = novo.ClienteId,
125+
ClienteNome = novo.Cliente,
126+
Cobrador = novo.Cobrador,
127+
Valor = novo.ValorFinal,
128+
DataVencimento = novo.DataVencimento,
129+
Tipo = "Cobrança",
130+
DataCriacao = DateTime.UtcNow,
131+
Lida = false,
132+
Mensagem = mensagem
133+
};
134+
135+
await colNotificacoes.InsertOneAsync(novaNotif);
135136
await EnviarPushAsync(novo.Cobrador, "Novo Empréstimo", mensagem);
136137

137-
return CreatedAtAction(nameof(Get), new { id = novo.Id, nomeCobrador = novo.Cobrador }, novo);
138-
}
139-
[HttpPatch("{id:int}/pagar/{nomeCobrador}")]
140-
public async Task<IActionResult> MarcarComoPago(int id, string nomeCobrador)
141-
{
142-
var emprestimo = await _emprestimos
143-
.Find(x => x.Id == id && x.Cobrador == nomeCobrador)
144-
.FirstOrDefaultAsync();
138+
return CreatedAtAction(nameof(Get), new { id = novo.Id }, novo);
139+
}
145140

146-
if (emprestimo is null)
147-
return NotFound(new { mensagem = "Empréstimo não encontrado." });
141+
[HttpPatch("{id:int}/pagar")]
142+
public async Task<IActionResult> MarcarComoPago(int id)
143+
{
144+
var cobrador = User.Identity?.Name;
148145

149-
// Encontra a próxima parcela pendente
150-
var parcelaPendente = emprestimo.Parcelas
151-
.Where(p => !p.Pago)
152-
.OrderBy(p => p.Numero)
153-
.FirstOrDefault();
146+
var emprestimo = await _emprestimos
147+
.Find(x => x.Id == id && x.Cobrador == cobrador)
148+
.FirstOrDefaultAsync();
154149

155-
if (parcelaPendente != null)
156-
{
157-
parcelaPendente.Pago = true;
158-
parcelaPendente.DataPagamento = DateTime.UtcNow;
159-
}
150+
if (emprestimo is null)
151+
return NotFound(new { mensagem = "Empréstimo não encontrado." });
160152

161-
// Verifica se todas as parcelas foram pagas
162-
bool todasPagas = emprestimo.Parcelas.All(p => p.Pago);
153+
var parcelaPendente = emprestimo.Parcelas
154+
.Where(p => !p.Pago)
155+
.OrderBy(p => p.Numero)
156+
.FirstOrDefault();
163157

164-
var filter = Builders<Emprestimo>.Filter.And(
165-
Builders<Emprestimo>.Filter.Eq(x => x.Id, id),
166-
Builders<Emprestimo>.Filter.Eq(x => x.Cobrador, nomeCobrador)
167-
);
158+
if (parcelaPendente != null)
159+
{
160+
parcelaPendente.Pago = true;
161+
parcelaPendente.DataPagamento = DateTime.UtcNow;
162+
}
168163

169-
var update = Builders<Emprestimo>.Update
170-
.Set(x => x.Parcelas, emprestimo.Parcelas)
171-
.Set(x => x.Pago, todasPagas)
172-
.Set(x => x.Status, todasPagas ? StatusPagamento.Pago : StatusPagamento.Pendente)
173-
.Set(x => x.DataPagamento, todasPagas ? DateTime.UtcNow : (DateTime?)null);
164+
bool todasPagas = emprestimo.Parcelas.All(p => p.Pago);
174165

175-
var emprestimoAtualizado = await _emprestimos.FindOneAndUpdateAsync(
176-
filter,
177-
update,
178-
new FindOneAndUpdateOptions<Emprestimo> { ReturnDocument = ReturnDocument.After }
179-
);
166+
var filter = Builders<Emprestimo>.Filter.And(
167+
Builders<Emprestimo>.Filter.Eq(x => x.Id, id),
168+
Builders<Emprestimo>.Filter.Eq(x => x.Cobrador, cobrador)
169+
);
180170

181-
if (emprestimoAtualizado is null)
182-
return NotFound(new { mensagem = "Empréstimo não encontrado." });
171+
var update = Builders<Emprestimo>.Update
172+
.Set(x => x.Parcelas, emprestimo.Parcelas)
173+
.Set(x => x.Pago, todasPagas)
174+
.Set(x => x.Status, todasPagas ? StatusPagamento.Pago : StatusPagamento.Pendente)
175+
.Set(x => x.DataPagamento, todasPagas ? DateTime.UtcNow : (DateTime?)null);
183176

184-
// NOTIFICAÇÃO DE PAGAMENTO
185-
var colNotificacoes = _db.GetCollection<Notificacao>("notificacoes");
186-
var ultima = await colNotificacoes.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
177+
var emprestimoAtualizado = await _emprestimos.FindOneAndUpdateAsync(
178+
filter,
179+
update,
180+
new FindOneAndUpdateOptions<Emprestimo> { ReturnDocument = ReturnDocument.After }
181+
);
187182

188-
var parcelasPagas = emprestimoAtualizado.Parcelas.Count(p => p.Pago);
189-
var totalParcelas = emprestimoAtualizado.NumeroParcelas;
183+
if (emprestimoAtualizado is null)
184+
return NotFound(new { mensagem = "Empréstimo não encontrado." });
190185

191-
var mensagem = todasPagas
192-
? $"💰 RECEBIDO: {emprestimoAtualizado.Cliente} quitou o empréstimo!"
193-
: $"💰 RECEBIDO: {emprestimoAtualizado.Cliente} pagou parcela {parcelasPagas}/{totalParcelas}{emprestimoAtualizado.ValorParcela:C}";
186+
var colNotificacoes = _db.GetCollection<Notificacao>("notificacoes");
187+
var ultima = await colNotificacoes.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
194188

195-
var notificacaoPagamento = new Notificacao
196-
{
197-
Id = (ultima == null) ? 1 : ultima.Id + 1,
198-
ClienteId = emprestimoAtualizado.ClienteId,
199-
ClienteNome = emprestimoAtualizado.Cliente,
200-
Cobrador = nomeCobrador,
201-
Valor = emprestimoAtualizado.ValorParcela,
202-
Tipo = "Pagamento",
203-
Data = DateTime.UtcNow,
204-
Lida = false,
205-
Mensagem = mensagem,
206-
NumeroParcela = parcelasPagas,
207-
TotalParcelas = totalParcelas
208-
};
209-
210-
211-
await colNotificacoes.InsertOneAsync(notificacaoPagamento);
212-
await EnviarPushAsync(nomeCobrador, "Pagamento Recebido", mensagem);
189+
var parcelasPagas = emprestimoAtualizado.Parcelas.Count(p => p.Pago);
190+
var totalParcelas = emprestimoAtualizado.NumeroParcelas;
213191

214-
var parcelasPendentes = emprestimoAtualizado.Parcelas.Count(p => !p.Pago);
215-
var saldoPendente = parcelasPendentes * emprestimoAtualizado.ValorParcela;
192+
var mensagem = todasPagas
193+
? $"💰 RECEBIDO: {emprestimoAtualizado.Cliente} quitou o empréstimo!"
194+
: $"💰 RECEBIDO: {emprestimoAtualizado.Cliente} pagou parcela {parcelasPagas}/{totalParcelas}{emprestimoAtualizado.ValorParcela:C}";
216195

217-
return Ok(new
218-
{
219-
mensagem = todasPagas ? "Empréstimo quitado!" : $"Parcela {parcelasPagas}/{totalParcelas} registrada.",
220-
parcelasPagas,
221-
parcelasPendentes,
222-
saldoPendente,
223-
dados = emprestimoAtualizado
224-
});
225-
}
196+
var notificacaoPagamento = new Notificacao
197+
{
198+
Id = (ultima == null) ? 1 : ultima.Id + 1,
199+
ClienteId = emprestimoAtualizado.ClienteId,
200+
ClienteNome = emprestimoAtualizado.Cliente,
201+
Cobrador = cobrador,
202+
Valor = emprestimoAtualizado.ValorParcela,
203+
Tipo = "Pagamento",
204+
Data = DateTime.UtcNow,
205+
Lida = false,
206+
Mensagem = mensagem,
207+
NumeroParcela = parcelasPagas,
208+
TotalParcelas = totalParcelas
209+
};
210+
211+
await colNotificacoes.InsertOneAsync(notificacaoPagamento);
212+
await EnviarPushAsync(cobrador, "Pagamento Recebido", mensagem);
213+
214+
var parcelasPendentes = emprestimoAtualizado.Parcelas.Count(p => !p.Pago);
215+
var saldoPendente = parcelasPendentes * emprestimoAtualizado.ValorParcela;
226216

217+
return Ok(new
218+
{
219+
mensagem = todasPagas ? "Empréstimo quitado!" : $"Parcela {parcelasPagas}/{totalParcelas} registrada.",
220+
parcelasPagas,
221+
parcelasPendentes,
222+
saldoPendente,
223+
dados = emprestimoAtualizado
224+
});
225+
}
227226

228-
[HttpDelete("{id:int}/{nomeCobrador}")]
229-
public async Task<IActionResult> Delete(int id, string nomeCobrador)
227+
[HttpDelete("{id:int}")]
228+
public async Task<IActionResult> Delete(int id)
230229
{
231-
var result = await _emprestimos.DeleteOneAsync(x => x.Id == id && x.Cobrador == nomeCobrador);
230+
var cobrador = User.Identity?.Name;
231+
var result = await _emprestimos.DeleteOneAsync(x => x.Id == id && x.Cobrador == cobrador);
232232
if (result.DeletedCount == 0) return NotFound();
233233
return NoContent();
234234
}
235235

236-
private async Task EnviarPushAsync(string cobrador, string titulo, string mensagem)
236+
private async Task EnviarPushAsync(string? cobrador, string titulo, string mensagem)
237237
{
238238
try
239239
{
@@ -293,7 +293,7 @@ public async Task<IActionResult> VerificarAtrasos()
293293

294294
var mensagem = emp.NumeroParcelas == 1
295295
? $"⚠️ ATRASO: {emp.Cliente} está {diasAtraso} dia(s) em atraso — {emp.ValorFinal:C}"
296-
: $"⚠️ ATRASO: {emp.Cliente} — parcela {parcela.Numero}/{emp.NumeroParcelas} ({parcela.Valor:C}) está {diasAtraso} dia(s) em atraso";
296+
: $"⚠️ ATRASO: {emp.Cliente} — parcela {emp.NumeroParcelas}/{emp.NumeroParcelas} ({parcela.Valor:C}) está {diasAtraso} dia(s) em atraso";
297297

298298
var ultima = await colNotificacoes.Find(_ => true).SortByDescending(x => x.Id).FirstOrDefaultAsync();
299299

@@ -335,5 +335,4 @@ public async Task<IActionResult> VerificarAtrasos()
335335

336336
return Ok(new { mensagem = $"{count} notificações de atraso enviadas." });
337337
}
338-
339-
}
338+
}
-65 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)